All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/16] linux: generalize sections, ranges and linker tables
@ 2016-08-19 21:32 ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This v4 addresses feedback from the previous v3 series [0], and also
addresses a huge array of additional tests against many architectures
outside of what 0-day provides. As I mentioned in my last v3 series,
0-day had only found one issue with the series, a blackfin architecture
linker issue with the last series. Guenter Rock was kind enough to give
my series a test spin on his test bed and he found quite a bit of other
oddball issues with obscure architectures, and even on x86 with an old
toolchain. After a lot of work and coordinating with a few maintainers
I'm happy to report all issues found so far through all possible testing
I could do are now fixed, this series also addresses all feedback from
the last series, as such this goes submitted as PATCH form.

In addressing fixing this work on a few architectures some of the previous
patches are further simplified. The kprobes port to linker tables is made
much easier now that I've addressed moving out core kprobe declarations
into asm-generic/kprobes.h. Refer to the patch "kprobes: move kprobe
declarations to asm-generic/kprobes.h". This makes for a much cleaner
solution across architectures.

Boris feedback on making the code bit rot feature optional is addressed
by using a new Kconfig symbol for this, CONFIG_BUILD_AVOID_BITROT,
but given Greg's concerns over lack of clarity over what this was all about
I've ripped that functionality out into its own patch with a bit more
extensive documentation and re-wording. See the patch "kbuild: enable option
to force compile force-obj-y and force-lib-y". I hope makes it clear how
linker tables can help with avoiding code bit rot. I've gone with a new
Kconfig symbol CONFIG_BUILD_AVOID_BITROT given CONFIG_COMPILE_TEST is
not available on UML, this feature is desirable on all architectures.

The documentation is revamped, now that the DocBook format is deprecated
I ported the documention into the trendy hipster Sphinx documentation
format.

AT Boris' request I've adapated the userspace linker table application
forintegration into the kernel under tools/ to make it easier to keep
things in sync, however since this requires a bit of changes to some headers
in tools/ I'll submit that separately.

[0] https://lkml.kernel.org/r/1469222687-1600-1-git-send-email-mcgrof@kernel.org

If you'd like this in git-form, you can get it on the 20160819-linker-table-v4
branch of my linux-next tree on kernel.org, this also includes the series of
the linker table userspace sandbox:

https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h 160819-linker-table-v4

Please let me know if there are any concerns or questions.

Luis R. Rodriguez (16):
  x86: remove LTO_REFERENCE_INITCALL()
  dell-smo8800: include uaccess.h
  scripts/module-common.lds: enable generation
  generic-sections: add section core helpers
  xtensa: skip adding literal when SORT() is used
  ranges.h: add helpers to build and identify Linux section ranges
  tables.h: add linker table support
  kbuild: enable option to force compile force-obj-y and force-lib-y
  firmware/Makefile: force recompilation if makefile changes
  firmware: port built-in section to linker table
  jump_label: move guard #endif down where it belongs
  jump_label: port __jump_table to linker tables
  dynamic_debug: port to use linker tables
  kprobes: move kprobe declarations to asm-generic/kprobes.h
  kprobes: port .kprobes.text to section range
  kprobes: port blacklist kprobes to linker table

 .gitignore                                         |   2 +
 Documentation/index.rst                            |   1 +
 Documentation/kbuild/makefiles.txt                 |  36 ++
 Documentation/sections/conf.py                     |   4 +
 Documentation/sections/index.rst                   |  13 +
 Documentation/sections/linker-tables.rst           | 202 +++++++
 Documentation/sections/ranges.rst                  |  49 ++
 Documentation/sections/section-core.rst            | 153 +++++
 MAINTAINERS                                        |  37 ++
 Makefile                                           |   6 +-
 arch/alpha/include/asm/Kbuild                      |   4 +
 arch/arc/include/asm/Kbuild                        |   3 +
 arch/arc/include/asm/kprobes.h                     |   6 +-
 arch/arc/kernel/vmlinux.lds.S                      |   1 -
 arch/arm/include/asm/Kbuild                        |   3 +
 arch/arm/include/asm/jump_label.h                  |   6 +-
 arch/arm/include/asm/kprobes.h                     |   4 +
 arch/arm/kernel/entry-armv.S                       |   3 +-
 arch/arm/kernel/vmlinux-xip.lds.S                  |   1 -
 arch/arm/kernel/vmlinux.lds.S                      |   1 -
 arch/arm/probes/decode.h                           |   1 +
 arch/arm64/include/asm/Kbuild                      |   3 +
 arch/arm64/include/asm/jump_label.h                |   6 +-
 arch/arm64/include/asm/kprobes.h                   |   4 +
 arch/arm64/kernel/armv8_deprecated.c               |   1 +
 arch/arm64/kernel/insn.c                           |   1 +
 arch/arm64/kernel/probes/kprobes.c                 |   4 +-
 arch/arm64/kernel/vmlinux.lds.S                    |   1 -
 arch/avr32/include/asm/Kbuild                      |   3 +
 arch/avr32/include/asm/kprobes.h                   |   4 +
 arch/avr32/kernel/entry-avr32b.S                   |  13 +-
 arch/avr32/kernel/vmlinux.lds.S                    |   1 -
 arch/blackfin/include/asm/Kbuild                   |   4 +
 arch/blackfin/kernel/vmlinux.lds.S                 |   1 -
 arch/c6x/include/asm/Kbuild                        |   3 +
 arch/c6x/include/asm/tables.h                      |  26 +
 arch/c6x/kernel/vmlinux.lds.S                      |   1 -
 arch/cris/include/asm/Kbuild                       |   4 +
 arch/frv/include/asm/Kbuild                        |   4 +
 arch/h8300/include/asm/Kbuild                      |   4 +
 arch/hexagon/include/asm/Kbuild                    |   4 +
 arch/hexagon/kernel/vmlinux.lds.S                  |   1 -
 arch/ia64/include/asm/Kbuild                       |   3 +
 arch/ia64/include/asm/kprobes.h                    |   7 +-
 arch/ia64/kernel/jprobes.S                         |   3 +-
 arch/ia64/kernel/vmlinux.lds.S                     |   1 -
 arch/ia64/lib/flush.S                              |   6 +-
 arch/m32r/include/asm/Kbuild                       |   4 +
 arch/m68k/include/asm/Kbuild                       |   4 +
 arch/metag/include/asm/Kbuild                      |   4 +
 arch/metag/kernel/vmlinux.lds.S                    |   1 -
 arch/microblaze/include/asm/Kbuild                 |   4 +
 arch/microblaze/kernel/vmlinux.lds.S               |   1 -
 arch/mips/include/asm/Kbuild                       |   3 +
 arch/mips/include/asm/jump_label.h                 |   6 +-
 arch/mips/include/asm/kprobes.h                    |   6 +-
 arch/mips/kernel/vmlinux.lds.S                     |   1 -
 arch/mn10300/include/asm/Kbuild                    |   3 +
 arch/mn10300/include/asm/kprobes.h                 |   4 +
 arch/mn10300/kernel/vmlinux.lds.S                  |   1 -
 arch/nios2/include/asm/Kbuild                      |   4 +
 arch/nios2/kernel/vmlinux.lds.S                    |   1 -
 arch/openrisc/include/asm/Kbuild                   |   4 +
 arch/openrisc/kernel/vmlinux.lds.S                 |   1 -
 arch/parisc/include/asm/Kbuild                     |   4 +
 arch/parisc/kernel/vmlinux.lds.S                   |   1 -
 arch/powerpc/include/asm/Kbuild                    |   3 +
 arch/powerpc/include/asm/jump_label.h              |   8 +-
 arch/powerpc/include/asm/kprobes.h                 |   6 +
 arch/powerpc/include/asm/ppc_asm.h                 |   7 +-
 arch/powerpc/kernel/vmlinux.lds.S                  |   1 -
 arch/s390/include/asm/Kbuild                       |   3 +
 arch/s390/include/asm/jump_label.h                 |   6 +-
 arch/s390/include/asm/kprobes.h                    |   4 +
 arch/s390/kernel/entry.S                           |   5 +-
 arch/s390/kernel/kprobes.c                         |   6 +-
 arch/s390/kernel/mcount.S                          |   3 +-
 arch/s390/kernel/vmlinux.lds.S                     |   1 -
 arch/score/include/asm/Kbuild                      |   4 +
 arch/score/kernel/vmlinux.lds.S                    |   1 -
 arch/sh/include/asm/Kbuild                         |   3 +
 arch/sh/include/asm/kprobes.h                      |   2 +
 arch/sh/kernel/vmlinux.lds.S                       |   1 -
 arch/sparc/include/asm/Kbuild                      |   3 +
 arch/sparc/include/asm/jump_label.h                |   6 +-
 arch/sparc/include/asm/kprobes.h                   |   5 +
 arch/sparc/kernel/vmlinux.lds.S                    |   1 -
 arch/sparc/mm/ultra.S                              |   3 +-
 arch/tile/include/asm/Kbuild                       |   3 +
 arch/tile/include/asm/kprobes.h                    |   6 +-
 arch/tile/kernel/vmlinux.lds.S                     |   1 -
 arch/um/include/asm/Kbuild                         |   4 +
 arch/unicore32/include/asm/Kbuild                  |   3 +
 arch/unicore32/include/asm/section-core.h          |  19 +
 arch/x86/include/asm/Kbuild                        |   3 +
 arch/x86/include/asm/jump_label.h                  |  10 +-
 arch/x86/include/asm/kprobes.h                     |   6 +
 arch/x86/kernel/cpu/microcode/core.c               |   8 +-
 arch/x86/kernel/kprobes/core.c                     |  11 +-
 arch/x86/kernel/vmlinux.lds.S                      |   1 -
 arch/x86/tools/relocs.c                            |   4 +
 arch/xtensa/include/asm/Kbuild                     |   4 +
 arch/xtensa/kernel/Makefile                        |   8 +-
 drivers/base/firmware_class.c                      |  12 +-
 drivers/platform/x86/dell-smo8800.c                |   1 +
 firmware/Makefile                                  |   6 +-
 include/asm-generic/kprobes.h                      |  26 +
 include/asm-generic/ranges.h                       | 103 ++++
 include/asm-generic/section-core.h                 | 341 +++++++++++
 include/asm-generic/sections.h                     |   4 +-
 include/asm-generic/tables.h                       |  50 ++
 include/asm-generic/vmlinux.lds.h                  |  73 +--
 include/linux/compiler.h                           |   8 -
 include/linux/dynamic_debug.h                      |   5 +-
 include/linux/init.h                               |  20 +-
 include/linux/jump_label.h                         |   8 +-
 include/linux/kprobes.h                            |  24 +-
 include/linux/ranges.h                             | 128 +++++
 include/linux/sections.h                           | 111 ++++
 include/linux/tables.h                             | 638 +++++++++++++++++++++
 init/Kconfig                                       |  22 +
 kernel/jump_label.c                                |  17 +-
 kernel/kprobes.c                                   |  17 +-
 lib/dynamic_debug.c                                |  13 +-
 scripts/Makefile.build                             |   7 +-
 scripts/Makefile.clean                             |   2 +
 scripts/Makefile.lib                               |  11 +
 scripts/Makefile.modpost                           |   2 +-
 scripts/mod/modpost.c                              |   2 +-
 scripts/{module-common.lds => module-common.lds.S} |   6 +
 scripts/recordmcount.c                             |   2 +-
 scripts/recordmcount.pl                            |   2 +-
 tools/objtool/special.c                            |   2 +-
 133 files changed, 2328 insertions(+), 214 deletions(-)
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/linker-tables.rst
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/c6x/include/asm/tables.h
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/kprobes.h
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/asm-generic/tables.h
 create mode 100644 include/linux/ranges.h
 create mode 100644 include/linux/sections.h
 create mode 100644 include/linux/tables.h
 rename scripts/{module-common.lds => module-common.lds.S} (80%)

-- 
2.9.2


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v4 00/16] linux: generalize sections, ranges and linker tables
@ 2016-08-19 21:32 ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This v4 addresses feedback from the previous v3 series [0], and also
addresses a huge array of additional tests against many architectures
outside of what 0-day provides. As I mentioned in my last v3 series,
0-day had only found one issue with the series, a blackfin architecture
linker issue with the last series. Guenter Rock was kind enough to give
my series a test spin on his test bed and he found quite a bit of other
oddball issues with obscure architectures, and even on x86 with an old
toolchain. After a lot of work and coordinating with a few maintainers
I'm happy to report all issues found so far through all possible testing
I could do are now fixed, this series also addresses all feedback from
the last series, as such this goes submitted as PATCH form.

In addressing fixing this work on a few architectures some of the previous
patches are further simplified. The kprobes port to linker tables is made
much easier now that I've addressed moving out core kprobe declarations
into asm-generic/kprobes.h. Refer to the patch "kprobes: move kprobe
declarations to asm-generic/kprobes.h". This makes for a much cleaner
solution across architectures.

Boris feedback on making the code bit rot feature optional is addressed
by using a new Kconfig symbol for this, CONFIG_BUILD_AVOID_BITROT,
but given Greg's concerns over lack of clarity over what this was all about
I've ripped that functionality out into its own patch with a bit more
extensive documentation and re-wording. See the patch "kbuild: enable option
to force compile force-obj-y and force-lib-y". I hope makes it clear how
linker tables can help with avoiding code bit rot. I've gone with a new
Kconfig symbol CONFIG_BUILD_AVOID_BITROT given CONFIG_COMPILE_TEST is
not available on UML, this feature is desirable on all architectures.

The documentation is revamped, now that the DocBook format is deprecated
I ported the documention into the trendy hipster Sphinx documentation
format.

AT Boris' request I've adapated the userspace linker table application
forintegration into the kernel under tools/ to make it easier to keep
things in sync, however since this requires a bit of changes to some headers
in tools/ I'll submit that separately.

[0] https://lkml.kernel.org/r/1469222687-1600-1-git-send-email-mcgrof@kernel.org

If you'd like this in git-form, you can get it on the 20160819-linker-table-v4
branch of my linux-next tree on kernel.org, this also includes the series of
the linker table userspace sandbox:

https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h=20160819-linker-table-v4

Please let me know if there are any concerns or questions.

Luis R. Rodriguez (16):
  x86: remove LTO_REFERENCE_INITCALL()
  dell-smo8800: include uaccess.h
  scripts/module-common.lds: enable generation
  generic-sections: add section core helpers
  xtensa: skip adding literal when SORT() is used
  ranges.h: add helpers to build and identify Linux section ranges
  tables.h: add linker table support
  kbuild: enable option to force compile force-obj-y and force-lib-y
  firmware/Makefile: force recompilation if makefile changes
  firmware: port built-in section to linker table
  jump_label: move guard #endif down where it belongs
  jump_label: port __jump_table to linker tables
  dynamic_debug: port to use linker tables
  kprobes: move kprobe declarations to asm-generic/kprobes.h
  kprobes: port .kprobes.text to section range
  kprobes: port blacklist kprobes to linker table

 .gitignore                                         |   2 +
 Documentation/index.rst                            |   1 +
 Documentation/kbuild/makefiles.txt                 |  36 ++
 Documentation/sections/conf.py                     |   4 +
 Documentation/sections/index.rst                   |  13 +
 Documentation/sections/linker-tables.rst           | 202 +++++++
 Documentation/sections/ranges.rst                  |  49 ++
 Documentation/sections/section-core.rst            | 153 +++++
 MAINTAINERS                                        |  37 ++
 Makefile                                           |   6 +-
 arch/alpha/include/asm/Kbuild                      |   4 +
 arch/arc/include/asm/Kbuild                        |   3 +
 arch/arc/include/asm/kprobes.h                     |   6 +-
 arch/arc/kernel/vmlinux.lds.S                      |   1 -
 arch/arm/include/asm/Kbuild                        |   3 +
 arch/arm/include/asm/jump_label.h                  |   6 +-
 arch/arm/include/asm/kprobes.h                     |   4 +
 arch/arm/kernel/entry-armv.S                       |   3 +-
 arch/arm/kernel/vmlinux-xip.lds.S                  |   1 -
 arch/arm/kernel/vmlinux.lds.S                      |   1 -
 arch/arm/probes/decode.h                           |   1 +
 arch/arm64/include/asm/Kbuild                      |   3 +
 arch/arm64/include/asm/jump_label.h                |   6 +-
 arch/arm64/include/asm/kprobes.h                   |   4 +
 arch/arm64/kernel/armv8_deprecated.c               |   1 +
 arch/arm64/kernel/insn.c                           |   1 +
 arch/arm64/kernel/probes/kprobes.c                 |   4 +-
 arch/arm64/kernel/vmlinux.lds.S                    |   1 -
 arch/avr32/include/asm/Kbuild                      |   3 +
 arch/avr32/include/asm/kprobes.h                   |   4 +
 arch/avr32/kernel/entry-avr32b.S                   |  13 +-
 arch/avr32/kernel/vmlinux.lds.S                    |   1 -
 arch/blackfin/include/asm/Kbuild                   |   4 +
 arch/blackfin/kernel/vmlinux.lds.S                 |   1 -
 arch/c6x/include/asm/Kbuild                        |   3 +
 arch/c6x/include/asm/tables.h                      |  26 +
 arch/c6x/kernel/vmlinux.lds.S                      |   1 -
 arch/cris/include/asm/Kbuild                       |   4 +
 arch/frv/include/asm/Kbuild                        |   4 +
 arch/h8300/include/asm/Kbuild                      |   4 +
 arch/hexagon/include/asm/Kbuild                    |   4 +
 arch/hexagon/kernel/vmlinux.lds.S                  |   1 -
 arch/ia64/include/asm/Kbuild                       |   3 +
 arch/ia64/include/asm/kprobes.h                    |   7 +-
 arch/ia64/kernel/jprobes.S                         |   3 +-
 arch/ia64/kernel/vmlinux.lds.S                     |   1 -
 arch/ia64/lib/flush.S                              |   6 +-
 arch/m32r/include/asm/Kbuild                       |   4 +
 arch/m68k/include/asm/Kbuild                       |   4 +
 arch/metag/include/asm/Kbuild                      |   4 +
 arch/metag/kernel/vmlinux.lds.S                    |   1 -
 arch/microblaze/include/asm/Kbuild                 |   4 +
 arch/microblaze/kernel/vmlinux.lds.S               |   1 -
 arch/mips/include/asm/Kbuild                       |   3 +
 arch/mips/include/asm/jump_label.h                 |   6 +-
 arch/mips/include/asm/kprobes.h                    |   6 +-
 arch/mips/kernel/vmlinux.lds.S                     |   1 -
 arch/mn10300/include/asm/Kbuild                    |   3 +
 arch/mn10300/include/asm/kprobes.h                 |   4 +
 arch/mn10300/kernel/vmlinux.lds.S                  |   1 -
 arch/nios2/include/asm/Kbuild                      |   4 +
 arch/nios2/kernel/vmlinux.lds.S                    |   1 -
 arch/openrisc/include/asm/Kbuild                   |   4 +
 arch/openrisc/kernel/vmlinux.lds.S                 |   1 -
 arch/parisc/include/asm/Kbuild                     |   4 +
 arch/parisc/kernel/vmlinux.lds.S                   |   1 -
 arch/powerpc/include/asm/Kbuild                    |   3 +
 arch/powerpc/include/asm/jump_label.h              |   8 +-
 arch/powerpc/include/asm/kprobes.h                 |   6 +
 arch/powerpc/include/asm/ppc_asm.h                 |   7 +-
 arch/powerpc/kernel/vmlinux.lds.S                  |   1 -
 arch/s390/include/asm/Kbuild                       |   3 +
 arch/s390/include/asm/jump_label.h                 |   6 +-
 arch/s390/include/asm/kprobes.h                    |   4 +
 arch/s390/kernel/entry.S                           |   5 +-
 arch/s390/kernel/kprobes.c                         |   6 +-
 arch/s390/kernel/mcount.S                          |   3 +-
 arch/s390/kernel/vmlinux.lds.S                     |   1 -
 arch/score/include/asm/Kbuild                      |   4 +
 arch/score/kernel/vmlinux.lds.S                    |   1 -
 arch/sh/include/asm/Kbuild                         |   3 +
 arch/sh/include/asm/kprobes.h                      |   2 +
 arch/sh/kernel/vmlinux.lds.S                       |   1 -
 arch/sparc/include/asm/Kbuild                      |   3 +
 arch/sparc/include/asm/jump_label.h                |   6 +-
 arch/sparc/include/asm/kprobes.h                   |   5 +
 arch/sparc/kernel/vmlinux.lds.S                    |   1 -
 arch/sparc/mm/ultra.S                              |   3 +-
 arch/tile/include/asm/Kbuild                       |   3 +
 arch/tile/include/asm/kprobes.h                    |   6 +-
 arch/tile/kernel/vmlinux.lds.S                     |   1 -
 arch/um/include/asm/Kbuild                         |   4 +
 arch/unicore32/include/asm/Kbuild                  |   3 +
 arch/unicore32/include/asm/section-core.h          |  19 +
 arch/x86/include/asm/Kbuild                        |   3 +
 arch/x86/include/asm/jump_label.h                  |  10 +-
 arch/x86/include/asm/kprobes.h                     |   6 +
 arch/x86/kernel/cpu/microcode/core.c               |   8 +-
 arch/x86/kernel/kprobes/core.c                     |  11 +-
 arch/x86/kernel/vmlinux.lds.S                      |   1 -
 arch/x86/tools/relocs.c                            |   4 +
 arch/xtensa/include/asm/Kbuild                     |   4 +
 arch/xtensa/kernel/Makefile                        |   8 +-
 drivers/base/firmware_class.c                      |  12 +-
 drivers/platform/x86/dell-smo8800.c                |   1 +
 firmware/Makefile                                  |   6 +-
 include/asm-generic/kprobes.h                      |  26 +
 include/asm-generic/ranges.h                       | 103 ++++
 include/asm-generic/section-core.h                 | 341 +++++++++++
 include/asm-generic/sections.h                     |   4 +-
 include/asm-generic/tables.h                       |  50 ++
 include/asm-generic/vmlinux.lds.h                  |  73 +--
 include/linux/compiler.h                           |   8 -
 include/linux/dynamic_debug.h                      |   5 +-
 include/linux/init.h                               |  20 +-
 include/linux/jump_label.h                         |   8 +-
 include/linux/kprobes.h                            |  24 +-
 include/linux/ranges.h                             | 128 +++++
 include/linux/sections.h                           | 111 ++++
 include/linux/tables.h                             | 638 +++++++++++++++++++++
 init/Kconfig                                       |  22 +
 kernel/jump_label.c                                |  17 +-
 kernel/kprobes.c                                   |  17 +-
 lib/dynamic_debug.c                                |  13 +-
 scripts/Makefile.build                             |   7 +-
 scripts/Makefile.clean                             |   2 +
 scripts/Makefile.lib                               |  11 +
 scripts/Makefile.modpost                           |   2 +-
 scripts/mod/modpost.c                              |   2 +-
 scripts/{module-common.lds => module-common.lds.S} |   6 +
 scripts/recordmcount.c                             |   2 +-
 scripts/recordmcount.pl                            |   2 +-
 tools/objtool/special.c                            |   2 +-
 133 files changed, 2328 insertions(+), 214 deletions(-)
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/linker-tables.rst
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/c6x/include/asm/tables.h
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/kprobes.h
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/asm-generic/tables.h
 create mode 100644 include/linux/ranges.h
 create mode 100644 include/linux/sections.h
 create mode 100644 include/linux/tables.h
 rename scripts/{module-common.lds => module-common.lds.S} (80%)

-- 
2.9.2


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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v4 00/16] linux: generalize sections, ranges and linker tables
@ 2016-08-19 21:32 ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This v4 addresses feedback from the previous v3 series [0], and also
addresses a huge array of additional tests against many architectures
outside of what 0-day provides. As I mentioned in my last v3 series,
0-day had only found one issue with the series, a blackfin architecture
linker issue with the last series. Guenter Rock was kind enough to give
my series a test spin on his test bed and he found quite a bit of other
oddball issues with obscure architectures, and even on x86 with an old
toolchain. After a lot of work and coordinating with a few maintainers
I'm happy to report all issues found so far through all possible testing
I could do are now fixed, this series also addresses all feedback from
the last series, as such this goes submitted as PATCH form.

In addressing fixing this work on a few architectures some of the previous
patches are further simplified. The kprobes port to linker tables is made
much easier now that I've addressed moving out core kprobe declarations
into asm-generic/kprobes.h. Refer to the patch "kprobes: move kprobe
declarations to asm-generic/kprobes.h". This makes for a much cleaner
solution across architectures.

Boris feedback on making the code bit rot feature optional is addressed
by using a new Kconfig symbol for this, CONFIG_BUILD_AVOID_BITROT,
but given Greg's concerns over lack of clarity over what this was all about
I've ripped that functionality out into its own patch with a bit more
extensive documentation and re-wording. See the patch "kbuild: enable option
to force compile force-obj-y and force-lib-y". I hope makes it clear how
linker tables can help with avoiding code bit rot. I've gone with a new
Kconfig symbol CONFIG_BUILD_AVOID_BITROT given CONFIG_COMPILE_TEST is
not available on UML, this feature is desirable on all architectures.

The documentation is revamped, now that the DocBook format is deprecated
I ported the documention into the trendy hipster Sphinx documentation
format.

AT Boris' request I've adapated the userspace linker table application
forintegration into the kernel under tools/ to make it easier to keep
things in sync, however since this requires a bit of changes to some headers
in tools/ I'll submit that separately.

[0] https://lkml.kernel.org/r/1469222687-1600-1-git-send-email-mcgrof@kernel.org

If you'd like this in git-form, you can get it on the 20160819-linker-table-v4
branch of my linux-next tree on kernel.org, this also includes the series of
the linker table userspace sandbox:

https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h=20160819-linker-table-v4

Please let me know if there are any concerns or questions.

Luis R. Rodriguez (16):
  x86: remove LTO_REFERENCE_INITCALL()
  dell-smo8800: include uaccess.h
  scripts/module-common.lds: enable generation
  generic-sections: add section core helpers
  xtensa: skip adding literal when SORT() is used
  ranges.h: add helpers to build and identify Linux section ranges
  tables.h: add linker table support
  kbuild: enable option to force compile force-obj-y and force-lib-y
  firmware/Makefile: force recompilation if makefile changes
  firmware: port built-in section to linker table
  jump_label: move guard #endif down where it belongs
  jump_label: port __jump_table to linker tables
  dynamic_debug: port to use linker tables
  kprobes: move kprobe declarations to asm-generic/kprobes.h
  kprobes: port .kprobes.text to section range
  kprobes: port blacklist kprobes to linker table

 .gitignore                                         |   2 +
 Documentation/index.rst                            |   1 +
 Documentation/kbuild/makefiles.txt                 |  36 ++
 Documentation/sections/conf.py                     |   4 +
 Documentation/sections/index.rst                   |  13 +
 Documentation/sections/linker-tables.rst           | 202 +++++++
 Documentation/sections/ranges.rst                  |  49 ++
 Documentation/sections/section-core.rst            | 153 +++++
 MAINTAINERS                                        |  37 ++
 Makefile                                           |   6 +-
 arch/alpha/include/asm/Kbuild                      |   4 +
 arch/arc/include/asm/Kbuild                        |   3 +
 arch/arc/include/asm/kprobes.h                     |   6 +-
 arch/arc/kernel/vmlinux.lds.S                      |   1 -
 arch/arm/include/asm/Kbuild                        |   3 +
 arch/arm/include/asm/jump_label.h                  |   6 +-
 arch/arm/include/asm/kprobes.h                     |   4 +
 arch/arm/kernel/entry-armv.S                       |   3 +-
 arch/arm/kernel/vmlinux-xip.lds.S                  |   1 -
 arch/arm/kernel/vmlinux.lds.S                      |   1 -
 arch/arm/probes/decode.h                           |   1 +
 arch/arm64/include/asm/Kbuild                      |   3 +
 arch/arm64/include/asm/jump_label.h                |   6 +-
 arch/arm64/include/asm/kprobes.h                   |   4 +
 arch/arm64/kernel/armv8_deprecated.c               |   1 +
 arch/arm64/kernel/insn.c                           |   1 +
 arch/arm64/kernel/probes/kprobes.c                 |   4 +-
 arch/arm64/kernel/vmlinux.lds.S                    |   1 -
 arch/avr32/include/asm/Kbuild                      |   3 +
 arch/avr32/include/asm/kprobes.h                   |   4 +
 arch/avr32/kernel/entry-avr32b.S                   |  13 +-
 arch/avr32/kernel/vmlinux.lds.S                    |   1 -
 arch/blackfin/include/asm/Kbuild                   |   4 +
 arch/blackfin/kernel/vmlinux.lds.S                 |   1 -
 arch/c6x/include/asm/Kbuild                        |   3 +
 arch/c6x/include/asm/tables.h                      |  26 +
 arch/c6x/kernel/vmlinux.lds.S                      |   1 -
 arch/cris/include/asm/Kbuild                       |   4 +
 arch/frv/include/asm/Kbuild                        |   4 +
 arch/h8300/include/asm/Kbuild                      |   4 +
 arch/hexagon/include/asm/Kbuild                    |   4 +
 arch/hexagon/kernel/vmlinux.lds.S                  |   1 -
 arch/ia64/include/asm/Kbuild                       |   3 +
 arch/ia64/include/asm/kprobes.h                    |   7 +-
 arch/ia64/kernel/jprobes.S                         |   3 +-
 arch/ia64/kernel/vmlinux.lds.S                     |   1 -
 arch/ia64/lib/flush.S                              |   6 +-
 arch/m32r/include/asm/Kbuild                       |   4 +
 arch/m68k/include/asm/Kbuild                       |   4 +
 arch/metag/include/asm/Kbuild                      |   4 +
 arch/metag/kernel/vmlinux.lds.S                    |   1 -
 arch/microblaze/include/asm/Kbuild                 |   4 +
 arch/microblaze/kernel/vmlinux.lds.S               |   1 -
 arch/mips/include/asm/Kbuild                       |   3 +
 arch/mips/include/asm/jump_label.h                 |   6 +-
 arch/mips/include/asm/kprobes.h                    |   6 +-
 arch/mips/kernel/vmlinux.lds.S                     |   1 -
 arch/mn10300/include/asm/Kbuild                    |   3 +
 arch/mn10300/include/asm/kprobes.h                 |   4 +
 arch/mn10300/kernel/vmlinux.lds.S                  |   1 -
 arch/nios2/include/asm/Kbuild                      |   4 +
 arch/nios2/kernel/vmlinux.lds.S                    |   1 -
 arch/openrisc/include/asm/Kbuild                   |   4 +
 arch/openrisc/kernel/vmlinux.lds.S                 |   1 -
 arch/parisc/include/asm/Kbuild                     |   4 +
 arch/parisc/kernel/vmlinux.lds.S                   |   1 -
 arch/powerpc/include/asm/Kbuild                    |   3 +
 arch/powerpc/include/asm/jump_label.h              |   8 +-
 arch/powerpc/include/asm/kprobes.h                 |   6 +
 arch/powerpc/include/asm/ppc_asm.h                 |   7 +-
 arch/powerpc/kernel/vmlinux.lds.S                  |   1 -
 arch/s390/include/asm/Kbuild                       |   3 +
 arch/s390/include/asm/jump_label.h                 |   6 +-
 arch/s390/include/asm/kprobes.h                    |   4 +
 arch/s390/kernel/entry.S                           |   5 +-
 arch/s390/kernel/kprobes.c                         |   6 +-
 arch/s390/kernel/mcount.S                          |   3 +-
 arch/s390/kernel/vmlinux.lds.S                     |   1 -
 arch/score/include/asm/Kbuild                      |   4 +
 arch/score/kernel/vmlinux.lds.S                    |   1 -
 arch/sh/include/asm/Kbuild                         |   3 +
 arch/sh/include/asm/kprobes.h                      |   2 +
 arch/sh/kernel/vmlinux.lds.S                       |   1 -
 arch/sparc/include/asm/Kbuild                      |   3 +
 arch/sparc/include/asm/jump_label.h                |   6 +-
 arch/sparc/include/asm/kprobes.h                   |   5 +
 arch/sparc/kernel/vmlinux.lds.S                    |   1 -
 arch/sparc/mm/ultra.S                              |   3 +-
 arch/tile/include/asm/Kbuild                       |   3 +
 arch/tile/include/asm/kprobes.h                    |   6 +-
 arch/tile/kernel/vmlinux.lds.S                     |   1 -
 arch/um/include/asm/Kbuild                         |   4 +
 arch/unicore32/include/asm/Kbuild                  |   3 +
 arch/unicore32/include/asm/section-core.h          |  19 +
 arch/x86/include/asm/Kbuild                        |   3 +
 arch/x86/include/asm/jump_label.h                  |  10 +-
 arch/x86/include/asm/kprobes.h                     |   6 +
 arch/x86/kernel/cpu/microcode/core.c               |   8 +-
 arch/x86/kernel/kprobes/core.c                     |  11 +-
 arch/x86/kernel/vmlinux.lds.S                      |   1 -
 arch/x86/tools/relocs.c                            |   4 +
 arch/xtensa/include/asm/Kbuild                     |   4 +
 arch/xtensa/kernel/Makefile                        |   8 +-
 drivers/base/firmware_class.c                      |  12 +-
 drivers/platform/x86/dell-smo8800.c                |   1 +
 firmware/Makefile                                  |   6 +-
 include/asm-generic/kprobes.h                      |  26 +
 include/asm-generic/ranges.h                       | 103 ++++
 include/asm-generic/section-core.h                 | 341 +++++++++++
 include/asm-generic/sections.h                     |   4 +-
 include/asm-generic/tables.h                       |  50 ++
 include/asm-generic/vmlinux.lds.h                  |  73 +--
 include/linux/compiler.h                           |   8 -
 include/linux/dynamic_debug.h                      |   5 +-
 include/linux/init.h                               |  20 +-
 include/linux/jump_label.h                         |   8 +-
 include/linux/kprobes.h                            |  24 +-
 include/linux/ranges.h                             | 128 +++++
 include/linux/sections.h                           | 111 ++++
 include/linux/tables.h                             | 638 +++++++++++++++++++++
 init/Kconfig                                       |  22 +
 kernel/jump_label.c                                |  17 +-
 kernel/kprobes.c                                   |  17 +-
 lib/dynamic_debug.c                                |  13 +-
 scripts/Makefile.build                             |   7 +-
 scripts/Makefile.clean                             |   2 +
 scripts/Makefile.lib                               |  11 +
 scripts/Makefile.modpost                           |   2 +-
 scripts/mod/modpost.c                              |   2 +-
 scripts/{module-common.lds => module-common.lds.S} |   6 +
 scripts/recordmcount.c                             |   2 +-
 scripts/recordmcount.pl                            |   2 +-
 tools/objtool/special.c                            |   2 +-
 133 files changed, 2328 insertions(+), 214 deletions(-)
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/linker-tables.rst
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/c6x/include/asm/tables.h
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/kprobes.h
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/asm-generic/tables.h
 create mode 100644 include/linux/ranges.h
 create mode 100644 include/linux/sections.h
 create mode 100644 include/linux/tables.h
 rename scripts/{module-common.lds => module-common.lds.S} (80%)

-- 
2.9.2


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v4 01/16] x86: remove LTO_REFERENCE_INITCALL()
  2016-08-19 21:32 ` mcgrof
  (?)
@ 2016-08-19 21:32   ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

The setup for LTO never made it upstream, and although this has
some users, this is now really old stuff for a gcc 4.7 LTO problem.
We know that at least LTO_REFERENCE_INITCALL() work around can
be removed if LTO is not supported on v4.7 anymore.

As per Andi the DISABLE_LTO and LTO_CFLAGS are still neeeded though.

v3: added to this series, removing LTO_REFERENCE_INITCALL()
    justifies that other future similar macros do not need
    a respective LTO_REFERENCE_INITCALL() on them therefore
    simplifying new code.

Acked-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/linux/init.h | 20 +-------------------
 1 file changed, 1 insertion(+), 19 deletions(-)

diff --git a/include/linux/init.h b/include/linux/init.h
index 1e5c131d5c9a..aa662ad80d9c 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -151,23 +151,6 @@ extern bool initcall_debug;
 
 #ifndef __ASSEMBLY__
 
-#ifdef CONFIG_LTO
-/* Work around a LTO gcc problem: when there is no reference to a variable
- * in a module it will be moved to the end of the program. This causes
- * reordering of initcalls which the kernel does not like.
- * Add a dummy reference function to avoid this. The function is
- * deleted by the linker.
- */
-#define LTO_REFERENCE_INITCALL(x) \
-	; /* yes this is needed */			\
-	static __used __exit void *reference_##x(void)	\
-	{						\
-		return &x;				\
-	}
-#else
-#define LTO_REFERENCE_INITCALL(x)
-#endif
-
 /* initcalls are now grouped by functionality into separate 
  * subsections. Ordering inside the subsections is determined
  * by link order. 
@@ -180,8 +163,7 @@ extern bool initcall_debug;
 
 #define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
-	__attribute__((__section__(".initcall" #id ".init"))) = fn; \
-	LTO_REFERENCE_INITCALL(__initcall_##fn##id)
+	__attribute__((__section__(".initcall" #id ".init"))) = fn;
 
 /*
  * Early initcalls run before initializing SMP.
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 01/16] x86: remove LTO_REFERENCE_INITCALL()
@ 2016-08-19 21:32   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

The setup for LTO never made it upstream, and although this has
some users, this is now really old stuff for a gcc 4.7 LTO problem.
We know that at least LTO_REFERENCE_INITCALL() work around can
be removed if LTO is not supported on v4.7 anymore.

As per Andi the DISABLE_LTO and LTO_CFLAGS are still neeeded though.

v3: added to this series, removing LTO_REFERENCE_INITCALL()
    justifies that other future similar macros do not need
    a respective LTO_REFERENCE_INITCALL() on them therefore
    simplifying new code.

Acked-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/linux/init.h | 20 +-------------------
 1 file changed, 1 insertion(+), 19 deletions(-)

diff --git a/include/linux/init.h b/include/linux/init.h
index 1e5c131d5c9a..aa662ad80d9c 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -151,23 +151,6 @@ extern bool initcall_debug;
 
 #ifndef __ASSEMBLY__
 
-#ifdef CONFIG_LTO
-/* Work around a LTO gcc problem: when there is no reference to a variable
- * in a module it will be moved to the end of the program. This causes
- * reordering of initcalls which the kernel does not like.
- * Add a dummy reference function to avoid this. The function is
- * deleted by the linker.
- */
-#define LTO_REFERENCE_INITCALL(x) \
-	; /* yes this is needed */			\
-	static __used __exit void *reference_##x(void)	\
-	{						\
-		return &x;				\
-	}
-#else
-#define LTO_REFERENCE_INITCALL(x)
-#endif
-
 /* initcalls are now grouped by functionality into separate 
  * subsections. Ordering inside the subsections is determined
  * by link order. 
@@ -180,8 +163,7 @@ extern bool initcall_debug;
 
 #define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
-	__attribute__((__section__(".initcall" #id ".init"))) = fn; \
-	LTO_REFERENCE_INITCALL(__initcall_##fn##id)
+	__attribute__((__section__(".initcall" #id ".init"))) = fn;
 
 /*
  * Early initcalls run before initializing SMP.
-- 
2.9.2


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 01/16] x86: remove LTO_REFERENCE_INITCALL()
@ 2016-08-19 21:32   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

The setup for LTO never made it upstream, and although this has
some users, this is now really old stuff for a gcc 4.7 LTO problem.
We know that at least LTO_REFERENCE_INITCALL() work around can
be removed if LTO is not supported on v4.7 anymore.

As per Andi the DISABLE_LTO and LTO_CFLAGS are still neeeded though.

v3: added to this series, removing LTO_REFERENCE_INITCALL()
    justifies that other future similar macros do not need
    a respective LTO_REFERENCE_INITCALL() on them therefore
    simplifying new code.

Acked-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/linux/init.h | 20 +-------------------
 1 file changed, 1 insertion(+), 19 deletions(-)

diff --git a/include/linux/init.h b/include/linux/init.h
index 1e5c131d5c9a..aa662ad80d9c 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -151,23 +151,6 @@ extern bool initcall_debug;
 
 #ifndef __ASSEMBLY__
 
-#ifdef CONFIG_LTO
-/* Work around a LTO gcc problem: when there is no reference to a variable
- * in a module it will be moved to the end of the program. This causes
- * reordering of initcalls which the kernel does not like.
- * Add a dummy reference function to avoid this. The function is
- * deleted by the linker.
- */
-#define LTO_REFERENCE_INITCALL(x) \
-	; /* yes this is needed */			\
-	static __used __exit void *reference_##x(void)	\
-	{						\
-		return &x;				\
-	}
-#else
-#define LTO_REFERENCE_INITCALL(x)
-#endif
-
 /* initcalls are now grouped by functionality into separate 
  * subsections. Ordering inside the subsections is determined
  * by link order. 
@@ -180,8 +163,7 @@ extern bool initcall_debug;
 
 #define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
-	__attribute__((__section__(".initcall" #id ".init"))) = fn; \
-	LTO_REFERENCE_INITCALL(__initcall_##fn##id)
+	__attribute__((__section__(".initcall" #id ".init"))) = fn;
 
 /*
  * Early initcalls run before initializing SMP.
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 02/16] dell-smo8800: include uaccess.h
  2016-08-19 21:32 ` mcgrof
  (?)
  (?)
@ 2016-08-19 21:32   ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

sections.h is currently included and it provides dell-smo8800
with what it needs, an upcoming change will decouple uaccess.h
from sections.h. This driver needs to explicitly require uaccess.h
before this change.

v3: new to this series -- needed due to collateral of the split of
    old linker tables from tables.h into 3 files: sections.h, ranges.h
    and tables.h

Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 drivers/platform/x86/dell-smo8800.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/platform/x86/dell-smo8800.c b/drivers/platform/x86/dell-smo8800.c
index 0aec4fd4c48e..37e646034ef8 100644
--- a/drivers/platform/x86/dell-smo8800.c
+++ b/drivers/platform/x86/dell-smo8800.c
@@ -24,6 +24,7 @@
 #include <linux/acpi.h>
 #include <linux/interrupt.h>
 #include <linux/miscdevice.h>
+#include <linux/uaccess.h>
 
 struct smo8800_device {
 	u32 irq;                     /* acpi device irq */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 02/16] dell-smo8800: include uaccess.h
@ 2016-08-19 21:32   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

sections.h is currently included and it provides dell-smo8800
with what it needs, an upcoming change will decouple uaccess.h
from sections.h. This driver needs to explicitly require uaccess.h
before this change.

v3: new to this series -- needed due to collateral of the split of
    old linker tables from tables.h into 3 files: sections.h, ranges.h
    and tables.h

Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 drivers/platform/x86/dell-smo8800.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/platform/x86/dell-smo8800.c b/drivers/platform/x86/dell-smo8800.c
index 0aec4fd4c48e..37e646034ef8 100644
--- a/drivers/platform/x86/dell-smo8800.c
+++ b/drivers/platform/x86/dell-smo8800.c
@@ -24,6 +24,7 @@
 #include <linux/acpi.h>
 #include <linux/interrupt.h>
 #include <linux/miscdevice.h>
+#include <linux/uaccess.h>
 
 struct smo8800_device {
 	u32 irq;                     /* acpi device irq */
-- 
2.9.2


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 02/16] dell-smo8800: include uaccess.h
@ 2016-08-19 21:32   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

sections.h is currently included and it provides dell-smo8800
with what it needs, an upcoming change will decouple uaccess.h
from sections.h. This driver needs to explicitly require uaccess.h
before this change.

v3: new to this series -- needed due to collateral of the split of
    old linker tables from tables.h into 3 files: sections.h, ranges.h
    and tables.h

Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 drivers/platform/x86/dell-smo8800.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/platform/x86/dell-smo8800.c b/drivers/platform/x86/dell-smo8800.c
index 0aec4fd4c48e..37e646034ef8 100644
--- a/drivers/platform/x86/dell-smo8800.c
+++ b/drivers/platform/x86/dell-smo8800.c
@@ -24,6 +24,7 @@
 #include <linux/acpi.h>
 #include <linux/interrupt.h>
 #include <linux/miscdevice.h>
+#include <linux/uaccess.h>
 
 struct smo8800_device {
 	u32 irq;                     /* acpi device irq */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 02/16] dell-smo8800: include uaccess.h
@ 2016-08-19 21:32   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

sections.h is currently included and it provides dell-smo8800
with what it needs, an upcoming change will decouple uaccess.h
from sections.h. This driver needs to explicitly require uaccess.h
before this change.

v3: new to this series -- needed due to collateral of the split of
    old linker tables from tables.h into 3 files: sections.h, ranges.h
    and tables.h

Reviewed-by: Pali Roh√°r <pali.rohar@gmail.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 drivers/platform/x86/dell-smo8800.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/platform/x86/dell-smo8800.c b/drivers/platform/x86/dell-smo8800.c
index 0aec4fd4c48e..37e646034ef8 100644
--- a/drivers/platform/x86/dell-smo8800.c
+++ b/drivers/platform/x86/dell-smo8800.c
@@ -24,6 +24,7 @@
 #include <linux/acpi.h>
 #include <linux/interrupt.h>
 #include <linux/miscdevice.h>
+#include <linux/uaccess.h>
 
 struct smo8800_device {
 	u32 irq;                     /* acpi device irq */
-- 
2.9.2

--
To unsubscribe from this list: send the line "unsubscribe linux-ia64" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 03/16] scripts/module-common.lds: enable generation
  2016-08-19 21:32 ` mcgrof
  (?)
@ 2016-08-19 21:32   ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

scripts/module-common.lds is currently pretty static, in the
future this may change and we will want access to kernel macros
to help expands certain areas. To get access to use macros we
need to generate module-common.lds from module-common.lds.S, for
now though only enable the generation. We'll later expand on this
as needed.

Since this file is now generated add it to .gitignore.

v4: add file to MAINTAINERS
v3: new to this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 .gitignore                                         | 2 ++
 MAINTAINERS                                        | 1 +
 Makefile                                           | 6 +++++-
 scripts/Makefile.modpost                           | 2 +-
 scripts/{module-common.lds => module-common.lds.S} | 0
 5 files changed, 9 insertions(+), 2 deletions(-)
 rename scripts/{module-common.lds => module-common.lds.S} (100%)

diff --git a/.gitignore b/.gitignore
index c2ed4ecb0acd..0f0702054fdb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -114,3 +114,5 @@ all.config
 
 # Kdevelop4
 *.kdev4
+
+scripts/module-common.lds
diff --git a/MAINTAINERS b/MAINTAINERS
index d635ab047f3a..5aec01883020 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7887,6 +7887,7 @@ M:	Rusty Russell <rusty@rustcorp.com.au>
 S:	Maintained
 F:	include/linux/module.h
 F:	kernel/module.c
+F:	scripts/module-common.lds.S
 
 MOTION EYE VAIO PICTUREBOOK CAMERA DRIVER
 W:	http://popies.net/meye/
diff --git a/Makefile b/Makefile
index 5c18baad7218..b3e5ea78d582 100644
--- a/Makefile
+++ b/Makefile
@@ -408,6 +408,10 @@ KBUILD_AFLAGS_MODULE  := -DMODULE
 KBUILD_CFLAGS_MODULE  := -DMODULE
 KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
 
+$(srctree)/scripts/module-common.lds: $(srctree)/scripts/module-common.lds.S
+	$(Q)$(CC) $(CFLAGS) $(INCLUDES) $(LINUXINCLUDE) -E -P \
+		-D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
+
 # Read KERNELRELEASE from include/config/kernel.release (if it exists)
 KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
 KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
@@ -1174,7 +1178,7 @@ all: modules
 # using awk while concatenating to the final file.
 
 PHONY += modules
-modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin
+modules: $(srctree)/scripts/module-common.lds $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin
 	$(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order
 	@$(kecho) '  Building modules, stage 2.';
 	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 1366a94b6c39..2d8aff7735d6 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -121,7 +121,7 @@ quiet_cmd_ld_ko_o = LD [M]  $@
                              $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
                              -o $@ $(filter-out FORCE,$^)
 
-$(modules): %.ko :%.o %.mod.o FORCE
+$(modules): %.ko : $(srctree)/scripts/module-common.lds %.o %.mod.o FORCE
 	$(call if_changed,ld_ko_o)
 
 targets += $(modules)
diff --git a/scripts/module-common.lds b/scripts/module-common.lds.S
similarity index 100%
rename from scripts/module-common.lds
rename to scripts/module-common.lds.S
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 03/16] scripts/module-common.lds: enable generation
@ 2016-08-19 21:32   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

scripts/module-common.lds is currently pretty static, in the
future this may change and we will want access to kernel macros
to help expands certain areas. To get access to use macros we
need to generate module-common.lds from module-common.lds.S, for
now though only enable the generation. We'll later expand on this
as needed.

Since this file is now generated add it to .gitignore.

v4: add file to MAINTAINERS
v3: new to this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 .gitignore                                         | 2 ++
 MAINTAINERS                                        | 1 +
 Makefile                                           | 6 +++++-
 scripts/Makefile.modpost                           | 2 +-
 scripts/{module-common.lds => module-common.lds.S} | 0
 5 files changed, 9 insertions(+), 2 deletions(-)
 rename scripts/{module-common.lds => module-common.lds.S} (100%)

diff --git a/.gitignore b/.gitignore
index c2ed4ecb0acd..0f0702054fdb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -114,3 +114,5 @@ all.config
 
 # Kdevelop4
 *.kdev4
+
+scripts/module-common.lds
diff --git a/MAINTAINERS b/MAINTAINERS
index d635ab047f3a..5aec01883020 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7887,6 +7887,7 @@ M:	Rusty Russell <rusty@rustcorp.com.au>
 S:	Maintained
 F:	include/linux/module.h
 F:	kernel/module.c
+F:	scripts/module-common.lds.S
 
 MOTION EYE VAIO PICTUREBOOK CAMERA DRIVER
 W:	http://popies.net/meye/
diff --git a/Makefile b/Makefile
index 5c18baad7218..b3e5ea78d582 100644
--- a/Makefile
+++ b/Makefile
@@ -408,6 +408,10 @@ KBUILD_AFLAGS_MODULE  := -DMODULE
 KBUILD_CFLAGS_MODULE  := -DMODULE
 KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
 
+$(srctree)/scripts/module-common.lds: $(srctree)/scripts/module-common.lds.S
+	$(Q)$(CC) $(CFLAGS) $(INCLUDES) $(LINUXINCLUDE) -E -P \
+		-D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
+
 # Read KERNELRELEASE from include/config/kernel.release (if it exists)
 KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
 KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
@@ -1174,7 +1178,7 @@ all: modules
 # using awk while concatenating to the final file.
 
 PHONY += modules
-modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin
+modules: $(srctree)/scripts/module-common.lds $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin
 	$(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order
 	@$(kecho) '  Building modules, stage 2.';
 	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 1366a94b6c39..2d8aff7735d6 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -121,7 +121,7 @@ quiet_cmd_ld_ko_o = LD [M]  $@
                              $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
                              -o $@ $(filter-out FORCE,$^)
 
-$(modules): %.ko :%.o %.mod.o FORCE
+$(modules): %.ko : $(srctree)/scripts/module-common.lds %.o %.mod.o FORCE
 	$(call if_changed,ld_ko_o)
 
 targets += $(modules)
diff --git a/scripts/module-common.lds b/scripts/module-common.lds.S
similarity index 100%
rename from scripts/module-common.lds
rename to scripts/module-common.lds.S
-- 
2.9.2


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 03/16] scripts/module-common.lds: enable generation
@ 2016-08-19 21:32   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

scripts/module-common.lds is currently pretty static, in the
future this may change and we will want access to kernel macros
to help expands certain areas. To get access to use macros we
need to generate module-common.lds from module-common.lds.S, for
now though only enable the generation. We'll later expand on this
as needed.

Since this file is now generated add it to .gitignore.

v4: add file to MAINTAINERS
v3: new to this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 .gitignore                                         | 2 ++
 MAINTAINERS                                        | 1 +
 Makefile                                           | 6 +++++-
 scripts/Makefile.modpost                           | 2 +-
 scripts/{module-common.lds => module-common.lds.S} | 0
 5 files changed, 9 insertions(+), 2 deletions(-)
 rename scripts/{module-common.lds => module-common.lds.S} (100%)

diff --git a/.gitignore b/.gitignore
index c2ed4ecb0acd..0f0702054fdb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -114,3 +114,5 @@ all.config
 
 # Kdevelop4
 *.kdev4
+
+scripts/module-common.lds
diff --git a/MAINTAINERS b/MAINTAINERS
index d635ab047f3a..5aec01883020 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7887,6 +7887,7 @@ M:	Rusty Russell <rusty@rustcorp.com.au>
 S:	Maintained
 F:	include/linux/module.h
 F:	kernel/module.c
+F:	scripts/module-common.lds.S
 
 MOTION EYE VAIO PICTUREBOOK CAMERA DRIVER
 W:	http://popies.net/meye/
diff --git a/Makefile b/Makefile
index 5c18baad7218..b3e5ea78d582 100644
--- a/Makefile
+++ b/Makefile
@@ -408,6 +408,10 @@ KBUILD_AFLAGS_MODULE  := -DMODULE
 KBUILD_CFLAGS_MODULE  := -DMODULE
 KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
 
+$(srctree)/scripts/module-common.lds: $(srctree)/scripts/module-common.lds.S
+	$(Q)$(CC) $(CFLAGS) $(INCLUDES) $(LINUXINCLUDE) -E -P \
+		-D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
+
 # Read KERNELRELEASE from include/config/kernel.release (if it exists)
 KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
 KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
@@ -1174,7 +1178,7 @@ all: modules
 # using awk while concatenating to the final file.
 
 PHONY += modules
-modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin
+modules: $(srctree)/scripts/module-common.lds $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin
 	$(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order
 	@$(kecho) '  Building modules, stage 2.';
 	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 1366a94b6c39..2d8aff7735d6 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -121,7 +121,7 @@ quiet_cmd_ld_ko_o = LD [M]  $@
                              $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
                              -o $@ $(filter-out FORCE,$^)
 
-$(modules): %.ko :%.o %.mod.o FORCE
+$(modules): %.ko : $(srctree)/scripts/module-common.lds %.o %.mod.o FORCE
 	$(call if_changed,ld_ko_o)
 
 targets += $(modules)
diff --git a/scripts/module-common.lds b/scripts/module-common.lds.S
similarity index 100%
rename from scripts/module-common.lds
rename to scripts/module-common.lds.S
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 04/16] generic-sections: add section core helpers
  2016-08-19 21:32 ` mcgrof
  (?)
@ 2016-08-19 21:32   ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Linux makes extensive use of custom ELF header sections,
documentation for these are well scatterred. Unify this
documentation in a central place and provide helpers to
build custom Linux sections.

This also generalizes sections code to enable avoiding
modifying the linker scripts when we want to add new
custom Linux sections. In order to make this generally
useful we need to ensure all architectures can make use of
core section helpers but that they can also override should
this be needed. Instead of relying on section.h this adds
a sections-core.h since this will be targetted to be safe
to be used on asm code, linker scripts and C code.

v4:

o Port to shiny new sphinx documentation format

o fix a unicore32 build, turns out this actually fixes unicore32
  defconfig builds which were failing for a long while. unicore32
  does not seem to grok well the type passed on a section declaration,
  this ignores it.

o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
  this was causing final linker issues with blackfin -- this is
  a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
  being metatag. metatag is not supported on 0-day so I cannot confirm
  compilation there.

o Added SECTION_CORE() for C code, used later by __LINUX_RANGE()

o Since SECTION_CORE() is defined for linker script and C code, share
  the same helper and just use a __stringify() for the C code as is done
  for the other C helpers.

o move generic sections to asm-generic/section-core.h instead.
  PowerPC compilation blows up if asm/jump_labels.h gets
  section.h included, fixing this is not in any way easy.
  The list of issues are endless. Moving new data to a new
  simple file resolves this.

o since things are now in asm-generic/section-core.h the
  guard changes on asm-generic/sections.h and each architecture
  sections.h are no longer needed

o Give generic sections some maintainer love, that change is
  Acked-by Arnd Bergmann, Josh and hpa.

o A few checkpatch.pl style fixes

o As suggested by James Hogan use generic-y to copy generic
  header files on architectures that do not have a sections.h
  instead of writing a simple file only to include the generic one.

v3:

o add missing sections.h for architectures that did not
  have it

o move generic sections to asm-generic/sections.h

o add generic asm helpers section_type(), section_type_asmtype(),
  push_section_type() -- these helpers enable easy use for
  for later declaring and using of custom linux sections using
  more standard APIs in both C code, asm code (C asm calls, or
  asm files), enabling future standardized section types to
  be more immediately accessible to asm code, not just C code.
  Note for ASM_CMD_SEP we use by default "\n", architectures needed
  to override can do so on their own sections.h prior to inclusion
  of asm-generic/sections.h

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/index.rst                   |   1 +
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  11 +
 Documentation/sections/section-core.rst   | 153 ++++++++++++++
 MAINTAINERS                               |  14 ++
 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/Kbuild               |   1 +
 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/section-core.h |  19 ++
 arch/x86/include/asm/Kbuild               |   1 +
 arch/xtensa/include/asm/Kbuild            |   1 +
 include/asm-generic/section-core.h        | 341 ++++++++++++++++++++++++++++++
 include/asm-generic/sections.h            |   2 +
 include/asm-generic/vmlinux.lds.h         |  27 +--
 include/linux/sections.h                  | 111 ++++++++++
 40 files changed, 700 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/linux/sections.h

diff --git a/Documentation/index.rst b/Documentation/index.rst
index a15f81855b39..10c9b867e326 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -14,6 +14,7 @@ Contents:
    kernel-documentation
    media/index
    gpu/index
+   sections/index
 
 Indices and tables
 =========
diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
new file mode 100644
index 000000000000..faa1c57595e1
--- /dev/null
+++ b/Documentation/sections/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel ELF sections'
+html_search_language = 'en'
diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
new file mode 100644
index 000000000000..d411e9b22eb3
--- /dev/null
+++ b/Documentation/sections/index.rst
@@ -0,0 +1,11 @@
+============+Linux Kernel ELF sections
+============+
+This book documents the Linux kernel's use of ELF sections, as well as helpers
+used throughout the kernel to help declare and define them.
+
+.. toctree::
+   :maxdepth: 4
+
+   section-core
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
new file mode 100644
index 000000000000..ecf4228bc4f8
--- /dev/null
+++ b/Documentation/sections/section-core.rst
@@ -0,0 +1,153 @@
+===============
+Core Linux kernel ELF sections
+===============
+
+About
+==+
+This book documents the different standard and custom ELF sections used
+on the Linux kernel, which we refer to as the ``core Linux sections``. We
+start off by documenting the standard ELF sections used by Linux and move
+on to the basic custom ELF sections, followed by a set of helpers. Each
+section documented describes the goal of the section, and addresses
+concurrency considerations when applicable.
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Custom linker script
+
+Standard ELF section use in Linux
+================+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Standard ELF section use in Linux
+
+SECTION_RODATA
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_RODATA
+
+SECTION_RODATA
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_TEXT
+
+SECTION_DATA
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_DATA
+
+Linux .init\* sections
+===========
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux init sections
+
+SECTION_INIT_DATA
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_INIT_DATA
+
+SECTION_INIT_RODATA
+-------------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_INIT_RODATA
+
+SECTION_INIT_CALL
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_INIT_CALL
+
+Linux .exit\* sections
+===========
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux exit sections
+
+SECTION_EXIT
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_EXIT
+
+SECTION_EXIT_DATA
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_EXIT_DATA
+
+SECTION_EXIT_CALL
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_EXIT_CALL
+
+Linux .ref\* sections
+==========+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux references to init sections
+
+SECTION_REF
+-----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_REF
+
+SECTION_REF_DATA
+----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_REF_DATA
+
+SECTION_REF_RODATA
+------------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_REF_RODATA
+
+Linux section ordering
+===========
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux section ordering
+
+SECTION_ORDER_ANY
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_ORDER_ANY
+
+Generic Linux kernel section helpers
+==================
+
+Introduction
+-------------
+.. kernel-doc:: include/linux/sections.h
+   :doc: Introduction
+
+LINUX_SECTION_ALIGNMENT
+-----------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_ALIGNMENT
+
+LINUX_SECTION_SIZE
+------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_SIZE
+
+LINUX_SECTION_EMPTY
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_EMPTY
+
+LINUX_SECTION_START
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_START
+
+LINUX_SECTION_END
+-----------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_END
+
+DECLARE_LINUX_SECTION
+---------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION
+
+DECLARE_LINUX_SECTION_RO
+------------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION_RO
diff --git a/MAINTAINERS b/MAINTAINERS
index 5aec01883020..689c12075842 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5217,6 +5217,20 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTIONS
+M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
+M:	Josh Poimboeuf <jpoimboe@redhat.com>
+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 for-arnd
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux-next.git for-arnd
+S:	Supported
+F:	include/asm-generic/section-core.h
+F:	include/asm-generic/sections.h
+F:	include/asm-generic/vmlinux.lds.h
+F:	Documentation/sections/section-core.rst
+
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index bf8475ce85ee..5422827f1585 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += section-core.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 0b10ef2a4372..9a0929576de1 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -50,3 +50,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 0745538b26d3..47923635be16 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += timex.h
 generic-y += trace_clock.h
 generic-y += unaligned.h
+generic-y += section-core.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index f43d2c44c765..42d00806e4fb 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -52,3 +52,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 241b9b9729d8..f2c3b656a0e7 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 91d49c0a3118..7de674411bed 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 64465e7e2245..38127ce747be 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -62,3 +62,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 1778805f6380..385cd88a9d9e 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += types.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 1fa084cf1a43..46d7c599d9b8 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 373cb23301e3..1ec04ec1c82b 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -75,3 +75,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index db8ddabc6bd2..37d7bfae7619 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -60,3 +60,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 502a91d8dbbd..672c6d5da18c 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 860e440611c9..6111e1523750 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index eb85bd9c6180..eef72c464c9b 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 29acb89daaaa..50ebd5a30d16 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -56,3 +56,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index b0ae88c9fed9..c6c2cf6edc98 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 9740066cc631..12f7c5984c03 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -20,3 +20,4 @@ generic-y += trace_clock.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 1c8dd0f5cd5d..f8145bc85835 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index d63330e88379..c9c7cb82b00f 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 2832f031fb11..86175e701869 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -71,3 +71,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index f9b3a81aefcd..6f43f33f0e0f 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index ab9f4e0ed4cf..b49fab7bab2f 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -7,3 +7,4 @@ generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
+generic-y += section-core.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 20f196b82a6e..89e74b59f32d 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index a05218ff3fe4..f089a264cd38 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 751c3373a92c..7b0356dca562 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index cfc918067f80..d51b84d6b4b7 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index ba35c41c71ff..7b8a652e43ae 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 904f3ebf4220..e9849834d55e 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -27,3 +27,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
new file mode 100644
index 000000000000..ebffeed8835d
--- /dev/null
+++ b/arch/unicore32/include/asm/section-core.h
@@ -0,0 +1,19 @@
+#ifndef __UNICORE_SECTION_CORE_ASM_H__
+#define __UNICORE_SECTION_CORE_ASM_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/.
+ */
+
+/* Unicore32 has known to not work properly with the type set, so ignore it */
+
+#define __set_section_core_type(___section, ___core, ___name,		\
+				___level, ___flags, ___type)		\
+	.section ___section.___core.___name.___level, ___flags
+
+#include <asm-generic/section-core.h>
+
+#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 2cfed174e3c9..f6914a57bc16 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -16,3 +16,4 @@ generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
+generic-y += section-core.h
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index 28cf4c5d65ef..81ca6816bd72 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -31,3 +31,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..2ab57e2c4117
--- /dev/null
+++ b/include/asm-generic/section-core.h
@@ -0,0 +1,341 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Custom linker script
+ *
+ * The Linux vmlinux binary uses a custom linker script on each architecture
+ * which it uses to strategically place standard ELF sections and also adds
+ * custom specialized ELF sections. Each architecture defines its own custom
+ * linker defined in arch/$(ARCH)/kernel/vmlinux.lds.S -- these in turn
+ * include and use definitions in include/asm-generic/vmlinux.lds.h as well
+ * as some helpers documented in this chaper.
+ */
+
+/**
+ * DOC: Standard ELF section use in Linux
+ *
+ * Linux makes use of the standard ELF sections, this sections documents
+ * these.
+ */
+
+/**
+ * DOC: SECTION_RODATA
+ *
+ * Macro name for code which must be protected from write access, read only
+ * data.
+ */
+#define SECTION_RODATA			.rodata
+
+/**
+ * DOC: SECTION_TEXT
+ *
+ * Macro name used to annotate code (functions) used during regular
+ * kernel run time. This is combined with `SECTION_RODATA`, only this
+ * section also allows for execution.
+ *
+ */
+#define SECTION_TEXT			.text
+
+/**
+ * DOC: SECTION_DATA
+ *
+ * Macro name for read-write data.
+ */
+#define SECTION_DATA			.data
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: SECTION_INIT
+ *
+ * Macro name used to annotate code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+#define SECTION_INIT			.init.text
+
+/**
+ * DOC: SECTION_INIT_DATA
+ *
+ * Macro name used to annotate data structures used only during boot or driver
+ * initialization.
+ */
+#define SECTION_INIT_DATA		.init.data
+
+/**
+ * DOC: SECTION_INIT_RODATA
+ *
+ * Macro name used to annotate read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+#define SECTION_INIT_RODATA		.init.rodata
+
+/**
+ * DOC: SECTION_INIT_CALL
+ *
+ * Special macro name used to annotate subsystem init call. These calls are
+ * are now grouped by functionality into separate subsections. Ordering inside
+ * the subsections is determined by link order.
+ */
+#define SECTION_INIT_CALL		.initcall
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: SECTION_EXIT
+ *
+ * Macro name used to annotate code (functions) used only during module
+ * unload.
+ */
+#define SECTION_EXIT			.exit.text
+
+/**
+ * DOC: SECTION_EXIT_DATA
+ *
+ * Macro name used to annotate data structures used only during module
+ * unload.
+ */
+#define SECTION_EXIT_DATA		.exit.data
+
+/**
+ * DOC: SECTION_EXIT_CALL
+ *
+ * Special macro name used to annotate an exit exit routine, order
+ * is important and maintained by link order.
+ */
+#define SECTION_EXIT_CALL		.exitcall.exit
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: SECTION_REF
+ *
+ * Macro name used to annotate that code (functions) declared with this section
+ * has been vetteed as valid for its reference or use of other code (functions)
+ * or data structures which are part of the init sections.
+ */
+#define SECTION_REF			.ref.text
+
+/**
+ * DOC: SECTION_REF_DATA
+ *
+ * Macro name used to annotate data structures declared with this section have
+ * been vetteed for its reference or use of other code (functions) or data
+ * structures part of the init sections.
+ */
+#define SECTION_REF_DATA		.ref.data
+
+/**
+ * DOC: SECTION_REF_RODATA
+ *
+ * Macro name used to annotate const code (functions) const data structures
+ * which has been vetteed for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+#define SECTION_REF_RODATA		.ref.rodata
+
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections. Linux has used 'SORT()' in ``include/asm-generic/vmlinux.lds.h``
+ * for years.
+ */
+
+/**
+ * DOC: SECTION_ORDER_ANY
+ *
+ * Macro name which can be used as helper to annotate custom section
+ * ordering at link time is not relevant for specific sections.
+ */
+#define SECTION_ORDER_ANY	any
+
+/*
+ * These section _ALL() helpers are for use on linker scripts and helpers
+ */
+#define SECTION_ALL(__section)						\
+	__section##.*
+
+#define __SECTION_CORE(__section, __core, __name, __level)		\
+	__section.__core.__name.__level
+
+#define SECTION_CORE_ALL(__section, __core)				\
+	__section##.##__core##.*
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section.___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section.___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section.__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifdef LINKER_SCRIPT
+
+#  ifndef SECTION_CORE
+#   define SECTION_CORE(__section, __core, __name, __level)		\
+	__SECTION_CORE(__section,__core,__name,__level)
+#  endif
+
+# else
+
+#  ifndef SECTION_CORE
+#   define SECTION_CORE(__section, __core, __name, __level)		\
+	push_section_core(__section, __core, __name, __level,)
+#  endif
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+# ifndef SECTION_CORE
+#  define SECTION_CORE(__section, __core, __name, __level)		\
+	__stringify(__SECTION_CORE(__section,__core,__name,__level))
+# endif
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align\x16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index af0254c09424..298252df3c81 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_GENERIC_SECTIONS_H_
 #define _ASM_GENERIC_SECTIONS_H_
 
+#include <asm/section-core.h>
+
 /* References to section boundaries */
 
 #include <linux/compiler.h>
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 24563970ff7b..731087276a32 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -55,6 +55,7 @@
 #endif
 
 #include <linux/export.h>
+#include <asm/section-core.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
@@ -198,8 +199,8 @@
 
 /* .data section */
 #define DATA_DATA							\
-	*(.data)							\
-	*(.ref.data)							\
+	*(SECTION_DATA)							\
+	*(SECTION_REF_DATA)						\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
 	MEM_KEEP(exit.data)						\
@@ -262,9 +263,9 @@
  */
 #define RO_DATA_SECTION(align)						\
 	. = ALIGN((align));						\
-	.rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {		\
+	SECTION_RODATA    : AT(ADDR(SECTION_RODATA) - LOAD_OFFSET) {	\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
-		*(.rodata) *(.rodata.*)					\
+		*(SECTION_RODATA) *(SECTION_ALL(SECTION_RODATA))	\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		*(__vermagic)		/* Kernel version magic */	\
 		. = ALIGN(8);						\
@@ -394,7 +395,7 @@
 									\
 	/* __*init sections */						\
 	__init_rodata : AT(ADDR(__init_rodata) - LOAD_OFFSET) {		\
-		*(.ref.rodata)						\
+		*(SECTION_REF_RODATA)					\
 		MEM_KEEP(init.rodata)					\
 		MEM_KEEP(exit.rodata)					\
 	}								\
@@ -432,8 +433,8 @@
  * during second ld run in second ld pass when generating System.map */
 #define TEXT_TEXT							\
 		ALIGN_FUNCTION();					\
-		*(.text.hot .text .text.fixup .text.unlikely)		\
-		*(.ref.text)						\
+		*(.text.hot SECTION_TEXT .text.fixup .text.unlikely)	\
+		*(SECTION_REF)						\
 	MEM_KEEP(init.text)						\
 	MEM_KEEP(exit.text)						\
 
@@ -527,11 +528,11 @@
 
 /* init and exit section handling */
 #define INIT_DATA							\
-	*(.init.data)							\
+	*(SECTION_INIT_DATA)						\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
-	*(.init.rodata)							\
+	*(SECTION_INIT_RODATA)						\
 	FTRACE_EVENTS()							\
 	TRACE_SYSCALLS()						\
 	KPROBE_BLACKLIST()						\
@@ -549,24 +550,24 @@
 	EARLYCON_TABLE()
 
 #define INIT_TEXT							\
-	*(.init.text)							\
+	*(SECTION_INIT)							\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
 #define EXIT_DATA							\
-	*(.exit.data)							\
+	*(SECTION_EXIT_DATA)						\
 	*(.fini_array)							\
 	*(.dtors)							\
 	MEM_DISCARD(exit.data)						\
 	MEM_DISCARD(exit.rodata)
 
 #define EXIT_TEXT							\
-	*(.exit.text)							\
+	*(SECTION_EXIT)							\
 	*(.text.exit)							\
 	MEM_DISCARD(exit.text)
 
 #define EXIT_CALL							\
-	*(.exitcall.exit)
+	*(SECTION_EXIT_CALL)
 
 /*
  * bss (Block Started by Symbol) - uninitialized data
diff --git a/include/linux/sections.h b/include/linux/sections.h
new file mode 100644
index 000000000000..f21c6ee88ded
--- /dev/null
+++ b/include/linux/sections.h
@@ -0,0 +1,111 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_SIZE - get number of entries in the section
+ *
+ * @name: section name
+ *
+ * This gives you the number of entries in the section.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINUX_SECTION_SIZE(frobnicator_fns);
+ */
+#define LINUX_SECTION_SIZE(name)					\
+	((VMLINUX_SYMBOL(name##__end)) - (VMLINUX_SYMBOL(name)))
+
+/**
+ * LINUX_SECTION_EMPTY - check if section has no entries
+ *
+ * @name: section name
+ *
+ * Returns true if section is emtpy.
+ *
+ *   bool is_empty = LINUX_SECTION_EMPTY(frobnicator_fns);
+ */
+#define LINUX_SECTION_EMPTY(name)	(LINUX_SECTION_SIZE(name) = 0)
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_TYPE(section, type, name, level)			\
+	#section "." #type "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-19 21:32   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Linux makes extensive use of custom ELF header sections,
documentation for these are well scatterred. Unify this
documentation in a central place and provide helpers to
build custom Linux sections.

This also generalizes sections code to enable avoiding
modifying the linker scripts when we want to add new
custom Linux sections. In order to make this generally
useful we need to ensure all architectures can make use of
core section helpers but that they can also override should
this be needed. Instead of relying on section.h this adds
a sections-core.h since this will be targetted to be safe
to be used on asm code, linker scripts and C code.

v4:

o Port to shiny new sphinx documentation format

o fix a unicore32 build, turns out this actually fixes unicore32
  defconfig builds which were failing for a long while. unicore32
  does not seem to grok well the type passed on a section declaration,
  this ignores it.

o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
  this was causing final linker issues with blackfin -- this is
  a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
  being metatag. metatag is not supported on 0-day so I cannot confirm
  compilation there.

o Added SECTION_CORE() for C code, used later by __LINUX_RANGE()

o Since SECTION_CORE() is defined for linker script and C code, share
  the same helper and just use a __stringify() for the C code as is done
  for the other C helpers.

o move generic sections to asm-generic/section-core.h instead.
  PowerPC compilation blows up if asm/jump_labels.h gets
  section.h included, fixing this is not in any way easy.
  The list of issues are endless. Moving new data to a new
  simple file resolves this.

o since things are now in asm-generic/section-core.h the
  guard changes on asm-generic/sections.h and each architecture
  sections.h are no longer needed

o Give generic sections some maintainer love, that change is
  Acked-by Arnd Bergmann, Josh and hpa.

o A few checkpatch.pl style fixes

o As suggested by James Hogan use generic-y to copy generic
  header files on architectures that do not have a sections.h
  instead of writing a simple file only to include the generic one.

v3:

o add missing sections.h for architectures that did not
  have it

o move generic sections to asm-generic/sections.h

o add generic asm helpers section_type(), section_type_asmtype(),
  push_section_type() -- these helpers enable easy use for
  for later declaring and using of custom linux sections using
  more standard APIs in both C code, asm code (C asm calls, or
  asm files), enabling future standardized section types to
  be more immediately accessible to asm code, not just C code.
  Note for ASM_CMD_SEP we use by default "\n", architectures needed
  to override can do so on their own sections.h prior to inclusion
  of asm-generic/sections.h

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/index.rst                   |   1 +
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  11 +
 Documentation/sections/section-core.rst   | 153 ++++++++++++++
 MAINTAINERS                               |  14 ++
 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/Kbuild               |   1 +
 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/section-core.h |  19 ++
 arch/x86/include/asm/Kbuild               |   1 +
 arch/xtensa/include/asm/Kbuild            |   1 +
 include/asm-generic/section-core.h        | 341 ++++++++++++++++++++++++++++++
 include/asm-generic/sections.h            |   2 +
 include/asm-generic/vmlinux.lds.h         |  27 +--
 include/linux/sections.h                  | 111 ++++++++++
 40 files changed, 700 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/linux/sections.h

diff --git a/Documentation/index.rst b/Documentation/index.rst
index a15f81855b39..10c9b867e326 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -14,6 +14,7 @@ Contents:
    kernel-documentation
    media/index
    gpu/index
+   sections/index
 
 Indices and tables
 ==================
diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
new file mode 100644
index 000000000000..faa1c57595e1
--- /dev/null
+++ b/Documentation/sections/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel ELF sections'
+html_search_language = 'en'
diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
new file mode 100644
index 000000000000..d411e9b22eb3
--- /dev/null
+++ b/Documentation/sections/index.rst
@@ -0,0 +1,11 @@
+=========================
+Linux Kernel ELF sections
+=========================
+
+This book documents the Linux kernel's use of ELF sections, as well as helpers
+used throughout the kernel to help declare and define them.
+
+.. toctree::
+   :maxdepth: 4
+
+   section-core
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
new file mode 100644
index 000000000000..ecf4228bc4f8
--- /dev/null
+++ b/Documentation/sections/section-core.rst
@@ -0,0 +1,153 @@
+==============================
+Core Linux kernel ELF sections
+==============================
+
+About
+=====
+
+This book documents the different standard and custom ELF sections used
+on the Linux kernel, which we refer to as the ``core Linux sections``. We
+start off by documenting the standard ELF sections used by Linux and move
+on to the basic custom ELF sections, followed by a set of helpers. Each
+section documented describes the goal of the section, and addresses
+concurrency considerations when applicable.
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Custom linker script
+
+Standard ELF section use in Linux
+=================================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Standard ELF section use in Linux
+
+SECTION_RODATA
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_RODATA
+
+SECTION_RODATA
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_TEXT
+
+SECTION_DATA
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_DATA
+
+Linux .init\* sections
+======================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux init sections
+
+SECTION_INIT_DATA
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_INIT_DATA
+
+SECTION_INIT_RODATA
+-------------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_INIT_RODATA
+
+SECTION_INIT_CALL
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_INIT_CALL
+
+Linux .exit\* sections
+======================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux exit sections
+
+SECTION_EXIT
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_EXIT
+
+SECTION_EXIT_DATA
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_EXIT_DATA
+
+SECTION_EXIT_CALL
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_EXIT_CALL
+
+Linux .ref\* sections
+=====================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux references to init sections
+
+SECTION_REF
+-----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_REF
+
+SECTION_REF_DATA
+----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_REF_DATA
+
+SECTION_REF_RODATA
+------------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_REF_RODATA
+
+Linux section ordering
+======================
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux section ordering
+
+SECTION_ORDER_ANY
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_ORDER_ANY
+
+Generic Linux kernel section helpers
+====================================
+
+Introduction
+-------------
+.. kernel-doc:: include/linux/sections.h
+   :doc: Introduction
+
+LINUX_SECTION_ALIGNMENT
+-----------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_ALIGNMENT
+
+LINUX_SECTION_SIZE
+------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_SIZE
+
+LINUX_SECTION_EMPTY
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_EMPTY
+
+LINUX_SECTION_START
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_START
+
+LINUX_SECTION_END
+-----------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_END
+
+DECLARE_LINUX_SECTION
+---------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION
+
+DECLARE_LINUX_SECTION_RO
+------------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION_RO
diff --git a/MAINTAINERS b/MAINTAINERS
index 5aec01883020..689c12075842 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5217,6 +5217,20 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTIONS
+M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
+M:	Josh Poimboeuf <jpoimboe@redhat.com>
+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 for-arnd
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux-next.git for-arnd
+S:	Supported
+F:	include/asm-generic/section-core.h
+F:	include/asm-generic/sections.h
+F:	include/asm-generic/vmlinux.lds.h
+F:	Documentation/sections/section-core.rst
+
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index bf8475ce85ee..5422827f1585 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += section-core.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 0b10ef2a4372..9a0929576de1 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -50,3 +50,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 0745538b26d3..47923635be16 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += timex.h
 generic-y += trace_clock.h
 generic-y += unaligned.h
+generic-y += section-core.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index f43d2c44c765..42d00806e4fb 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -52,3 +52,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 241b9b9729d8..f2c3b656a0e7 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 91d49c0a3118..7de674411bed 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 64465e7e2245..38127ce747be 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -62,3 +62,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 1778805f6380..385cd88a9d9e 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += types.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 1fa084cf1a43..46d7c599d9b8 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 373cb23301e3..1ec04ec1c82b 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -75,3 +75,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index db8ddabc6bd2..37d7bfae7619 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -60,3 +60,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 502a91d8dbbd..672c6d5da18c 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 860e440611c9..6111e1523750 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index eb85bd9c6180..eef72c464c9b 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 29acb89daaaa..50ebd5a30d16 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -56,3 +56,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index b0ae88c9fed9..c6c2cf6edc98 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 9740066cc631..12f7c5984c03 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -20,3 +20,4 @@ generic-y += trace_clock.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 1c8dd0f5cd5d..f8145bc85835 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index d63330e88379..c9c7cb82b00f 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 2832f031fb11..86175e701869 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -71,3 +71,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index f9b3a81aefcd..6f43f33f0e0f 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index ab9f4e0ed4cf..b49fab7bab2f 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -7,3 +7,4 @@ generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
+generic-y += section-core.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 20f196b82a6e..89e74b59f32d 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index a05218ff3fe4..f089a264cd38 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 751c3373a92c..7b0356dca562 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index cfc918067f80..d51b84d6b4b7 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index ba35c41c71ff..7b8a652e43ae 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 904f3ebf4220..e9849834d55e 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -27,3 +27,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
new file mode 100644
index 000000000000..ebffeed8835d
--- /dev/null
+++ b/arch/unicore32/include/asm/section-core.h
@@ -0,0 +1,19 @@
+#ifndef __UNICORE_SECTION_CORE_ASM_H__
+#define __UNICORE_SECTION_CORE_ASM_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/.
+ */
+
+/* Unicore32 has known to not work properly with the type set, so ignore it */
+
+#define __set_section_core_type(___section, ___core, ___name,		\
+				___level, ___flags, ___type)		\
+	.section ___section.___core.___name.___level, ___flags
+
+#include <asm-generic/section-core.h>
+
+#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 2cfed174e3c9..f6914a57bc16 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -16,3 +16,4 @@ generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
+generic-y += section-core.h
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index 28cf4c5d65ef..81ca6816bd72 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -31,3 +31,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..2ab57e2c4117
--- /dev/null
+++ b/include/asm-generic/section-core.h
@@ -0,0 +1,341 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Custom linker script
+ *
+ * The Linux vmlinux binary uses a custom linker script on each architecture
+ * which it uses to strategically place standard ELF sections and also adds
+ * custom specialized ELF sections. Each architecture defines its own custom
+ * linker defined in arch/$(ARCH)/kernel/vmlinux.lds.S -- these in turn
+ * include and use definitions in include/asm-generic/vmlinux.lds.h as well
+ * as some helpers documented in this chaper.
+ */
+
+/**
+ * DOC: Standard ELF section use in Linux
+ *
+ * Linux makes use of the standard ELF sections, this sections documents
+ * these.
+ */
+
+/**
+ * DOC: SECTION_RODATA
+ *
+ * Macro name for code which must be protected from write access, read only
+ * data.
+ */
+#define SECTION_RODATA			.rodata
+
+/**
+ * DOC: SECTION_TEXT
+ *
+ * Macro name used to annotate code (functions) used during regular
+ * kernel run time. This is combined with `SECTION_RODATA`, only this
+ * section also allows for execution.
+ *
+ */
+#define SECTION_TEXT			.text
+
+/**
+ * DOC: SECTION_DATA
+ *
+ * Macro name for read-write data.
+ */
+#define SECTION_DATA			.data
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: SECTION_INIT
+ *
+ * Macro name used to annotate code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+#define SECTION_INIT			.init.text
+
+/**
+ * DOC: SECTION_INIT_DATA
+ *
+ * Macro name used to annotate data structures used only during boot or driver
+ * initialization.
+ */
+#define SECTION_INIT_DATA		.init.data
+
+/**
+ * DOC: SECTION_INIT_RODATA
+ *
+ * Macro name used to annotate read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+#define SECTION_INIT_RODATA		.init.rodata
+
+/**
+ * DOC: SECTION_INIT_CALL
+ *
+ * Special macro name used to annotate subsystem init call. These calls are
+ * are now grouped by functionality into separate subsections. Ordering inside
+ * the subsections is determined by link order.
+ */
+#define SECTION_INIT_CALL		.initcall
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: SECTION_EXIT
+ *
+ * Macro name used to annotate code (functions) used only during module
+ * unload.
+ */
+#define SECTION_EXIT			.exit.text
+
+/**
+ * DOC: SECTION_EXIT_DATA
+ *
+ * Macro name used to annotate data structures used only during module
+ * unload.
+ */
+#define SECTION_EXIT_DATA		.exit.data
+
+/**
+ * DOC: SECTION_EXIT_CALL
+ *
+ * Special macro name used to annotate an exit exit routine, order
+ * is important and maintained by link order.
+ */
+#define SECTION_EXIT_CALL		.exitcall.exit
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: SECTION_REF
+ *
+ * Macro name used to annotate that code (functions) declared with this section
+ * has been vetteed as valid for its reference or use of other code (functions)
+ * or data structures which are part of the init sections.
+ */
+#define SECTION_REF			.ref.text
+
+/**
+ * DOC: SECTION_REF_DATA
+ *
+ * Macro name used to annotate data structures declared with this section have
+ * been vetteed for its reference or use of other code (functions) or data
+ * structures part of the init sections.
+ */
+#define SECTION_REF_DATA		.ref.data
+
+/**
+ * DOC: SECTION_REF_RODATA
+ *
+ * Macro name used to annotate const code (functions) const data structures
+ * which has been vetteed for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+#define SECTION_REF_RODATA		.ref.rodata
+
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections. Linux has used 'SORT()' in ``include/asm-generic/vmlinux.lds.h``
+ * for years.
+ */
+
+/**
+ * DOC: SECTION_ORDER_ANY
+ *
+ * Macro name which can be used as helper to annotate custom section
+ * ordering at link time is not relevant for specific sections.
+ */
+#define SECTION_ORDER_ANY	any
+
+/*
+ * These section _ALL() helpers are for use on linker scripts and helpers
+ */
+#define SECTION_ALL(__section)						\
+	__section##.*
+
+#define __SECTION_CORE(__section, __core, __name, __level)		\
+	__section.__core.__name.__level
+
+#define SECTION_CORE_ALL(__section, __core)				\
+	__section##.##__core##.*
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section.___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section.___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section.__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifdef LINKER_SCRIPT
+
+#  ifndef SECTION_CORE
+#   define SECTION_CORE(__section, __core, __name, __level)		\
+	__SECTION_CORE(__section,__core,__name,__level)
+#  endif
+
+# else
+
+#  ifndef SECTION_CORE
+#   define SECTION_CORE(__section, __core, __name, __level)		\
+	push_section_core(__section, __core, __name, __level,)
+#  endif
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+# ifndef SECTION_CORE
+#  define SECTION_CORE(__section, __core, __name, __level)		\
+	__stringify(__SECTION_CORE(__section,__core,__name,__level))
+# endif
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align=16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index af0254c09424..298252df3c81 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_GENERIC_SECTIONS_H_
 #define _ASM_GENERIC_SECTIONS_H_
 
+#include <asm/section-core.h>
+
 /* References to section boundaries */
 
 #include <linux/compiler.h>
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 24563970ff7b..731087276a32 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -55,6 +55,7 @@
 #endif
 
 #include <linux/export.h>
+#include <asm/section-core.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
@@ -198,8 +199,8 @@
 
 /* .data section */
 #define DATA_DATA							\
-	*(.data)							\
-	*(.ref.data)							\
+	*(SECTION_DATA)							\
+	*(SECTION_REF_DATA)						\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
 	MEM_KEEP(exit.data)						\
@@ -262,9 +263,9 @@
  */
 #define RO_DATA_SECTION(align)						\
 	. = ALIGN((align));						\
-	.rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {		\
+	SECTION_RODATA    : AT(ADDR(SECTION_RODATA) - LOAD_OFFSET) {	\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
-		*(.rodata) *(.rodata.*)					\
+		*(SECTION_RODATA) *(SECTION_ALL(SECTION_RODATA))	\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		*(__vermagic)		/* Kernel version magic */	\
 		. = ALIGN(8);						\
@@ -394,7 +395,7 @@
 									\
 	/* __*init sections */						\
 	__init_rodata : AT(ADDR(__init_rodata) - LOAD_OFFSET) {		\
-		*(.ref.rodata)						\
+		*(SECTION_REF_RODATA)					\
 		MEM_KEEP(init.rodata)					\
 		MEM_KEEP(exit.rodata)					\
 	}								\
@@ -432,8 +433,8 @@
  * during second ld run in second ld pass when generating System.map */
 #define TEXT_TEXT							\
 		ALIGN_FUNCTION();					\
-		*(.text.hot .text .text.fixup .text.unlikely)		\
-		*(.ref.text)						\
+		*(.text.hot SECTION_TEXT .text.fixup .text.unlikely)	\
+		*(SECTION_REF)						\
 	MEM_KEEP(init.text)						\
 	MEM_KEEP(exit.text)						\
 
@@ -527,11 +528,11 @@
 
 /* init and exit section handling */
 #define INIT_DATA							\
-	*(.init.data)							\
+	*(SECTION_INIT_DATA)						\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
-	*(.init.rodata)							\
+	*(SECTION_INIT_RODATA)						\
 	FTRACE_EVENTS()							\
 	TRACE_SYSCALLS()						\
 	KPROBE_BLACKLIST()						\
@@ -549,24 +550,24 @@
 	EARLYCON_TABLE()
 
 #define INIT_TEXT							\
-	*(.init.text)							\
+	*(SECTION_INIT)							\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
 #define EXIT_DATA							\
-	*(.exit.data)							\
+	*(SECTION_EXIT_DATA)						\
 	*(.fini_array)							\
 	*(.dtors)							\
 	MEM_DISCARD(exit.data)						\
 	MEM_DISCARD(exit.rodata)
 
 #define EXIT_TEXT							\
-	*(.exit.text)							\
+	*(SECTION_EXIT)							\
 	*(.text.exit)							\
 	MEM_DISCARD(exit.text)
 
 #define EXIT_CALL							\
-	*(.exitcall.exit)
+	*(SECTION_EXIT_CALL)
 
 /*
  * bss (Block Started by Symbol) - uninitialized data
diff --git a/include/linux/sections.h b/include/linux/sections.h
new file mode 100644
index 000000000000..f21c6ee88ded
--- /dev/null
+++ b/include/linux/sections.h
@@ -0,0 +1,111 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_SIZE - get number of entries in the section
+ *
+ * @name: section name
+ *
+ * This gives you the number of entries in the section.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINUX_SECTION_SIZE(frobnicator_fns);
+ */
+#define LINUX_SECTION_SIZE(name)					\
+	((VMLINUX_SYMBOL(name##__end)) - (VMLINUX_SYMBOL(name)))
+
+/**
+ * LINUX_SECTION_EMPTY - check if section has no entries
+ *
+ * @name: section name
+ *
+ * Returns true if section is emtpy.
+ *
+ *   bool is_empty = LINUX_SECTION_EMPTY(frobnicator_fns);
+ */
+#define LINUX_SECTION_EMPTY(name)	(LINUX_SECTION_SIZE(name) == 0)
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_TYPE(section, type, name, level)			\
+	#section "." #type "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
-- 
2.9.2


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-19 21:32   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Linux makes extensive use of custom ELF header sections,
documentation for these are well scatterred. Unify this
documentation in a central place and provide helpers to
build custom Linux sections.

This also generalizes sections code to enable avoiding
modifying the linker scripts when we want to add new
custom Linux sections. In order to make this generally
useful we need to ensure all architectures can make use of
core section helpers but that they can also override should
this be needed. Instead of relying on section.h this adds
a sections-core.h since this will be targetted to be safe
to be used on asm code, linker scripts and C code.

v4:

o Port to shiny new sphinx documentation format

o fix a unicore32 build, turns out this actually fixes unicore32
  defconfig builds which were failing for a long while. unicore32
  does not seem to grok well the type passed on a section declaration,
  this ignores it.

o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
  this was causing final linker issues with blackfin -- this is
  a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
  being metatag. metatag is not supported on 0-day so I cannot confirm
  compilation there.

o Added SECTION_CORE() for C code, used later by __LINUX_RANGE()

o Since SECTION_CORE() is defined for linker script and C code, share
  the same helper and just use a __stringify() for the C code as is done
  for the other C helpers.

o move generic sections to asm-generic/section-core.h instead.
  PowerPC compilation blows up if asm/jump_labels.h gets
  section.h included, fixing this is not in any way easy.
  The list of issues are endless. Moving new data to a new
  simple file resolves this.

o since things are now in asm-generic/section-core.h the
  guard changes on asm-generic/sections.h and each architecture
  sections.h are no longer needed

o Give generic sections some maintainer love, that change is
  Acked-by Arnd Bergmann, Josh and hpa.

o A few checkpatch.pl style fixes

o As suggested by James Hogan use generic-y to copy generic
  header files on architectures that do not have a sections.h
  instead of writing a simple file only to include the generic one.

v3:

o add missing sections.h for architectures that did not
  have it

o move generic sections to asm-generic/sections.h

o add generic asm helpers section_type(), section_type_asmtype(),
  push_section_type() -- these helpers enable easy use for
  for later declaring and using of custom linux sections using
  more standard APIs in both C code, asm code (C asm calls, or
  asm files), enabling future standardized section types to
  be more immediately accessible to asm code, not just C code.
  Note for ASM_CMD_SEP we use by default "\n", architectures needed
  to override can do so on their own sections.h prior to inclusion
  of asm-generic/sections.h

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/index.rst                   |   1 +
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  11 +
 Documentation/sections/section-core.rst   | 153 ++++++++++++++
 MAINTAINERS                               |  14 ++
 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/Kbuild               |   1 +
 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/section-core.h |  19 ++
 arch/x86/include/asm/Kbuild               |   1 +
 arch/xtensa/include/asm/Kbuild            |   1 +
 include/asm-generic/section-core.h        | 341 ++++++++++++++++++++++++++++++
 include/asm-generic/sections.h            |   2 +
 include/asm-generic/vmlinux.lds.h         |  27 +--
 include/linux/sections.h                  | 111 ++++++++++
 40 files changed, 700 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/linux/sections.h

diff --git a/Documentation/index.rst b/Documentation/index.rst
index a15f81855b39..10c9b867e326 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -14,6 +14,7 @@ Contents:
    kernel-documentation
    media/index
    gpu/index
+   sections/index
 
 Indices and tables
 ==================
diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
new file mode 100644
index 000000000000..faa1c57595e1
--- /dev/null
+++ b/Documentation/sections/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel ELF sections'
+html_search_language = 'en'
diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
new file mode 100644
index 000000000000..d411e9b22eb3
--- /dev/null
+++ b/Documentation/sections/index.rst
@@ -0,0 +1,11 @@
+=========================
+Linux Kernel ELF sections
+=========================
+
+This book documents the Linux kernel's use of ELF sections, as well as helpers
+used throughout the kernel to help declare and define them.
+
+.. toctree::
+   :maxdepth: 4
+
+   section-core
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
new file mode 100644
index 000000000000..ecf4228bc4f8
--- /dev/null
+++ b/Documentation/sections/section-core.rst
@@ -0,0 +1,153 @@
+==============================
+Core Linux kernel ELF sections
+==============================
+
+About
+=====
+
+This book documents the different standard and custom ELF sections used
+on the Linux kernel, which we refer to as the ``core Linux sections``. We
+start off by documenting the standard ELF sections used by Linux and move
+on to the basic custom ELF sections, followed by a set of helpers. Each
+section documented describes the goal of the section, and addresses
+concurrency considerations when applicable.
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Custom linker script
+
+Standard ELF section use in Linux
+=================================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Standard ELF section use in Linux
+
+SECTION_RODATA
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_RODATA
+
+SECTION_RODATA
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_TEXT
+
+SECTION_DATA
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_DATA
+
+Linux .init\* sections
+======================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux init sections
+
+SECTION_INIT_DATA
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_INIT_DATA
+
+SECTION_INIT_RODATA
+-------------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_INIT_RODATA
+
+SECTION_INIT_CALL
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_INIT_CALL
+
+Linux .exit\* sections
+======================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux exit sections
+
+SECTION_EXIT
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_EXIT
+
+SECTION_EXIT_DATA
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_EXIT_DATA
+
+SECTION_EXIT_CALL
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_EXIT_CALL
+
+Linux .ref\* sections
+=====================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux references to init sections
+
+SECTION_REF
+-----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_REF
+
+SECTION_REF_DATA
+----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_REF_DATA
+
+SECTION_REF_RODATA
+------------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_REF_RODATA
+
+Linux section ordering
+======================
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux section ordering
+
+SECTION_ORDER_ANY
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_ORDER_ANY
+
+Generic Linux kernel section helpers
+====================================
+
+Introduction
+-------------
+.. kernel-doc:: include/linux/sections.h
+   :doc: Introduction
+
+LINUX_SECTION_ALIGNMENT
+-----------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_ALIGNMENT
+
+LINUX_SECTION_SIZE
+------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_SIZE
+
+LINUX_SECTION_EMPTY
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_EMPTY
+
+LINUX_SECTION_START
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_START
+
+LINUX_SECTION_END
+-----------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_END
+
+DECLARE_LINUX_SECTION
+---------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION
+
+DECLARE_LINUX_SECTION_RO
+------------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION_RO
diff --git a/MAINTAINERS b/MAINTAINERS
index 5aec01883020..689c12075842 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5217,6 +5217,20 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTIONS
+M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
+M:	Josh Poimboeuf <jpoimboe@redhat.com>
+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 for-arnd
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux-next.git for-arnd
+S:	Supported
+F:	include/asm-generic/section-core.h
+F:	include/asm-generic/sections.h
+F:	include/asm-generic/vmlinux.lds.h
+F:	Documentation/sections/section-core.rst
+
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index bf8475ce85ee..5422827f1585 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += section-core.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 0b10ef2a4372..9a0929576de1 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -50,3 +50,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 0745538b26d3..47923635be16 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += timex.h
 generic-y += trace_clock.h
 generic-y += unaligned.h
+generic-y += section-core.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index f43d2c44c765..42d00806e4fb 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -52,3 +52,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 241b9b9729d8..f2c3b656a0e7 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 91d49c0a3118..7de674411bed 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 64465e7e2245..38127ce747be 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -62,3 +62,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 1778805f6380..385cd88a9d9e 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += types.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 1fa084cf1a43..46d7c599d9b8 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 373cb23301e3..1ec04ec1c82b 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -75,3 +75,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index db8ddabc6bd2..37d7bfae7619 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -60,3 +60,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 502a91d8dbbd..672c6d5da18c 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 860e440611c9..6111e1523750 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index eb85bd9c6180..eef72c464c9b 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 29acb89daaaa..50ebd5a30d16 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -56,3 +56,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index b0ae88c9fed9..c6c2cf6edc98 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 9740066cc631..12f7c5984c03 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -20,3 +20,4 @@ generic-y += trace_clock.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 1c8dd0f5cd5d..f8145bc85835 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index d63330e88379..c9c7cb82b00f 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 2832f031fb11..86175e701869 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -71,3 +71,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index f9b3a81aefcd..6f43f33f0e0f 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index ab9f4e0ed4cf..b49fab7bab2f 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -7,3 +7,4 @@ generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
+generic-y += section-core.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 20f196b82a6e..89e74b59f32d 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index a05218ff3fe4..f089a264cd38 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 751c3373a92c..7b0356dca562 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index cfc918067f80..d51b84d6b4b7 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index ba35c41c71ff..7b8a652e43ae 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 904f3ebf4220..e9849834d55e 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -27,3 +27,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
new file mode 100644
index 000000000000..ebffeed8835d
--- /dev/null
+++ b/arch/unicore32/include/asm/section-core.h
@@ -0,0 +1,19 @@
+#ifndef __UNICORE_SECTION_CORE_ASM_H__
+#define __UNICORE_SECTION_CORE_ASM_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/.
+ */
+
+/* Unicore32 has known to not work properly with the type set, so ignore it */
+
+#define __set_section_core_type(___section, ___core, ___name,		\
+				___level, ___flags, ___type)		\
+	.section ___section.___core.___name.___level, ___flags
+
+#include <asm-generic/section-core.h>
+
+#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 2cfed174e3c9..f6914a57bc16 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -16,3 +16,4 @@ generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
+generic-y += section-core.h
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index 28cf4c5d65ef..81ca6816bd72 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -31,3 +31,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..2ab57e2c4117
--- /dev/null
+++ b/include/asm-generic/section-core.h
@@ -0,0 +1,341 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Custom linker script
+ *
+ * The Linux vmlinux binary uses a custom linker script on each architecture
+ * which it uses to strategically place standard ELF sections and also adds
+ * custom specialized ELF sections. Each architecture defines its own custom
+ * linker defined in arch/$(ARCH)/kernel/vmlinux.lds.S -- these in turn
+ * include and use definitions in include/asm-generic/vmlinux.lds.h as well
+ * as some helpers documented in this chaper.
+ */
+
+/**
+ * DOC: Standard ELF section use in Linux
+ *
+ * Linux makes use of the standard ELF sections, this sections documents
+ * these.
+ */
+
+/**
+ * DOC: SECTION_RODATA
+ *
+ * Macro name for code which must be protected from write access, read only
+ * data.
+ */
+#define SECTION_RODATA			.rodata
+
+/**
+ * DOC: SECTION_TEXT
+ *
+ * Macro name used to annotate code (functions) used during regular
+ * kernel run time. This is combined with `SECTION_RODATA`, only this
+ * section also allows for execution.
+ *
+ */
+#define SECTION_TEXT			.text
+
+/**
+ * DOC: SECTION_DATA
+ *
+ * Macro name for read-write data.
+ */
+#define SECTION_DATA			.data
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: SECTION_INIT
+ *
+ * Macro name used to annotate code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+#define SECTION_INIT			.init.text
+
+/**
+ * DOC: SECTION_INIT_DATA
+ *
+ * Macro name used to annotate data structures used only during boot or driver
+ * initialization.
+ */
+#define SECTION_INIT_DATA		.init.data
+
+/**
+ * DOC: SECTION_INIT_RODATA
+ *
+ * Macro name used to annotate read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+#define SECTION_INIT_RODATA		.init.rodata
+
+/**
+ * DOC: SECTION_INIT_CALL
+ *
+ * Special macro name used to annotate subsystem init call. These calls are
+ * are now grouped by functionality into separate subsections. Ordering inside
+ * the subsections is determined by link order.
+ */
+#define SECTION_INIT_CALL		.initcall
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: SECTION_EXIT
+ *
+ * Macro name used to annotate code (functions) used only during module
+ * unload.
+ */
+#define SECTION_EXIT			.exit.text
+
+/**
+ * DOC: SECTION_EXIT_DATA
+ *
+ * Macro name used to annotate data structures used only during module
+ * unload.
+ */
+#define SECTION_EXIT_DATA		.exit.data
+
+/**
+ * DOC: SECTION_EXIT_CALL
+ *
+ * Special macro name used to annotate an exit exit routine, order
+ * is important and maintained by link order.
+ */
+#define SECTION_EXIT_CALL		.exitcall.exit
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: SECTION_REF
+ *
+ * Macro name used to annotate that code (functions) declared with this section
+ * has been vetteed as valid for its reference or use of other code (functions)
+ * or data structures which are part of the init sections.
+ */
+#define SECTION_REF			.ref.text
+
+/**
+ * DOC: SECTION_REF_DATA
+ *
+ * Macro name used to annotate data structures declared with this section have
+ * been vetteed for its reference or use of other code (functions) or data
+ * structures part of the init sections.
+ */
+#define SECTION_REF_DATA		.ref.data
+
+/**
+ * DOC: SECTION_REF_RODATA
+ *
+ * Macro name used to annotate const code (functions) const data structures
+ * which has been vetteed for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+#define SECTION_REF_RODATA		.ref.rodata
+
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections. Linux has used 'SORT()' in ``include/asm-generic/vmlinux.lds.h``
+ * for years.
+ */
+
+/**
+ * DOC: SECTION_ORDER_ANY
+ *
+ * Macro name which can be used as helper to annotate custom section
+ * ordering at link time is not relevant for specific sections.
+ */
+#define SECTION_ORDER_ANY	any
+
+/*
+ * These section _ALL() helpers are for use on linker scripts and helpers
+ */
+#define SECTION_ALL(__section)						\
+	__section##.*
+
+#define __SECTION_CORE(__section, __core, __name, __level)		\
+	__section.__core.__name.__level
+
+#define SECTION_CORE_ALL(__section, __core)				\
+	__section##.##__core##.*
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section.___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section.___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section.__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifdef LINKER_SCRIPT
+
+#  ifndef SECTION_CORE
+#   define SECTION_CORE(__section, __core, __name, __level)		\
+	__SECTION_CORE(__section,__core,__name,__level)
+#  endif
+
+# else
+
+#  ifndef SECTION_CORE
+#   define SECTION_CORE(__section, __core, __name, __level)		\
+	push_section_core(__section, __core, __name, __level,)
+#  endif
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+# ifndef SECTION_CORE
+#  define SECTION_CORE(__section, __core, __name, __level)		\
+	__stringify(__SECTION_CORE(__section,__core,__name,__level))
+# endif
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align=16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index af0254c09424..298252df3c81 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_GENERIC_SECTIONS_H_
 #define _ASM_GENERIC_SECTIONS_H_
 
+#include <asm/section-core.h>
+
 /* References to section boundaries */
 
 #include <linux/compiler.h>
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 24563970ff7b..731087276a32 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -55,6 +55,7 @@
 #endif
 
 #include <linux/export.h>
+#include <asm/section-core.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
@@ -198,8 +199,8 @@
 
 /* .data section */
 #define DATA_DATA							\
-	*(.data)							\
-	*(.ref.data)							\
+	*(SECTION_DATA)							\
+	*(SECTION_REF_DATA)						\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
 	MEM_KEEP(exit.data)						\
@@ -262,9 +263,9 @@
  */
 #define RO_DATA_SECTION(align)						\
 	. = ALIGN((align));						\
-	.rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {		\
+	SECTION_RODATA    : AT(ADDR(SECTION_RODATA) - LOAD_OFFSET) {	\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
-		*(.rodata) *(.rodata.*)					\
+		*(SECTION_RODATA) *(SECTION_ALL(SECTION_RODATA))	\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		*(__vermagic)		/* Kernel version magic */	\
 		. = ALIGN(8);						\
@@ -394,7 +395,7 @@
 									\
 	/* __*init sections */						\
 	__init_rodata : AT(ADDR(__init_rodata) - LOAD_OFFSET) {		\
-		*(.ref.rodata)						\
+		*(SECTION_REF_RODATA)					\
 		MEM_KEEP(init.rodata)					\
 		MEM_KEEP(exit.rodata)					\
 	}								\
@@ -432,8 +433,8 @@
  * during second ld run in second ld pass when generating System.map */
 #define TEXT_TEXT							\
 		ALIGN_FUNCTION();					\
-		*(.text.hot .text .text.fixup .text.unlikely)		\
-		*(.ref.text)						\
+		*(.text.hot SECTION_TEXT .text.fixup .text.unlikely)	\
+		*(SECTION_REF)						\
 	MEM_KEEP(init.text)						\
 	MEM_KEEP(exit.text)						\
 
@@ -527,11 +528,11 @@
 
 /* init and exit section handling */
 #define INIT_DATA							\
-	*(.init.data)							\
+	*(SECTION_INIT_DATA)						\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
-	*(.init.rodata)							\
+	*(SECTION_INIT_RODATA)						\
 	FTRACE_EVENTS()							\
 	TRACE_SYSCALLS()						\
 	KPROBE_BLACKLIST()						\
@@ -549,24 +550,24 @@
 	EARLYCON_TABLE()
 
 #define INIT_TEXT							\
-	*(.init.text)							\
+	*(SECTION_INIT)							\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
 #define EXIT_DATA							\
-	*(.exit.data)							\
+	*(SECTION_EXIT_DATA)						\
 	*(.fini_array)							\
 	*(.dtors)							\
 	MEM_DISCARD(exit.data)						\
 	MEM_DISCARD(exit.rodata)
 
 #define EXIT_TEXT							\
-	*(.exit.text)							\
+	*(SECTION_EXIT)							\
 	*(.text.exit)							\
 	MEM_DISCARD(exit.text)
 
 #define EXIT_CALL							\
-	*(.exitcall.exit)
+	*(SECTION_EXIT_CALL)
 
 /*
  * bss (Block Started by Symbol) - uninitialized data
diff --git a/include/linux/sections.h b/include/linux/sections.h
new file mode 100644
index 000000000000..f21c6ee88ded
--- /dev/null
+++ b/include/linux/sections.h
@@ -0,0 +1,111 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_SIZE - get number of entries in the section
+ *
+ * @name: section name
+ *
+ * This gives you the number of entries in the section.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINUX_SECTION_SIZE(frobnicator_fns);
+ */
+#define LINUX_SECTION_SIZE(name)					\
+	((VMLINUX_SYMBOL(name##__end)) - (VMLINUX_SYMBOL(name)))
+
+/**
+ * LINUX_SECTION_EMPTY - check if section has no entries
+ *
+ * @name: section name
+ *
+ * Returns true if section is emtpy.
+ *
+ *   bool is_empty = LINUX_SECTION_EMPTY(frobnicator_fns);
+ */
+#define LINUX_SECTION_EMPTY(name)	(LINUX_SECTION_SIZE(name) == 0)
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_TYPE(section, type, name, level)			\
+	#section "." #type "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 05/16] xtensa: skip adding literal when SORT() is used
  2016-08-19 21:32 ` mcgrof
  (?)
@ 2016-08-19 21:32   ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

When SORT(foo.*) is used the current sed replacements add
SORT(foo.literal foo.*), this breaks linking. Avoid adding
literals for SORT globs, if needed, these need to be added
manually.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/xtensa/kernel/Makefile | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index c31f5d5afc7d..8180850ed147 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -29,10 +29,10 @@ AFLAGS_mxhead.o += -mtext-section-literals
 #
 # Replicate rules in scripts/Makefile.build
 
-sed-y = -e ':a; s/\*(\([^)]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
-	-e ':b; s/\*(\([^)]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
-	-e ':c; s/\*(\([^)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
-	-e ':d; s/\*(\([^)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
+sed-y = -e ':a; s/\*(\([^)SORT]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
+	-e ':b; s/\*(\([^)SORT]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
+	-e ':c; s/\*(\([^SORT)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
+	-e ':d; s/\*(\([^SORT)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
 	-e 's/\.{text}/.text/g'
 
 quiet_cmd__cpp_lds_S = LDS     $@
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 05/16] xtensa: skip adding literal when SORT() is used
@ 2016-08-19 21:32   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

When SORT(foo.*) is used the current sed replacements add
SORT(foo.literal foo.*), this breaks linking. Avoid adding
literals for SORT globs, if needed, these need to be added
manually.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/xtensa/kernel/Makefile | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index c31f5d5afc7d..8180850ed147 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -29,10 +29,10 @@ AFLAGS_mxhead.o += -mtext-section-literals
 #
 # Replicate rules in scripts/Makefile.build
 
-sed-y = -e ':a; s/\*(\([^)]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
-	-e ':b; s/\*(\([^)]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
-	-e ':c; s/\*(\([^)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
-	-e ':d; s/\*(\([^)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
+sed-y = -e ':a; s/\*(\([^)SORT]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
+	-e ':b; s/\*(\([^)SORT]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
+	-e ':c; s/\*(\([^SORT)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
+	-e ':d; s/\*(\([^SORT)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
 	-e 's/\.{text}/.text/g'
 
 quiet_cmd__cpp_lds_S = LDS     $@
-- 
2.9.2


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 05/16] xtensa: skip adding literal when SORT() is used
@ 2016-08-19 21:32   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

When SORT(foo.*) is used the current sed replacements add
SORT(foo.literal foo.*), this breaks linking. Avoid adding
literals for SORT globs, if needed, these need to be added
manually.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/xtensa/kernel/Makefile | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index c31f5d5afc7d..8180850ed147 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -29,10 +29,10 @@ AFLAGS_mxhead.o += -mtext-section-literals
 #
 # Replicate rules in scripts/Makefile.build
 
-sed-y = -e ':a; s/\*(\([^)]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
-	-e ':b; s/\*(\([^)]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
-	-e ':c; s/\*(\([^)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
-	-e ':d; s/\*(\([^)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
+sed-y = -e ':a; s/\*(\([^)SORT]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
+	-e ':b; s/\*(\([^)SORT]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
+	-e ':c; s/\*(\([^SORT)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
+	-e ':d; s/\*(\([^SORT)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
 	-e 's/\.{text}/.text/g'
 
 quiet_cmd__cpp_lds_S = LDS     $@
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 06/16] ranges.h: add helpers to build and identify Linux section ranges
  2016-08-19 21:32 ` mcgrof
  (?)
@ 2016-08-19 21:32   ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Section ranges are on one of the types of custom sections
types used in Linux. This provides a series of helpers for
defining them and using them. Most importantly this also
enables us to avoid modifying the linker script when we
add a new section range.

It turns out a lot of custom sections are actually section ranges,
and these are typically spelled out in their architecture specific
asm/sections.h file -- we anable architectures to override what asm
is used for section ranges but start by default trusting the
asm-generic version all around.

v4:

o tons of documentation love
o fix arch/x86/tools/relocs.c typo - which caused compilation issues
  on old toolchains
o port to new shiny sphinx documentation
o sprinkle a few more needed VMLINUX_SYMBOL() - fixes
  compilation on blackfin
o name changes as suggested 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
- rebrand DECLARE_SECTION_RNG() as DEFINE_SECTION_RANGE() - this is
  the asm version of the respective C version, this will have a
  userspace C demo added later.
o move __LINUX_RANGE() and __LINUX_RANGE_ORDER() - fixes builds
  on sparc
o adds section ranges to linker script
o rename SECTION_RANGE_ALL()
o use default alignment, fixes builds on powerpc and arm for both
  __LINUX_RANGE() and __LINUX_RANGE_ORDER()
o expand documentation to document modules support
o add maintainers
o use generic-y

v3: new in this series, uses copyleft-next

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst   |   1 +
 Documentation/sections/ranges.rst  |  49 ++++++++++++++
 MAINTAINERS                        |  10 +++
 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/Kbuild        |   1 +
 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       |  89 ++++++++++++++++++++++++++
 include/asm-generic/vmlinux.lds.h  |  12 +++-
 include/linux/ranges.h             | 128 +++++++++++++++++++++++++++++++++++++
 38 files changed, 320 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/linux/ranges.h

diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
index d411e9b22eb3..6dd93ddd5dbe 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -9,3 +9,4 @@ used throughout the kernel to help declare and define them.
    :maxdepth: 4
 
    section-core
+   ranges
diff --git a/Documentation/sections/ranges.rst b/Documentation/sections/ranges.rst
new file mode 100644
index 000000000000..1293dcb3ab38
--- /dev/null
+++ b/Documentation/sections/ranges.rst
@@ -0,0 +1,49 @@
+==========
+Linux section ranges
+==========
+
+This documents Linux' use of section ranges, how you can use
+them and how they work.
+
+About section ranges
+==========
+
+Introduction
+------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Introduction
+
+Section range module support
+----------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range module support
+
+Section range helpers
+==========+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range helpers
+
+DECLARE_SECTION_RANGE
+---------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DECLARE_SECTION_RANGE
+
+DEFINE_SECTION_RANGE
+--------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DEFINE_SECTION_RANGE
+
+SECTION_ADDR_IN_RANGE
+---------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_ADDR_IN_RANGE
+
+__LINUX_RANGE
+-------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE
+
+__LINUX_RANGE_ORDER
+-------------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE_ORDER
diff --git a/MAINTAINERS b/MAINTAINERS
index 689c12075842..1a217751aa8a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5217,6 +5217,16 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTION RANGES
+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
+S:	Supported
+F:	include/asm-generic/ranges.h
+F:	include/linux/ranges.h
+F:	Documentation/sections/ranges.rst
+
 GENERIC SECTIONS
 M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
 M:	Josh Poimboeuf <jpoimboe@redhat.com>
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index 5422827f1585..e44c896b91c4 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 9a0929576de1..e5295413fdf8 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 47923635be16..8e52300e1eed 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += timex.h
 generic-y += trace_clock.h
 generic-y += unaligned.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 42d00806e4fb..5ff184574976 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -53,3 +53,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index f2c3b656a0e7..edc176348d7c 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -23,3 +23,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 7de674411bed..35b7752e65c0 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -49,3 +49,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 38127ce747be..cede2a950fbf 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 385cd88a9d9e..fb8bb4112773 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 46d7c599d9b8..5191fec655d7 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 1ec04ec1c82b..7929a992566c 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -76,3 +76,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index 37d7bfae7619..af17ee334788 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 672c6d5da18c..d8f226b35a0a 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 6111e1523750..1c6504d29312 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index eef72c464c9b..d465f51c2088 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -36,3 +36,4 @@ generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 50ebd5a30d16..c869b1ebd583 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -57,3 +57,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index c6c2cf6edc98..63c083a1f8da 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 12f7c5984c03..ed225600c8a4 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index f8145bc85835..656af7b69940 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index c9c7cb82b00f..c55880659d67 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 86175e701869..7d6a704b808c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -72,3 +72,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 6f43f33f0e0f..1a263a7158e2 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -30,3 +30,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index b49fab7bab2f..065c6e84fb67 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 89e74b59f32d..3e8b95927cb5 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index f089a264cd38..f0cdb2cbca4d 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -15,3 +15,4 @@ generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 7b0356dca562..c9bb7932a3d1 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index d51b84d6b4b7..79664d10e63b 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -23,3 +23,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 7b8a652e43ae..951fa4be571d 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -42,3 +42,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index e9849834d55e..99be54949b99 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -28,3 +28,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 256c45b3ae34..6c35905fe371 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += ranges.h
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index f6914a57bc16..f790756fdb48 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -17,3 +17,4 @@ generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index 0c2fae8d929d..c215db049920 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -68,6 +68,8 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
 	"__end_rodata|"
 	"__initramfs_start|"
 	"(jiffies|jiffies_64)|"
+	".rodata.rng.*|"
+	".init.text.rng.*|"
 #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 81ca6816bd72..221b6b652500 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/include/asm-generic/ranges.h b/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..74cd941aa2f8
--- /dev/null
+++ b/include/asm-generic/ranges.h
@@ -0,0 +1,89 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#define SECTION_RNG(section, name)					\
+	SECTION_CORE(section, rng, name,				\
+		     SECTION_ORDER_ANY)
+
+#define SECTION_RNG_LEVEL(section, name, level)				\
+	SECTION_CORE(section, rng, name, level)
+
+#define SECTION_RNG_ALL(section)					\
+	SECTION_CORE_ALL(section,rng)
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  SECTION_ORDER_ANY, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       SECTION_ORDER_ANY, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   SECTION_ORDER_ANY, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(SECTION_RNG(section, name))))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using
+ * 	binutils SORT(), the number is sorted as a string, as such be
+ * 	sure to fill with zeroes any empty digits. For instance if you are
+ * 	using 3 levels of digits for order levels, use 001 for the first entry,
+ * 	0002 for the second, 999 for the last entry. You can use however many
+ * 	digits you need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(SECTION_RNG_LEVEL(section, name, level))))
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_GENERIC_RANGES_H_ */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 731087276a32..ad843555e6a4 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -56,6 +56,7 @@
 
 #include <linux/export.h>
 #include <asm/section-core.h>
+#include <asm/ranges.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
@@ -200,6 +201,7 @@
 /* .data section */
 #define DATA_DATA							\
 	*(SECTION_DATA)							\
+	*(SORT(SECTION_RNG_ALL(SECTION_DATA)))				\
 	*(SECTION_REF_DATA)						\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -265,7 +267,9 @@
 	. = ALIGN((align));						\
 	SECTION_RODATA    : AT(ADDR(SECTION_RODATA) - LOAD_OFFSET) {	\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
-		*(SECTION_RODATA) *(SECTION_ALL(SECTION_RODATA))	\
+		*(SECTION_RODATA)					\
+		*(SORT(SECTION_RNG_ALL(SECTION_RODATA)))		\
+		*(SECTION_ALL(SECTION_RODATA))				\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		*(__vermagic)		/* Kernel version magic */	\
 		. = ALIGN(8);						\
@@ -433,7 +437,9 @@
  * during second ld run in second ld pass when generating System.map */
 #define TEXT_TEXT							\
 		ALIGN_FUNCTION();					\
-		*(.text.hot SECTION_TEXT .text.fixup .text.unlikely)	\
+		*(.text.hot SECTION_TEXT)				\
+		*(SORT(SECTION_RNG_ALL(SECTION_TEXT)))			\
+		*(.text.fixup .text.unlikely)				\
 		*(SECTION_REF)						\
 	MEM_KEEP(init.text)						\
 	MEM_KEEP(exit.text)						\
@@ -529,6 +535,7 @@
 /* init and exit section handling */
 #define INIT_DATA							\
 	*(SECTION_INIT_DATA)						\
+	*(SORT(SECTION_RNG_ALL(SECTION_INIT_DATA)))			\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -551,6 +558,7 @@
 
 #define INIT_TEXT							\
 	*(SECTION_INIT)							\
+	*(SORT(SECTION_RNG_ALL(SECTION_INIT)))				\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/ranges.h b/include/linux/ranges.h
new file mode 100644
index 000000000000..30b2182bd484
--- /dev/null
+++ b/include/linux/ranges.h
@@ -0,0 +1,128 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(VMLINUX_SYMBOL(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+			     section(SECTION_RNG_LEVEL(__section, name,))))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(VMLINUX_SYMBOL(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+			     section(SECTION_RNG_LEVEL(__section, name, ~))))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) VMLINUX_SYMBOL(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) VMLINUX_SYMBOL(name##__end)[0] = {}
+
+/**
+ * SECTION_ADDR_IN_RANGE - returns true if address is in range
+ *
+ * @name: section range name
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_ADDR_IN_RANGE(name, addr)				\
+	 (addr >= (unsigned long) LINUX_SECTION_START(name) &&		\
+	  addr <  (unsigned long) LINUX_SECTION_END(name))
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 06/16] ranges.h: add helpers to build and identify Linux section ranges
@ 2016-08-19 21:32   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Section ranges are on one of the types of custom sections
types used in Linux. This provides a series of helpers for
defining them and using them. Most importantly this also
enables us to avoid modifying the linker script when we
add a new section range.

It turns out a lot of custom sections are actually section ranges,
and these are typically spelled out in their architecture specific
asm/sections.h file -- we anable architectures to override what asm
is used for section ranges but start by default trusting the
asm-generic version all around.

v4:

o tons of documentation love
o fix arch/x86/tools/relocs.c typo - which caused compilation issues
  on old toolchains
o port to new shiny sphinx documentation
o sprinkle a few more needed VMLINUX_SYMBOL() - fixes
  compilation on blackfin
o name changes as suggested 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
- rebrand DECLARE_SECTION_RNG() as DEFINE_SECTION_RANGE() - this is
  the asm version of the respective C version, this will have a
  userspace C demo added later.
o move __LINUX_RANGE() and __LINUX_RANGE_ORDER() - fixes builds
  on sparc
o adds section ranges to linker script
o rename SECTION_RANGE_ALL()
o use default alignment, fixes builds on powerpc and arm for both
  __LINUX_RANGE() and __LINUX_RANGE_ORDER()
o expand documentation to document modules support
o add maintainers
o use generic-y

v3: new in this series, uses copyleft-next

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst   |   1 +
 Documentation/sections/ranges.rst  |  49 ++++++++++++++
 MAINTAINERS                        |  10 +++
 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/Kbuild        |   1 +
 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       |  89 ++++++++++++++++++++++++++
 include/asm-generic/vmlinux.lds.h  |  12 +++-
 include/linux/ranges.h             | 128 +++++++++++++++++++++++++++++++++++++
 38 files changed, 320 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/linux/ranges.h

diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
index d411e9b22eb3..6dd93ddd5dbe 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -9,3 +9,4 @@ used throughout the kernel to help declare and define them.
    :maxdepth: 4
 
    section-core
+   ranges
diff --git a/Documentation/sections/ranges.rst b/Documentation/sections/ranges.rst
new file mode 100644
index 000000000000..1293dcb3ab38
--- /dev/null
+++ b/Documentation/sections/ranges.rst
@@ -0,0 +1,49 @@
+====================
+Linux section ranges
+====================
+
+This documents Linux' use of section ranges, how you can use
+them and how they work.
+
+About section ranges
+====================
+
+Introduction
+------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Introduction
+
+Section range module support
+----------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range module support
+
+Section range helpers
+=====================
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range helpers
+
+DECLARE_SECTION_RANGE
+---------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DECLARE_SECTION_RANGE
+
+DEFINE_SECTION_RANGE
+--------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DEFINE_SECTION_RANGE
+
+SECTION_ADDR_IN_RANGE
+---------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_ADDR_IN_RANGE
+
+__LINUX_RANGE
+-------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE
+
+__LINUX_RANGE_ORDER
+-------------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE_ORDER
diff --git a/MAINTAINERS b/MAINTAINERS
index 689c12075842..1a217751aa8a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5217,6 +5217,16 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTION RANGES
+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
+S:	Supported
+F:	include/asm-generic/ranges.h
+F:	include/linux/ranges.h
+F:	Documentation/sections/ranges.rst
+
 GENERIC SECTIONS
 M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
 M:	Josh Poimboeuf <jpoimboe@redhat.com>
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index 5422827f1585..e44c896b91c4 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 9a0929576de1..e5295413fdf8 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 47923635be16..8e52300e1eed 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += timex.h
 generic-y += trace_clock.h
 generic-y += unaligned.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 42d00806e4fb..5ff184574976 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -53,3 +53,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index f2c3b656a0e7..edc176348d7c 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -23,3 +23,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 7de674411bed..35b7752e65c0 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -49,3 +49,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 38127ce747be..cede2a950fbf 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 385cd88a9d9e..fb8bb4112773 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 46d7c599d9b8..5191fec655d7 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 1ec04ec1c82b..7929a992566c 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -76,3 +76,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index 37d7bfae7619..af17ee334788 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 672c6d5da18c..d8f226b35a0a 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 6111e1523750..1c6504d29312 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index eef72c464c9b..d465f51c2088 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -36,3 +36,4 @@ generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 50ebd5a30d16..c869b1ebd583 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -57,3 +57,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index c6c2cf6edc98..63c083a1f8da 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 12f7c5984c03..ed225600c8a4 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index f8145bc85835..656af7b69940 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index c9c7cb82b00f..c55880659d67 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 86175e701869..7d6a704b808c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -72,3 +72,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 6f43f33f0e0f..1a263a7158e2 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -30,3 +30,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index b49fab7bab2f..065c6e84fb67 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 89e74b59f32d..3e8b95927cb5 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index f089a264cd38..f0cdb2cbca4d 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -15,3 +15,4 @@ generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 7b0356dca562..c9bb7932a3d1 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index d51b84d6b4b7..79664d10e63b 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -23,3 +23,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 7b8a652e43ae..951fa4be571d 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -42,3 +42,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index e9849834d55e..99be54949b99 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -28,3 +28,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 256c45b3ae34..6c35905fe371 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += ranges.h
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index f6914a57bc16..f790756fdb48 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -17,3 +17,4 @@ generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index 0c2fae8d929d..c215db049920 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -68,6 +68,8 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
 	"__end_rodata|"
 	"__initramfs_start|"
 	"(jiffies|jiffies_64)|"
+	".rodata.rng.*|"
+	".init.text.rng.*|"
 #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 81ca6816bd72..221b6b652500 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/include/asm-generic/ranges.h b/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..74cd941aa2f8
--- /dev/null
+++ b/include/asm-generic/ranges.h
@@ -0,0 +1,89 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#define SECTION_RNG(section, name)					\
+	SECTION_CORE(section, rng, name,				\
+		     SECTION_ORDER_ANY)
+
+#define SECTION_RNG_LEVEL(section, name, level)				\
+	SECTION_CORE(section, rng, name, level)
+
+#define SECTION_RNG_ALL(section)					\
+	SECTION_CORE_ALL(section,rng)
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  SECTION_ORDER_ANY, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       SECTION_ORDER_ANY, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   SECTION_ORDER_ANY, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(SECTION_RNG(section, name))))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using
+ * 	binutils SORT(), the number is sorted as a string, as such be
+ * 	sure to fill with zeroes any empty digits. For instance if you are
+ * 	using 3 levels of digits for order levels, use 001 for the first entry,
+ * 	0002 for the second, 999 for the last entry. You can use however many
+ * 	digits you need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(SECTION_RNG_LEVEL(section, name, level))))
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_GENERIC_RANGES_H_ */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 731087276a32..ad843555e6a4 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -56,6 +56,7 @@
 
 #include <linux/export.h>
 #include <asm/section-core.h>
+#include <asm/ranges.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
@@ -200,6 +201,7 @@
 /* .data section */
 #define DATA_DATA							\
 	*(SECTION_DATA)							\
+	*(SORT(SECTION_RNG_ALL(SECTION_DATA)))				\
 	*(SECTION_REF_DATA)						\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -265,7 +267,9 @@
 	. = ALIGN((align));						\
 	SECTION_RODATA    : AT(ADDR(SECTION_RODATA) - LOAD_OFFSET) {	\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
-		*(SECTION_RODATA) *(SECTION_ALL(SECTION_RODATA))	\
+		*(SECTION_RODATA)					\
+		*(SORT(SECTION_RNG_ALL(SECTION_RODATA)))		\
+		*(SECTION_ALL(SECTION_RODATA))				\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		*(__vermagic)		/* Kernel version magic */	\
 		. = ALIGN(8);						\
@@ -433,7 +437,9 @@
  * during second ld run in second ld pass when generating System.map */
 #define TEXT_TEXT							\
 		ALIGN_FUNCTION();					\
-		*(.text.hot SECTION_TEXT .text.fixup .text.unlikely)	\
+		*(.text.hot SECTION_TEXT)				\
+		*(SORT(SECTION_RNG_ALL(SECTION_TEXT)))			\
+		*(.text.fixup .text.unlikely)				\
 		*(SECTION_REF)						\
 	MEM_KEEP(init.text)						\
 	MEM_KEEP(exit.text)						\
@@ -529,6 +535,7 @@
 /* init and exit section handling */
 #define INIT_DATA							\
 	*(SECTION_INIT_DATA)						\
+	*(SORT(SECTION_RNG_ALL(SECTION_INIT_DATA)))			\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -551,6 +558,7 @@
 
 #define INIT_TEXT							\
 	*(SECTION_INIT)							\
+	*(SORT(SECTION_RNG_ALL(SECTION_INIT)))				\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/ranges.h b/include/linux/ranges.h
new file mode 100644
index 000000000000..30b2182bd484
--- /dev/null
+++ b/include/linux/ranges.h
@@ -0,0 +1,128 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(VMLINUX_SYMBOL(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+			     section(SECTION_RNG_LEVEL(__section, name,))))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(VMLINUX_SYMBOL(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+			     section(SECTION_RNG_LEVEL(__section, name, ~))))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) VMLINUX_SYMBOL(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) VMLINUX_SYMBOL(name##__end)[0] = {}
+
+/**
+ * SECTION_ADDR_IN_RANGE - returns true if address is in range
+ *
+ * @name: section range name
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_ADDR_IN_RANGE(name, addr)				\
+	 (addr >= (unsigned long) LINUX_SECTION_START(name) &&		\
+	  addr <  (unsigned long) LINUX_SECTION_END(name))
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
-- 
2.9.2


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 06/16] ranges.h: add helpers to build and identify Linux section ranges
@ 2016-08-19 21:32   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Section ranges are on one of the types of custom sections
types used in Linux. This provides a series of helpers for
defining them and using them. Most importantly this also
enables us to avoid modifying the linker script when we
add a new section range.

It turns out a lot of custom sections are actually section ranges,
and these are typically spelled out in their architecture specific
asm/sections.h file -- we anable architectures to override what asm
is used for section ranges but start by default trusting the
asm-generic version all around.

v4:

o tons of documentation love
o fix arch/x86/tools/relocs.c typo - which caused compilation issues
  on old toolchains
o port to new shiny sphinx documentation
o sprinkle a few more needed VMLINUX_SYMBOL() - fixes
  compilation on blackfin
o name changes as suggested 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
- rebrand DECLARE_SECTION_RNG() as DEFINE_SECTION_RANGE() - this is
  the asm version of the respective C version, this will have a
  userspace C demo added later.
o move __LINUX_RANGE() and __LINUX_RANGE_ORDER() - fixes builds
  on sparc
o adds section ranges to linker script
o rename SECTION_RANGE_ALL()
o use default alignment, fixes builds on powerpc and arm for both
  __LINUX_RANGE() and __LINUX_RANGE_ORDER()
o expand documentation to document modules support
o add maintainers
o use generic-y

v3: new in this series, uses copyleft-next

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst   |   1 +
 Documentation/sections/ranges.rst  |  49 ++++++++++++++
 MAINTAINERS                        |  10 +++
 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/Kbuild        |   1 +
 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       |  89 ++++++++++++++++++++++++++
 include/asm-generic/vmlinux.lds.h  |  12 +++-
 include/linux/ranges.h             | 128 +++++++++++++++++++++++++++++++++++++
 38 files changed, 320 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/linux/ranges.h

diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
index d411e9b22eb3..6dd93ddd5dbe 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -9,3 +9,4 @@ used throughout the kernel to help declare and define them.
    :maxdepth: 4
 
    section-core
+   ranges
diff --git a/Documentation/sections/ranges.rst b/Documentation/sections/ranges.rst
new file mode 100644
index 000000000000..1293dcb3ab38
--- /dev/null
+++ b/Documentation/sections/ranges.rst
@@ -0,0 +1,49 @@
+====================
+Linux section ranges
+====================
+
+This documents Linux' use of section ranges, how you can use
+them and how they work.
+
+About section ranges
+====================
+
+Introduction
+------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Introduction
+
+Section range module support
+----------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range module support
+
+Section range helpers
+=====================
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range helpers
+
+DECLARE_SECTION_RANGE
+---------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DECLARE_SECTION_RANGE
+
+DEFINE_SECTION_RANGE
+--------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DEFINE_SECTION_RANGE
+
+SECTION_ADDR_IN_RANGE
+---------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_ADDR_IN_RANGE
+
+__LINUX_RANGE
+-------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE
+
+__LINUX_RANGE_ORDER
+-------------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE_ORDER
diff --git a/MAINTAINERS b/MAINTAINERS
index 689c12075842..1a217751aa8a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5217,6 +5217,16 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTION RANGES
+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
+S:	Supported
+F:	include/asm-generic/ranges.h
+F:	include/linux/ranges.h
+F:	Documentation/sections/ranges.rst
+
 GENERIC SECTIONS
 M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
 M:	Josh Poimboeuf <jpoimboe@redhat.com>
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index 5422827f1585..e44c896b91c4 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 9a0929576de1..e5295413fdf8 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 47923635be16..8e52300e1eed 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += timex.h
 generic-y += trace_clock.h
 generic-y += unaligned.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 42d00806e4fb..5ff184574976 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -53,3 +53,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index f2c3b656a0e7..edc176348d7c 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -23,3 +23,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 7de674411bed..35b7752e65c0 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -49,3 +49,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 38127ce747be..cede2a950fbf 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 385cd88a9d9e..fb8bb4112773 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 46d7c599d9b8..5191fec655d7 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 1ec04ec1c82b..7929a992566c 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -76,3 +76,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index 37d7bfae7619..af17ee334788 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 672c6d5da18c..d8f226b35a0a 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 6111e1523750..1c6504d29312 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index eef72c464c9b..d465f51c2088 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -36,3 +36,4 @@ generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 50ebd5a30d16..c869b1ebd583 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -57,3 +57,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index c6c2cf6edc98..63c083a1f8da 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 12f7c5984c03..ed225600c8a4 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index f8145bc85835..656af7b69940 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index c9c7cb82b00f..c55880659d67 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 86175e701869..7d6a704b808c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -72,3 +72,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 6f43f33f0e0f..1a263a7158e2 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -30,3 +30,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index b49fab7bab2f..065c6e84fb67 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 89e74b59f32d..3e8b95927cb5 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index f089a264cd38..f0cdb2cbca4d 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -15,3 +15,4 @@ generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 7b0356dca562..c9bb7932a3d1 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index d51b84d6b4b7..79664d10e63b 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -23,3 +23,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 7b8a652e43ae..951fa4be571d 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -42,3 +42,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index e9849834d55e..99be54949b99 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -28,3 +28,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 256c45b3ae34..6c35905fe371 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += ranges.h
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index f6914a57bc16..f790756fdb48 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -17,3 +17,4 @@ generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index 0c2fae8d929d..c215db049920 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -68,6 +68,8 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
 	"__end_rodata|"
 	"__initramfs_start|"
 	"(jiffies|jiffies_64)|"
+	".rodata.rng.*|"
+	".init.text.rng.*|"
 #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 81ca6816bd72..221b6b652500 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/include/asm-generic/ranges.h b/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..74cd941aa2f8
--- /dev/null
+++ b/include/asm-generic/ranges.h
@@ -0,0 +1,89 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#define SECTION_RNG(section, name)					\
+	SECTION_CORE(section, rng, name,				\
+		     SECTION_ORDER_ANY)
+
+#define SECTION_RNG_LEVEL(section, name, level)				\
+	SECTION_CORE(section, rng, name, level)
+
+#define SECTION_RNG_ALL(section)					\
+	SECTION_CORE_ALL(section,rng)
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  SECTION_ORDER_ANY, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       SECTION_ORDER_ANY, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   SECTION_ORDER_ANY, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(SECTION_RNG(section, name))))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using
+ * 	binutils SORT(), the number is sorted as a string, as such be
+ * 	sure to fill with zeroes any empty digits. For instance if you are
+ * 	using 3 levels of digits for order levels, use 001 for the first entry,
+ * 	0002 for the second, 999 for the last entry. You can use however many
+ * 	digits you need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(SECTION_RNG_LEVEL(section, name, level))))
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_GENERIC_RANGES_H_ */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 731087276a32..ad843555e6a4 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -56,6 +56,7 @@
 
 #include <linux/export.h>
 #include <asm/section-core.h>
+#include <asm/ranges.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
@@ -200,6 +201,7 @@
 /* .data section */
 #define DATA_DATA							\
 	*(SECTION_DATA)							\
+	*(SORT(SECTION_RNG_ALL(SECTION_DATA)))				\
 	*(SECTION_REF_DATA)						\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -265,7 +267,9 @@
 	. = ALIGN((align));						\
 	SECTION_RODATA    : AT(ADDR(SECTION_RODATA) - LOAD_OFFSET) {	\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
-		*(SECTION_RODATA) *(SECTION_ALL(SECTION_RODATA))	\
+		*(SECTION_RODATA)					\
+		*(SORT(SECTION_RNG_ALL(SECTION_RODATA)))		\
+		*(SECTION_ALL(SECTION_RODATA))				\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		*(__vermagic)		/* Kernel version magic */	\
 		. = ALIGN(8);						\
@@ -433,7 +437,9 @@
  * during second ld run in second ld pass when generating System.map */
 #define TEXT_TEXT							\
 		ALIGN_FUNCTION();					\
-		*(.text.hot SECTION_TEXT .text.fixup .text.unlikely)	\
+		*(.text.hot SECTION_TEXT)				\
+		*(SORT(SECTION_RNG_ALL(SECTION_TEXT)))			\
+		*(.text.fixup .text.unlikely)				\
 		*(SECTION_REF)						\
 	MEM_KEEP(init.text)						\
 	MEM_KEEP(exit.text)						\
@@ -529,6 +535,7 @@
 /* init and exit section handling */
 #define INIT_DATA							\
 	*(SECTION_INIT_DATA)						\
+	*(SORT(SECTION_RNG_ALL(SECTION_INIT_DATA)))			\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -551,6 +558,7 @@
 
 #define INIT_TEXT							\
 	*(SECTION_INIT)							\
+	*(SORT(SECTION_RNG_ALL(SECTION_INIT)))				\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/ranges.h b/include/linux/ranges.h
new file mode 100644
index 000000000000..30b2182bd484
--- /dev/null
+++ b/include/linux/ranges.h
@@ -0,0 +1,128 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(VMLINUX_SYMBOL(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+			     section(SECTION_RNG_LEVEL(__section, name,))))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(VMLINUX_SYMBOL(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+			     section(SECTION_RNG_LEVEL(__section, name, ~))))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) VMLINUX_SYMBOL(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) VMLINUX_SYMBOL(name##__end)[0] = {}
+
+/**
+ * SECTION_ADDR_IN_RANGE - returns true if address is in range
+ *
+ * @name: section range name
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_ADDR_IN_RANGE(name, addr)				\
+	 (addr >= (unsigned long) LINUX_SECTION_START(name) &&		\
+	  addr <  (unsigned long) LINUX_SECTION_END(name))
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 07/16] tables.h: add linker table support
  2016-08-19 21:32 ` mcgrof
  (?)
@ 2016-08-19 21:32   ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

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@ipxe.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 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@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
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@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 */
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@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_ */
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@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 */
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


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 07/16] tables.h: add linker table support
@ 2016-08-19 21:32   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

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@ipxe.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 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@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
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@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 */
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@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_ */
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@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 */
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


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 07/16] tables.h: add linker table support
@ 2016-08-19 21:32   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

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@ipxe.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 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@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
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@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 */
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@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_ */
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@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 */
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


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 08/16] kbuild: enable option to force compile force-obj-y and force-lib-y
  2016-08-19 21:32 ` mcgrof
  (?)
@ 2016-08-19 21:32   ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Linux provides a rich array of features, enabling each feature
however increases the size of the kernel and there are many
features which users often want disabled. The traditional
solution to this problem is for each feature to have its own
Kconfig symbol, followed by a series of #ifdef statements
in C code and header files, allowing the feature to be compiled
only when desirable. As the variability of Linux increases build
tests can and are often done with random kernel configurations,
allyesconfig, and allmodconfig to help find code issues. This
however doesn't catch all errors and as a consequence code that
is typically not enabled often can suffer from bit-rot over time.

An alternative approach for subsystems, which refer to as the 'build-all
link-selectively philosophy' is to keep the Kconfig symbols, replace
the #ifdef approach by having each feature implemented it its own C file,
and force compilation for all features to avoid the code bit-rot problem.
With this strategy only features that are enabled via Kconfig get
linked into the kernel, so the forced compilation has no size impact
on the kernel. The practice of having each feature implemented in its own
C file is already prevalent in many subsystems, however #ifdefs are still
typically required during feature initialization. For instance in:

  #ifdef CONFIG_FOO
  foo_init();
  #endif

We cannot remove the #ifdef and leave foo_init() as we'd either
need to always enable the feature or add a respective #ifdef in a
foo.h which makes foo_init() do nothing when CONFIG_FOO is disabled.

Linker tables enable lifting the requirement to use of #ifdefs during
initialization. With linker tables initialization sequences can instead
be aggregated into a custom ELF section at link time, during run time
the table can be iterated over and each init sequence enabled can be called.
A feature's init routine is only added to a table when its respective
Kconfig symbols has been enabled and therefore linked in. Linker tables
enable subsystems to completely do away with #ifdefs if one is comfortable
in accepting all subsystem's feature's structural size implications.

Subsystems which want to follow the 'build-all link-selectively
philosophy' still need a way to easily express and annotate that they
wish for all code to always be compiled to help avoid code bit rot,
as such two new targets force-obj-y and force-lib-y are provided to
help with this. Its not fair to require everyone to force compilation
of all features of a subsystem though, so as a compromise, the new
targets only force compilation when CONFIG_BUILD_AVOID_BITROT is
enabled.

Only built-in features are supported at the moment. Module support
is expected to be added after a generic solution to add linker
tables to modules more easily is developed.

v4: this patch was added to this series, it was split off from the
    linker tables addition due to the confusion over the code bit
    rot alternatives that are possible with linker tables.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/kbuild/makefiles.txt       | 36 ++++++++++++++++
 Documentation/sections/linker-tables.rst | 15 +++++++
 include/linux/tables.h                   | 71 ++++++++++++++++++++++++++++++++
 init/Kconfig                             | 22 ++++++++++
 scripts/Makefile.build                   |  7 ++--
 scripts/Makefile.lib                     | 11 +++++
 6 files changed, 159 insertions(+), 3 deletions(-)

diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 385a5ef41c17..01c260913f5c 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -1089,6 +1089,42 @@ When kbuild executes, the following steps are followed (roughly):
 	In this example, extra-y is used to list object files that
 	shall be built, but shall not be linked as part of built-in.o.
 
+    force-obj-y force-lib-y
+
+	When CONFIG_BUILD_AVOID_BITROT is enabled using these targets for your
+	kconfig symbols forces compilation of the associated objects if the
+	kconfig's symbol's dependencies are met, the objects however are only
+	linked into to the kernel if and only if the kconfig symbol was
+	enabled. If CONFIG_BUILD_AVOID_BITROT is disabled the force-obj-y and
+	force-lib-y targets are functionally equilvalent to obj-y and lib-y
+	respectively.
+
+	Using force-obj-y and force-lib-y are part of a code architecture and
+	build philosophy further enabled by linker tables, for more details
+	refer to the documention in include/linux/tables.h, refer to the
+	sections:
+
+		o The code bit-rot problem
+		o The build-all selective-link philosophy
+		o Avoiding the code bit-rot problem with linker tables
+		o Linker table module support
+
+	Modules support is expected to be enhanced in the future, so for now
+	only built-in features are supported.
+
+	Example use:
+
+		force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	An alternative to using force-obj-y, is to use extra-y followed by the
+	respective obj-y:
+
+		extra-y += foo.o
+		obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	Using force-obj-y and force-lib-y can be used to help annotate the
+	targets follow the 'build-all selective-link philosophy' further
+	enabled by linker tables.
 
 --- 6.7 Commands useful for building a boot image
 
diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index df11c632dca7..e425c5cd36d6 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -30,6 +30,21 @@ How linker tables simplify initialization code
 .. kernel-doc:: include/linux/tables.h
    :doc: How linker tables simplify initialization code
 
+The code bit-rot problem
+------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The code bit-rot problem
+
+The build-all selective-link philosophy
+---------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The build-all selective-link philosophy
+
+Avoiding the code bit-rot problem with linker tables
+----------------------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: Avoiding the code bit-rot problem with linker tables
+
 Using linker tables in Linux
 ==============
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
index 423827eafb52..bf8fae7f9246 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -169,6 +169,77 @@
  */
 
 /**
+ * DOC: The code bit-rot problem
+ *
+ * Linux provides a rich array of features, enabling each feature
+ * however increases the size of the kernel and there are many
+ * features which users often want disabled. The traditional
+ * solution to this problem is for each feature to have its own
+ * Kconfig symbol, followed by a series of #ifdef statements
+ * in C code and header files, allowing the feature to be compiled
+ * only when desirable. As the variability of Linux increases build
+ * tests can and are often done with random kernel configurations,
+ * allyesconfig, and allmodconfig to help find code issues. This
+ * however doesn't catch all errors and as a consequence code that
+ * is typically not enabled often can suffer from bit-rot over time.
+ */
+
+/**
+ * DOC: The build-all selective-link philosophy
+ *
+ * A code architecture philosophy to help avoid code bit-rot consists
+ * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
+ * by instead having each feature implemented it its own C file, and force
+ * compilation for all features. Only features that are enabled get linked in,
+ * the forced compilation therefore has no size impact on the final result of
+ * the kernel. The practice of having each feature implemented in its own C
+ * file is already prevalent in many subsystems, however #ifdefs are still
+ * typically required during feature initialization. For instance in::
+ *
+ *	#ifdef CONFIG_FOO
+ *	foo_init();
+ *	#endif
+ *
+ * We cannot remove the #ifdef and leave foo_init() as we'd either
+ * need to always enable the feature or add a respective #ifdef in a
+ * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem with linker tables
+ *
+ * Linker tables can be used to further help avoid the code bit-rot problem
+ * when embracing the 'build-all selective-link philosophy' by lifting the
+ * requirement to use of #ifdefs during initialization. With linker tables
+ * initialization sequences can be aggregated into a custom ELF section at
+ * link time, during run time the table can be iterated over and each init
+ * sequence enabled can be called. A feature's init routine is only added to a
+ * table when its respective Kconfig symbols has been enabled and therefore
+ * linked in. Linker tables enable subsystems to completely do away with
+ * #ifdefs if one is comfortable in accepting all subsystem's feature's
+ * structural size implications.
+ *
+ * To further help with this the Linux build system supports two special
+ * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
+ * follow the 'build-all selective-link philosophy' can use these targets for a
+ * feature's kconfig symbol. Using these targets will always require
+ * compilation of the kconfig's objects if the kconfig symbol's dependencies
+ * are met but only link the objects into the kernel, and therefore enable the
+ * feature, if and only if the kconfig symbol has been enabled.
+ *
+ * Not all users or build systems may want to opt-in to compile all objects
+ * following the 'build-all selective-link philosophy', as such the targets
+ * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
+ * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
+ * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
+ * ``obj-y`` and ``lib-y`` respectively.
+ *
+ * Example use::
+ *
+ * 	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+ */
+
+/**
  * DOC: Linker table module support
  *
  * Modules can use linker tables, however the linker table definition
diff --git a/init/Kconfig b/init/Kconfig
index cac3f096050d..ef09e83b9196 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -53,6 +53,28 @@ config CROSS_COMPILE
 	  need to set this unless you want the configured kernel build
 	  directory to select the cross-compiler automatically.
 
+config BUILD_AVOID_BITROT
+	bool "Enable force building of force-obj-y and force-lib-y"
+	default n
+	help
+	  When enabled objects under the force-obj-y and force-lib-y targets
+	  using a Kconfig symbol will be forced to compile if the Kconfig
+	  symbol's dependencies are met but only linked into the kernel if
+	  the Kconfig symbol is enabled. If a Kconfig symbol on a force-obj-y
+	  or force-lib-y target is disabled, it will be compiled but not linked
+	  into the kernel.
+
+	  The force-obj-y and force-lib-y targets can be used by subsystems
+	  which wish to want to follow the 'build-all selective-link philosophy'
+	  documented under include/linux/tables.h.
+
+	  Say Y if you have a decent build machine and would like to help test
+	  building code for more subsystems. Say N if you do you not have a
+	  good build machine or only want to compile what you've enabled for
+	  your kernel.
+
+	  Enabling this option never increases the size of your kernel.
+
 config COMPILE_TEST
 	bool "Compile also drivers which will not load"
 	depends on !UML
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index cd9bf22bb027..cc2c7241d193 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -92,7 +92,8 @@ modorder-target := $(obj)/modules.order
 
 # We keep a list of all modules in $(MODVERDIR)
 
-__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
+__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y) \
+				$(force-obj-y)) \
 	 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
 	 $(subdir-ym) $(always)
 	@:
@@ -326,8 +327,8 @@ cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $<
 $(obj)/%.o: $(src)/%.S $(objtool_obj) FORCE
 	$(call if_changed_rule,as_o_S)
 
-targets += $(real-objs-y) $(real-objs-m) $(lib-y)
-targets += $(extra-y) $(MAKECMDGOALS) $(always)
+targets += $(real-objs-y) $(real-objs-m) $(lib-y) $(force-lib-y)
+targets += $(extra-y) $(force-obj-y) $(MAKECMDGOALS) $(always)
 
 # Linker scripts preprocessor (.lds.S -> .lds)
 # ---------------------------------------------------------------------------
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 0a07f9014944..d1cb0cfdf1bf 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -12,6 +12,15 @@ export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y)
 # Figure out what we need to build from the various variables
 # ===================================== 
+ifeq ($(CONFIG_BUILD_AVOID_BITROT),y)
+extra-y += $(force-obj-) $(force-lib-)
+endif
+
+obj-m += $(force-obj-m)
+obj-y += $(force-obj-y)
+lib-m += $(force-lib-m)
+lib-y += $(force-lib-y)
+
 # When an object is listed to be built compiled-in and modular,
 # only build the compiled-in version
 
@@ -72,6 +81,8 @@ real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)
 # Add subdir path
 
 extra-y		:= $(addprefix $(obj)/,$(extra-y))
+force-obj-y		:= $(addprefix $(obj)/,$(force-obj-y))
+force-obj-m		:= $(addprefix $(obj)/,$(force-obj-m))
 always		:= $(addprefix $(obj)/,$(always))
 targets		:= $(addprefix $(obj)/,$(targets))
 modorder	:= $(addprefix $(obj)/,$(modorder))
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 08/16] kbuild: enable option to force compile force-obj-y and force-lib-y
@ 2016-08-19 21:32   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Linux provides a rich array of features, enabling each feature
however increases the size of the kernel and there are many
features which users often want disabled. The traditional
solution to this problem is for each feature to have its own
Kconfig symbol, followed by a series of #ifdef statements
in C code and header files, allowing the feature to be compiled
only when desirable. As the variability of Linux increases build
tests can and are often done with random kernel configurations,
allyesconfig, and allmodconfig to help find code issues. This
however doesn't catch all errors and as a consequence code that
is typically not enabled often can suffer from bit-rot over time.

An alternative approach for subsystems, which refer to as the 'build-all
link-selectively philosophy' is to keep the Kconfig symbols, replace
the #ifdef approach by having each feature implemented it its own C file,
and force compilation for all features to avoid the code bit-rot problem.
With this strategy only features that are enabled via Kconfig get
linked into the kernel, so the forced compilation has no size impact
on the kernel. The practice of having each feature implemented in its own
C file is already prevalent in many subsystems, however #ifdefs are still
typically required during feature initialization. For instance in:

  #ifdef CONFIG_FOO
  foo_init();
  #endif

We cannot remove the #ifdef and leave foo_init() as we'd either
need to always enable the feature or add a respective #ifdef in a
foo.h which makes foo_init() do nothing when CONFIG_FOO is disabled.

Linker tables enable lifting the requirement to use of #ifdefs during
initialization. With linker tables initialization sequences can instead
be aggregated into a custom ELF section at link time, during run time
the table can be iterated over and each init sequence enabled can be called.
A feature's init routine is only added to a table when its respective
Kconfig symbols has been enabled and therefore linked in. Linker tables
enable subsystems to completely do away with #ifdefs if one is comfortable
in accepting all subsystem's feature's structural size implications.

Subsystems which want to follow the 'build-all link-selectively
philosophy' still need a way to easily express and annotate that they
wish for all code to always be compiled to help avoid code bit rot,
as such two new targets force-obj-y and force-lib-y are provided to
help with this. Its not fair to require everyone to force compilation
of all features of a subsystem though, so as a compromise, the new
targets only force compilation when CONFIG_BUILD_AVOID_BITROT is
enabled.

Only built-in features are supported at the moment. Module support
is expected to be added after a generic solution to add linker
tables to modules more easily is developed.

v4: this patch was added to this series, it was split off from the
    linker tables addition due to the confusion over the code bit
    rot alternatives that are possible with linker tables.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/kbuild/makefiles.txt       | 36 ++++++++++++++++
 Documentation/sections/linker-tables.rst | 15 +++++++
 include/linux/tables.h                   | 71 ++++++++++++++++++++++++++++++++
 init/Kconfig                             | 22 ++++++++++
 scripts/Makefile.build                   |  7 ++--
 scripts/Makefile.lib                     | 11 +++++
 6 files changed, 159 insertions(+), 3 deletions(-)

diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 385a5ef41c17..01c260913f5c 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -1089,6 +1089,42 @@ When kbuild executes, the following steps are followed (roughly):
 	In this example, extra-y is used to list object files that
 	shall be built, but shall not be linked as part of built-in.o.
 
+    force-obj-y force-lib-y
+
+	When CONFIG_BUILD_AVOID_BITROT is enabled using these targets for your
+	kconfig symbols forces compilation of the associated objects if the
+	kconfig's symbol's dependencies are met, the objects however are only
+	linked into to the kernel if and only if the kconfig symbol was
+	enabled. If CONFIG_BUILD_AVOID_BITROT is disabled the force-obj-y and
+	force-lib-y targets are functionally equilvalent to obj-y and lib-y
+	respectively.
+
+	Using force-obj-y and force-lib-y are part of a code architecture and
+	build philosophy further enabled by linker tables, for more details
+	refer to the documention in include/linux/tables.h, refer to the
+	sections:
+
+		o The code bit-rot problem
+		o The build-all selective-link philosophy
+		o Avoiding the code bit-rot problem with linker tables
+		o Linker table module support
+
+	Modules support is expected to be enhanced in the future, so for now
+	only built-in features are supported.
+
+	Example use:
+
+		force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	An alternative to using force-obj-y, is to use extra-y followed by the
+	respective obj-y:
+
+		extra-y += foo.o
+		obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	Using force-obj-y and force-lib-y can be used to help annotate the
+	targets follow the 'build-all selective-link philosophy' further
+	enabled by linker tables.
 
 --- 6.7 Commands useful for building a boot image
 
diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index df11c632dca7..e425c5cd36d6 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -30,6 +30,21 @@ How linker tables simplify initialization code
 .. kernel-doc:: include/linux/tables.h
    :doc: How linker tables simplify initialization code
 
+The code bit-rot problem
+------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The code bit-rot problem
+
+The build-all selective-link philosophy
+---------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The build-all selective-link philosophy
+
+Avoiding the code bit-rot problem with linker tables
+----------------------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: Avoiding the code bit-rot problem with linker tables
+
 Using linker tables in Linux
 ============================
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
index 423827eafb52..bf8fae7f9246 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -169,6 +169,77 @@
  */
 
 /**
+ * DOC: The code bit-rot problem
+ *
+ * Linux provides a rich array of features, enabling each feature
+ * however increases the size of the kernel and there are many
+ * features which users often want disabled. The traditional
+ * solution to this problem is for each feature to have its own
+ * Kconfig symbol, followed by a series of #ifdef statements
+ * in C code and header files, allowing the feature to be compiled
+ * only when desirable. As the variability of Linux increases build
+ * tests can and are often done with random kernel configurations,
+ * allyesconfig, and allmodconfig to help find code issues. This
+ * however doesn't catch all errors and as a consequence code that
+ * is typically not enabled often can suffer from bit-rot over time.
+ */
+
+/**
+ * DOC: The build-all selective-link philosophy
+ *
+ * A code architecture philosophy to help avoid code bit-rot consists
+ * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
+ * by instead having each feature implemented it its own C file, and force
+ * compilation for all features. Only features that are enabled get linked in,
+ * the forced compilation therefore has no size impact on the final result of
+ * the kernel. The practice of having each feature implemented in its own C
+ * file is already prevalent in many subsystems, however #ifdefs are still
+ * typically required during feature initialization. For instance in::
+ *
+ *	#ifdef CONFIG_FOO
+ *	foo_init();
+ *	#endif
+ *
+ * We cannot remove the #ifdef and leave foo_init() as we'd either
+ * need to always enable the feature or add a respective #ifdef in a
+ * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem with linker tables
+ *
+ * Linker tables can be used to further help avoid the code bit-rot problem
+ * when embracing the 'build-all selective-link philosophy' by lifting the
+ * requirement to use of #ifdefs during initialization. With linker tables
+ * initialization sequences can be aggregated into a custom ELF section at
+ * link time, during run time the table can be iterated over and each init
+ * sequence enabled can be called. A feature's init routine is only added to a
+ * table when its respective Kconfig symbols has been enabled and therefore
+ * linked in. Linker tables enable subsystems to completely do away with
+ * #ifdefs if one is comfortable in accepting all subsystem's feature's
+ * structural size implications.
+ *
+ * To further help with this the Linux build system supports two special
+ * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
+ * follow the 'build-all selective-link philosophy' can use these targets for a
+ * feature's kconfig symbol. Using these targets will always require
+ * compilation of the kconfig's objects if the kconfig symbol's dependencies
+ * are met but only link the objects into the kernel, and therefore enable the
+ * feature, if and only if the kconfig symbol has been enabled.
+ *
+ * Not all users or build systems may want to opt-in to compile all objects
+ * following the 'build-all selective-link philosophy', as such the targets
+ * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
+ * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
+ * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
+ * ``obj-y`` and ``lib-y`` respectively.
+ *
+ * Example use::
+ *
+ * 	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+ */
+
+/**
  * DOC: Linker table module support
  *
  * Modules can use linker tables, however the linker table definition
diff --git a/init/Kconfig b/init/Kconfig
index cac3f096050d..ef09e83b9196 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -53,6 +53,28 @@ config CROSS_COMPILE
 	  need to set this unless you want the configured kernel build
 	  directory to select the cross-compiler automatically.
 
+config BUILD_AVOID_BITROT
+	bool "Enable force building of force-obj-y and force-lib-y"
+	default n
+	help
+	  When enabled objects under the force-obj-y and force-lib-y targets
+	  using a Kconfig symbol will be forced to compile if the Kconfig
+	  symbol's dependencies are met but only linked into the kernel if
+	  the Kconfig symbol is enabled. If a Kconfig symbol on a force-obj-y
+	  or force-lib-y target is disabled, it will be compiled but not linked
+	  into the kernel.
+
+	  The force-obj-y and force-lib-y targets can be used by subsystems
+	  which wish to want to follow the 'build-all selective-link philosophy'
+	  documented under include/linux/tables.h.
+
+	  Say Y if you have a decent build machine and would like to help test
+	  building code for more subsystems. Say N if you do you not have a
+	  good build machine or only want to compile what you've enabled for
+	  your kernel.
+
+	  Enabling this option never increases the size of your kernel.
+
 config COMPILE_TEST
 	bool "Compile also drivers which will not load"
 	depends on !UML
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index cd9bf22bb027..cc2c7241d193 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -92,7 +92,8 @@ modorder-target := $(obj)/modules.order
 
 # We keep a list of all modules in $(MODVERDIR)
 
-__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
+__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y) \
+				$(force-obj-y)) \
 	 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
 	 $(subdir-ym) $(always)
 	@:
@@ -326,8 +327,8 @@ cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $<
 $(obj)/%.o: $(src)/%.S $(objtool_obj) FORCE
 	$(call if_changed_rule,as_o_S)
 
-targets += $(real-objs-y) $(real-objs-m) $(lib-y)
-targets += $(extra-y) $(MAKECMDGOALS) $(always)
+targets += $(real-objs-y) $(real-objs-m) $(lib-y) $(force-lib-y)
+targets += $(extra-y) $(force-obj-y) $(MAKECMDGOALS) $(always)
 
 # Linker scripts preprocessor (.lds.S -> .lds)
 # ---------------------------------------------------------------------------
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 0a07f9014944..d1cb0cfdf1bf 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -12,6 +12,15 @@ export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y)
 # Figure out what we need to build from the various variables
 # ===========================================================================
 
+ifeq ($(CONFIG_BUILD_AVOID_BITROT),y)
+extra-y += $(force-obj-) $(force-lib-)
+endif
+
+obj-m += $(force-obj-m)
+obj-y += $(force-obj-y)
+lib-m += $(force-lib-m)
+lib-y += $(force-lib-y)
+
 # When an object is listed to be built compiled-in and modular,
 # only build the compiled-in version
 
@@ -72,6 +81,8 @@ real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)
 # Add subdir path
 
 extra-y		:= $(addprefix $(obj)/,$(extra-y))
+force-obj-y		:= $(addprefix $(obj)/,$(force-obj-y))
+force-obj-m		:= $(addprefix $(obj)/,$(force-obj-m))
 always		:= $(addprefix $(obj)/,$(always))
 targets		:= $(addprefix $(obj)/,$(targets))
 modorder	:= $(addprefix $(obj)/,$(modorder))
-- 
2.9.2


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 08/16] kbuild: enable option to force compile force-obj-y and force-lib-y
@ 2016-08-19 21:32   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Linux provides a rich array of features, enabling each feature
however increases the size of the kernel and there are many
features which users often want disabled. The traditional
solution to this problem is for each feature to have its own
Kconfig symbol, followed by a series of #ifdef statements
in C code and header files, allowing the feature to be compiled
only when desirable. As the variability of Linux increases build
tests can and are often done with random kernel configurations,
allyesconfig, and allmodconfig to help find code issues. This
however doesn't catch all errors and as a consequence code that
is typically not enabled often can suffer from bit-rot over time.

An alternative approach for subsystems, which refer to as the 'build-all
link-selectively philosophy' is to keep the Kconfig symbols, replace
the #ifdef approach by having each feature implemented it its own C file,
and force compilation for all features to avoid the code bit-rot problem.
With this strategy only features that are enabled via Kconfig get
linked into the kernel, so the forced compilation has no size impact
on the kernel. The practice of having each feature implemented in its own
C file is already prevalent in many subsystems, however #ifdefs are still
typically required during feature initialization. For instance in:

  #ifdef CONFIG_FOO
  foo_init();
  #endif

We cannot remove the #ifdef and leave foo_init() as we'd either
need to always enable the feature or add a respective #ifdef in a
foo.h which makes foo_init() do nothing when CONFIG_FOO is disabled.

Linker tables enable lifting the requirement to use of #ifdefs during
initialization. With linker tables initialization sequences can instead
be aggregated into a custom ELF section at link time, during run time
the table can be iterated over and each init sequence enabled can be called.
A feature's init routine is only added to a table when its respective
Kconfig symbols has been enabled and therefore linked in. Linker tables
enable subsystems to completely do away with #ifdefs if one is comfortable
in accepting all subsystem's feature's structural size implications.

Subsystems which want to follow the 'build-all link-selectively
philosophy' still need a way to easily express and annotate that they
wish for all code to always be compiled to help avoid code bit rot,
as such two new targets force-obj-y and force-lib-y are provided to
help with this. Its not fair to require everyone to force compilation
of all features of a subsystem though, so as a compromise, the new
targets only force compilation when CONFIG_BUILD_AVOID_BITROT is
enabled.

Only built-in features are supported at the moment. Module support
is expected to be added after a generic solution to add linker
tables to modules more easily is developed.

v4: this patch was added to this series, it was split off from the
    linker tables addition due to the confusion over the code bit
    rot alternatives that are possible with linker tables.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/kbuild/makefiles.txt       | 36 ++++++++++++++++
 Documentation/sections/linker-tables.rst | 15 +++++++
 include/linux/tables.h                   | 71 ++++++++++++++++++++++++++++++++
 init/Kconfig                             | 22 ++++++++++
 scripts/Makefile.build                   |  7 ++--
 scripts/Makefile.lib                     | 11 +++++
 6 files changed, 159 insertions(+), 3 deletions(-)

diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 385a5ef41c17..01c260913f5c 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -1089,6 +1089,42 @@ When kbuild executes, the following steps are followed (roughly):
 	In this example, extra-y is used to list object files that
 	shall be built, but shall not be linked as part of built-in.o.
 
+    force-obj-y force-lib-y
+
+	When CONFIG_BUILD_AVOID_BITROT is enabled using these targets for your
+	kconfig symbols forces compilation of the associated objects if the
+	kconfig's symbol's dependencies are met, the objects however are only
+	linked into to the kernel if and only if the kconfig symbol was
+	enabled. If CONFIG_BUILD_AVOID_BITROT is disabled the force-obj-y and
+	force-lib-y targets are functionally equilvalent to obj-y and lib-y
+	respectively.
+
+	Using force-obj-y and force-lib-y are part of a code architecture and
+	build philosophy further enabled by linker tables, for more details
+	refer to the documention in include/linux/tables.h, refer to the
+	sections:
+
+		o The code bit-rot problem
+		o The build-all selective-link philosophy
+		o Avoiding the code bit-rot problem with linker tables
+		o Linker table module support
+
+	Modules support is expected to be enhanced in the future, so for now
+	only built-in features are supported.
+
+	Example use:
+
+		force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	An alternative to using force-obj-y, is to use extra-y followed by the
+	respective obj-y:
+
+		extra-y += foo.o
+		obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	Using force-obj-y and force-lib-y can be used to help annotate the
+	targets follow the 'build-all selective-link philosophy' further
+	enabled by linker tables.
 
 --- 6.7 Commands useful for building a boot image
 
diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index df11c632dca7..e425c5cd36d6 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -30,6 +30,21 @@ How linker tables simplify initialization code
 .. kernel-doc:: include/linux/tables.h
    :doc: How linker tables simplify initialization code
 
+The code bit-rot problem
+------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The code bit-rot problem
+
+The build-all selective-link philosophy
+---------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The build-all selective-link philosophy
+
+Avoiding the code bit-rot problem with linker tables
+----------------------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: Avoiding the code bit-rot problem with linker tables
+
 Using linker tables in Linux
 ============================
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
index 423827eafb52..bf8fae7f9246 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -169,6 +169,77 @@
  */
 
 /**
+ * DOC: The code bit-rot problem
+ *
+ * Linux provides a rich array of features, enabling each feature
+ * however increases the size of the kernel and there are many
+ * features which users often want disabled. The traditional
+ * solution to this problem is for each feature to have its own
+ * Kconfig symbol, followed by a series of #ifdef statements
+ * in C code and header files, allowing the feature to be compiled
+ * only when desirable. As the variability of Linux increases build
+ * tests can and are often done with random kernel configurations,
+ * allyesconfig, and allmodconfig to help find code issues. This
+ * however doesn't catch all errors and as a consequence code that
+ * is typically not enabled often can suffer from bit-rot over time.
+ */
+
+/**
+ * DOC: The build-all selective-link philosophy
+ *
+ * A code architecture philosophy to help avoid code bit-rot consists
+ * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
+ * by instead having each feature implemented it its own C file, and force
+ * compilation for all features. Only features that are enabled get linked in,
+ * the forced compilation therefore has no size impact on the final result of
+ * the kernel. The practice of having each feature implemented in its own C
+ * file is already prevalent in many subsystems, however #ifdefs are still
+ * typically required during feature initialization. For instance in::
+ *
+ *	#ifdef CONFIG_FOO
+ *	foo_init();
+ *	#endif
+ *
+ * We cannot remove the #ifdef and leave foo_init() as we'd either
+ * need to always enable the feature or add a respective #ifdef in a
+ * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem with linker tables
+ *
+ * Linker tables can be used to further help avoid the code bit-rot problem
+ * when embracing the 'build-all selective-link philosophy' by lifting the
+ * requirement to use of #ifdefs during initialization. With linker tables
+ * initialization sequences can be aggregated into a custom ELF section at
+ * link time, during run time the table can be iterated over and each init
+ * sequence enabled can be called. A feature's init routine is only added to a
+ * table when its respective Kconfig symbols has been enabled and therefore
+ * linked in. Linker tables enable subsystems to completely do away with
+ * #ifdefs if one is comfortable in accepting all subsystem's feature's
+ * structural size implications.
+ *
+ * To further help with this the Linux build system supports two special
+ * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
+ * follow the 'build-all selective-link philosophy' can use these targets for a
+ * feature's kconfig symbol. Using these targets will always require
+ * compilation of the kconfig's objects if the kconfig symbol's dependencies
+ * are met but only link the objects into the kernel, and therefore enable the
+ * feature, if and only if the kconfig symbol has been enabled.
+ *
+ * Not all users or build systems may want to opt-in to compile all objects
+ * following the 'build-all selective-link philosophy', as such the targets
+ * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
+ * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
+ * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
+ * ``obj-y`` and ``lib-y`` respectively.
+ *
+ * Example use::
+ *
+ * 	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+ */
+
+/**
  * DOC: Linker table module support
  *
  * Modules can use linker tables, however the linker table definition
diff --git a/init/Kconfig b/init/Kconfig
index cac3f096050d..ef09e83b9196 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -53,6 +53,28 @@ config CROSS_COMPILE
 	  need to set this unless you want the configured kernel build
 	  directory to select the cross-compiler automatically.
 
+config BUILD_AVOID_BITROT
+	bool "Enable force building of force-obj-y and force-lib-y"
+	default n
+	help
+	  When enabled objects under the force-obj-y and force-lib-y targets
+	  using a Kconfig symbol will be forced to compile if the Kconfig
+	  symbol's dependencies are met but only linked into the kernel if
+	  the Kconfig symbol is enabled. If a Kconfig symbol on a force-obj-y
+	  or force-lib-y target is disabled, it will be compiled but not linked
+	  into the kernel.
+
+	  The force-obj-y and force-lib-y targets can be used by subsystems
+	  which wish to want to follow the 'build-all selective-link philosophy'
+	  documented under include/linux/tables.h.
+
+	  Say Y if you have a decent build machine and would like to help test
+	  building code for more subsystems. Say N if you do you not have a
+	  good build machine or only want to compile what you've enabled for
+	  your kernel.
+
+	  Enabling this option never increases the size of your kernel.
+
 config COMPILE_TEST
 	bool "Compile also drivers which will not load"
 	depends on !UML
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index cd9bf22bb027..cc2c7241d193 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -92,7 +92,8 @@ modorder-target := $(obj)/modules.order
 
 # We keep a list of all modules in $(MODVERDIR)
 
-__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
+__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y) \
+				$(force-obj-y)) \
 	 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
 	 $(subdir-ym) $(always)
 	@:
@@ -326,8 +327,8 @@ cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $<
 $(obj)/%.o: $(src)/%.S $(objtool_obj) FORCE
 	$(call if_changed_rule,as_o_S)
 
-targets += $(real-objs-y) $(real-objs-m) $(lib-y)
-targets += $(extra-y) $(MAKECMDGOALS) $(always)
+targets += $(real-objs-y) $(real-objs-m) $(lib-y) $(force-lib-y)
+targets += $(extra-y) $(force-obj-y) $(MAKECMDGOALS) $(always)
 
 # Linker scripts preprocessor (.lds.S -> .lds)
 # ---------------------------------------------------------------------------
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 0a07f9014944..d1cb0cfdf1bf 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -12,6 +12,15 @@ export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y)
 # Figure out what we need to build from the various variables
 # ===========================================================================
 
+ifeq ($(CONFIG_BUILD_AVOID_BITROT),y)
+extra-y += $(force-obj-) $(force-lib-)
+endif
+
+obj-m += $(force-obj-m)
+obj-y += $(force-obj-y)
+lib-m += $(force-lib-m)
+lib-y += $(force-lib-y)
+
 # When an object is listed to be built compiled-in and modular,
 # only build the compiled-in version
 
@@ -72,6 +81,8 @@ real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)
 # Add subdir path
 
 extra-y		:= $(addprefix $(obj)/,$(extra-y))
+force-obj-y		:= $(addprefix $(obj)/,$(force-obj-y))
+force-obj-m		:= $(addprefix $(obj)/,$(force-obj-m))
 always		:= $(addprefix $(obj)/,$(always))
 targets		:= $(addprefix $(obj)/,$(targets))
 modorder	:= $(addprefix $(obj)/,$(modorder))
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 09/16] firmware/Makefile: force recompilation if makefile changes
  2016-08-19 21:32 ` mcgrof
  (?)
@ 2016-08-19 21:32   ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

If you modify the target asm we currently do not force the
recompilation of the firmware files. The target asm is in
the firmware/Makefile, peg this file as a dependency to
require re-compilation of firmware targets when the asm
changes.

v3: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 firmware/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/firmware/Makefile b/firmware/Makefile
index e297e1b52636..fa3e81c2a97b 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -176,7 +176,8 @@ quiet_cmd_fwbin = MK_FW   $@
 wordsize_deps := $(wildcard include/config/64bit.h include/config/32bit.h \
 		include/config/ppc32.h include/config/ppc64.h \
 		include/config/superh32.h include/config/superh64.h \
-		include/config/x86_32.h include/config/x86_64.h)
+		include/config/x86_32.h include/config/x86_64.h \
+		firmware/Makefile)
 
 $(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)): %: $(wordsize_deps)
 	$(call cmd,fwbin,$(patsubst %.gen.S,%,$@))
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 09/16] firmware/Makefile: force recompilation if makefile changes
@ 2016-08-19 21:32   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

If you modify the target asm we currently do not force the
recompilation of the firmware files. The target asm is in
the firmware/Makefile, peg this file as a dependency to
require re-compilation of firmware targets when the asm
changes.

v3: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 firmware/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/firmware/Makefile b/firmware/Makefile
index e297e1b52636..fa3e81c2a97b 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -176,7 +176,8 @@ quiet_cmd_fwbin = MK_FW   $@
 wordsize_deps := $(wildcard include/config/64bit.h include/config/32bit.h \
 		include/config/ppc32.h include/config/ppc64.h \
 		include/config/superh32.h include/config/superh64.h \
-		include/config/x86_32.h include/config/x86_64.h)
+		include/config/x86_32.h include/config/x86_64.h \
+		firmware/Makefile)
 
 $(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)): %: $(wordsize_deps)
 	$(call cmd,fwbin,$(patsubst %.gen.S,%,$@))
-- 
2.9.2


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 09/16] firmware/Makefile: force recompilation if makefile changes
@ 2016-08-19 21:32   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

If you modify the target asm we currently do not force the
recompilation of the firmware files. The target asm is in
the firmware/Makefile, peg this file as a dependency to
require re-compilation of firmware targets when the asm
changes.

v3: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 firmware/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/firmware/Makefile b/firmware/Makefile
index e297e1b52636..fa3e81c2a97b 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -176,7 +176,8 @@ quiet_cmd_fwbin = MK_FW   $@
 wordsize_deps := $(wildcard include/config/64bit.h include/config/32bit.h \
 		include/config/ppc32.h include/config/ppc64.h \
 		include/config/superh32.h include/config/superh64.h \
-		include/config/x86_32.h include/config/x86_64.h)
+		include/config/x86_32.h include/config/x86_64.h \
+		firmware/Makefile)
 
 $(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)): %: $(wordsize_deps)
 	$(call cmd,fwbin,$(patsubst %.gen.S,%,$@))
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 10/16] firmware: port built-in section to linker table
  2016-08-19 21:32 ` mcgrof
  (?)
@ 2016-08-19 21:32   ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, Michael Matz, Barry Song, mchehab, linux-arch,
	markus.heiser, xen-devel, msalter, linux-sh, mpe, x86, fontana,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, Guenter Roeck,
	linux-xtensa, pali.rohar, Mike Frysinger, keescook, arnd,
	jani.nikula, will.dea

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This ports built-in firmware to use linker tables,
this replaces the custom section solution with a
generic solution.

This also demos the use of the .rodata (SECTION_RO)
linker tables.

Tested with 0 built-in firmware, 1 and 2 built-in
firmwares successfully.

v4:

o work around c6x toolchain bug by using SECTION_TBL_RO

o fix compilation on blackfin

v3:
o explicitly include tables.h as we no longer include
  tables.h from sections.h

o use new section_tbl_asmtype() helper on firmware/Makefile
  to enable having to unfold things on our own.

v2: introduced this file in this version of the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/x86/kernel/cpu/microcode/core.c |  8 ++++----
 drivers/base/firmware_class.c        | 12 ++++++------
 firmware/Makefile                    |  3 ++-
 include/asm-generic/vmlinux.lds.h    |  7 -------
 4 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index df04b2d033f6..3e7c08d99601 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -31,6 +31,7 @@
 #include <linux/cpu.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/tables.h>
 
 #include <asm/microcode_intel.h>
 #include <asm/cpu_device_id.h>
@@ -91,15 +92,14 @@ static bool __init check_loader_disabled_bsp(void)
 	return *res;
 }
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DECLARE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 bool get_builtin_firmware(struct cpio_data *cd, const char *name)
 {
 #ifdef CONFIG_FW_LOADER
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw) {
 		if (!strcmp(name, b_fw->name)) {
 			cd->size = b_fw->size;
 			cd->data = b_fw->data;
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 22d1760a4278..8fbf03c3e4c2 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -30,6 +30,7 @@
 #include <linux/syscore_ops.h>
 #include <linux/reboot.h>
 #include <linux/security.h>
+#include <linux/tables.h>
 
 #include <generated/utsrelease.h>
 
@@ -43,15 +44,14 @@ MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_FW_LOADER
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DEFINE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 				    void *buf, size_t size)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw) {
 		if (strcmp(name, b_fw->name) = 0) {
 			fw->size = b_fw->size;
 			fw->data = b_fw->data;
@@ -67,9 +67,9 @@ static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 
 static bool fw_is_builtin_firmware(const struct firmware *fw)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++)
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw)
 		if (fw->data = b_fw->data)
 			return true;
 
diff --git a/firmware/Makefile b/firmware/Makefile
index fa3e81c2a97b..9e701bf4ced2 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -155,6 +155,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  ASM_ALIGN=$(if $(CONFIG_64BIT),3,2);			     \
 		  PROGBITS=$(if $(CONFIG_ARM),%,@)progbits;		     \
 		  echo "/* Generated by firmware/Makefile */"		> $@;\
+		  echo "\#include <asm/tables.h>"			>>$@;\
 		  echo "    .section .rodata"				>>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_bin:"				>>$@;\
@@ -164,7 +165,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_name:"				>>$@;\
 		  echo "    .string \"$$FWNAME\""			>>$@;\
-		  echo "    .section .builtin_fw,\"a\",$${PROGBITS}"	>>$@;\
+		  echo "    set_section_tbl_type(SECTION_TBL_RO, builtin_fw, SECTION_ORDER_ANY, a,$${PROGBITS})" >>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_name"		>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_bin"		>>$@;\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 4b6a3d820883..2413444c048d 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -316,13 +316,6 @@
 		VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .;	\
 	}								\
 									\
-	/* Built-in firmware blobs */					\
-	.builtin_fw        : AT(ADDR(.builtin_fw) - LOAD_OFFSET) {	\
-		VMLINUX_SYMBOL(__start_builtin_fw) = .;			\
-		*(.builtin_fw)						\
-		VMLINUX_SYMBOL(__end_builtin_fw) = .;			\
-	}								\
-									\
 	TRACEDATA							\
 									\
 	/* Kernel symbol table: Normal symbols */			\
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 10/16] firmware: port built-in section to linker table
@ 2016-08-19 21:32   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, Michael Matz, Barry Song, mchehab, linux-arch,
	markus.heiser, xen-devel, msalter, linux-sh, mpe, x86, fontana,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, Guenter Roeck,
	linux-xtensa, pali.rohar, Mike Frysinger, keescook, arnd,
	jani.nikula, will.dea

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This ports built-in firmware to use linker tables,
this replaces the custom section solution with a
generic solution.

This also demos the use of the .rodata (SECTION_RO)
linker tables.

Tested with 0 built-in firmware, 1 and 2 built-in
firmwares successfully.

v4:

o work around c6x toolchain bug by using SECTION_TBL_RO

o fix compilation on blackfin

v3:
o explicitly include tables.h as we no longer include
  tables.h from sections.h

o use new section_tbl_asmtype() helper on firmware/Makefile
  to enable having to unfold things on our own.

v2: introduced this file in this version of the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/x86/kernel/cpu/microcode/core.c |  8 ++++----
 drivers/base/firmware_class.c        | 12 ++++++------
 firmware/Makefile                    |  3 ++-
 include/asm-generic/vmlinux.lds.h    |  7 -------
 4 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index df04b2d033f6..3e7c08d99601 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -31,6 +31,7 @@
 #include <linux/cpu.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/tables.h>
 
 #include <asm/microcode_intel.h>
 #include <asm/cpu_device_id.h>
@@ -91,15 +92,14 @@ static bool __init check_loader_disabled_bsp(void)
 	return *res;
 }
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DECLARE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 bool get_builtin_firmware(struct cpio_data *cd, const char *name)
 {
 #ifdef CONFIG_FW_LOADER
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw) {
 		if (!strcmp(name, b_fw->name)) {
 			cd->size = b_fw->size;
 			cd->data = b_fw->data;
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 22d1760a4278..8fbf03c3e4c2 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -30,6 +30,7 @@
 #include <linux/syscore_ops.h>
 #include <linux/reboot.h>
 #include <linux/security.h>
+#include <linux/tables.h>
 
 #include <generated/utsrelease.h>
 
@@ -43,15 +44,14 @@ MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_FW_LOADER
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DEFINE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 				    void *buf, size_t size)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw) {
 		if (strcmp(name, b_fw->name) == 0) {
 			fw->size = b_fw->size;
 			fw->data = b_fw->data;
@@ -67,9 +67,9 @@ static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 
 static bool fw_is_builtin_firmware(const struct firmware *fw)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++)
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw)
 		if (fw->data == b_fw->data)
 			return true;
 
diff --git a/firmware/Makefile b/firmware/Makefile
index fa3e81c2a97b..9e701bf4ced2 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -155,6 +155,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  ASM_ALIGN=$(if $(CONFIG_64BIT),3,2);			     \
 		  PROGBITS=$(if $(CONFIG_ARM),%,@)progbits;		     \
 		  echo "/* Generated by firmware/Makefile */"		> $@;\
+		  echo "\#include <asm/tables.h>"			>>$@;\
 		  echo "    .section .rodata"				>>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_bin:"				>>$@;\
@@ -164,7 +165,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_name:"				>>$@;\
 		  echo "    .string \"$$FWNAME\""			>>$@;\
-		  echo "    .section .builtin_fw,\"a\",$${PROGBITS}"	>>$@;\
+		  echo "    set_section_tbl_type(SECTION_TBL_RO, builtin_fw, SECTION_ORDER_ANY, a,$${PROGBITS})" >>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_name"		>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_bin"		>>$@;\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 4b6a3d820883..2413444c048d 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -316,13 +316,6 @@
 		VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .;	\
 	}								\
 									\
-	/* Built-in firmware blobs */					\
-	.builtin_fw        : AT(ADDR(.builtin_fw) - LOAD_OFFSET) {	\
-		VMLINUX_SYMBOL(__start_builtin_fw) = .;			\
-		*(.builtin_fw)						\
-		VMLINUX_SYMBOL(__end_builtin_fw) = .;			\
-	}								\
-									\
 	TRACEDATA							\
 									\
 	/* Kernel symbol table: Normal symbols */			\
-- 
2.9.2


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 10/16] firmware: port built-in section to linker table
@ 2016-08-19 21:32   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:32 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez, Barry Song, Mike Frysinger,
	Michael Matz, Guenter Roeck, Fengguang Wu

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This ports built-in firmware to use linker tables,
this replaces the custom section solution with a
generic solution.

This also demos the use of the .rodata (SECTION_RO)
linker tables.

Tested with 0 built-in firmware, 1 and 2 built-in
firmwares successfully.

v4:

o work around c6x toolchain bug by using SECTION_TBL_RO

o fix compilation on blackfin

v3:
o explicitly include tables.h as we no longer include
  tables.h from sections.h

o use new section_tbl_asmtype() helper on firmware/Makefile
  to enable having to unfold things on our own.

v2: introduced this file in this version of the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/x86/kernel/cpu/microcode/core.c |  8 ++++----
 drivers/base/firmware_class.c        | 12 ++++++------
 firmware/Makefile                    |  3 ++-
 include/asm-generic/vmlinux.lds.h    |  7 -------
 4 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index df04b2d033f6..3e7c08d99601 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -31,6 +31,7 @@
 #include <linux/cpu.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/tables.h>
 
 #include <asm/microcode_intel.h>
 #include <asm/cpu_device_id.h>
@@ -91,15 +92,14 @@ static bool __init check_loader_disabled_bsp(void)
 	return *res;
 }
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DECLARE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 bool get_builtin_firmware(struct cpio_data *cd, const char *name)
 {
 #ifdef CONFIG_FW_LOADER
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw) {
 		if (!strcmp(name, b_fw->name)) {
 			cd->size = b_fw->size;
 			cd->data = b_fw->data;
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 22d1760a4278..8fbf03c3e4c2 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -30,6 +30,7 @@
 #include <linux/syscore_ops.h>
 #include <linux/reboot.h>
 #include <linux/security.h>
+#include <linux/tables.h>
 
 #include <generated/utsrelease.h>
 
@@ -43,15 +44,14 @@ MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_FW_LOADER
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DEFINE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 				    void *buf, size_t size)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw) {
 		if (strcmp(name, b_fw->name) == 0) {
 			fw->size = b_fw->size;
 			fw->data = b_fw->data;
@@ -67,9 +67,9 @@ static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 
 static bool fw_is_builtin_firmware(const struct firmware *fw)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++)
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw)
 		if (fw->data == b_fw->data)
 			return true;
 
diff --git a/firmware/Makefile b/firmware/Makefile
index fa3e81c2a97b..9e701bf4ced2 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -155,6 +155,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  ASM_ALIGN=$(if $(CONFIG_64BIT),3,2);			     \
 		  PROGBITS=$(if $(CONFIG_ARM),%,@)progbits;		     \
 		  echo "/* Generated by firmware/Makefile */"		> $@;\
+		  echo "\#include <asm/tables.h>"			>>$@;\
 		  echo "    .section .rodata"				>>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_bin:"				>>$@;\
@@ -164,7 +165,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_name:"				>>$@;\
 		  echo "    .string \"$$FWNAME\""			>>$@;\
-		  echo "    .section .builtin_fw,\"a\",$${PROGBITS}"	>>$@;\
+		  echo "    set_section_tbl_type(SECTION_TBL_RO, builtin_fw, SECTION_ORDER_ANY, a,$${PROGBITS})" >>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_name"		>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_bin"		>>$@;\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 4b6a3d820883..2413444c048d 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -316,13 +316,6 @@
 		VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .;	\
 	}								\
 									\
-	/* Built-in firmware blobs */					\
-	.builtin_fw        : AT(ADDR(.builtin_fw) - LOAD_OFFSET) {	\
-		VMLINUX_SYMBOL(__start_builtin_fw) = .;			\
-		*(.builtin_fw)						\
-		VMLINUX_SYMBOL(__end_builtin_fw) = .;			\
-	}								\
-									\
 	TRACEDATA							\
 									\
 	/* Kernel symbol table: Normal symbols */			\
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 00/16] linux: generalize sections, ranges and linker tables
@ 2016-08-19 21:33   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:33 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This v4 addresses feedback from the previous v3 series [0], and also
addresses a huge array of additional tests against many architectures
outside of what 0-day provides. As I mentioned in my last v3 series,
0-day had only found one issue with the series, a blackfin architecture
linker issue with the last series. Guenter Rock was kind enough to give
my series a test spin on his test bed and he found quite a bit of other
oddball issues with obscure architectures, and even on x86 with an old
toolchain. After a lot of work and coordinating with a few maintainers
I'm happy to report all issues found so far through all possible testing
I could do are now fixed, this series also addresses all feedback from
the last series, as such this goes submitted as PATCH form.

In addressing fixing this work on a few architectures some of the previous
patches are further simplified. The kprobes port to linker tables is made
much easier now that I've addressed moving out core kprobe declarations
into asm-generic/kprobes.h. Refer to the patch "kprobes: move kprobe
declarations to asm-generic/kprobes.h". This makes for a much cleaner
solution across architectures.

Boris feedback on making the code bit rot feature optional is addressed
by using a new Kconfig symbol for this, CONFIG_BUILD_AVOID_BITROT,
but given Greg's concerns over lack of clarity over what this was all about
I've ripped that functionality out into its own patch with a bit more
extensive documentation and re-wording. See the patch "kbuild: enable option
to force compile force-obj-y and force-lib-y". I hope makes it clear how
linker tables can help with avoiding code bit rot. I've gone with a new
Kconfig symbol CONFIG_BUILD_AVOID_BITROT given CONFIG_COMPILE_TEST is
not available on UML, this feature is desirable on all architectures.

The documentation is revamped, now that the DocBook format is deprecated
I ported the documention into the trendy hipster Sphinx documentation
format.

AT Boris' request I've adapated the userspace linker table application
forintegration into the kernel under tools/ to make it easier to keep
things in sync, however since this requires a bit of changes to some headers
in tools/ I'll submit that separately.

[0] https://lkml.kernel.org/r/1469222687-1600-1-git-send-email-mcgrof@kernel.org

If you'd like this in git-form, you can get it on the 20160819-linker-table-v4
branch of my linux-next tree on kernel.org, this also includes the series of
the linker table userspace sandbox:

https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h 160819-linker-table-v4

Please let me know if there are any concerns or questions.

Luis R. Rodriguez (16):
  x86: remove LTO_REFERENCE_INITCALL()
  dell-smo8800: include uaccess.h
  scripts/module-common.lds: enable generation
  generic-sections: add section core helpers
  xtensa: skip adding literal when SORT() is used
  ranges.h: add helpers to build and identify Linux section ranges
  tables.h: add linker table support
  kbuild: enable option to force compile force-obj-y and force-lib-y
  firmware/Makefile: force recompilation if makefile changes
  firmware: port built-in section to linker table
  jump_label: move guard #endif down where it belongs
  jump_label: port __jump_table to linker tables
  dynamic_debug: port to use linker tables
  kprobes: move kprobe declarations to asm-generic/kprobes.h
  kprobes: port .kprobes.text to section range
  kprobes: port blacklist kprobes to linker table

 .gitignore                                         |   2 +
 Documentation/index.rst                            |   1 +
 Documentation/kbuild/makefiles.txt                 |  36 ++
 Documentation/sections/conf.py                     |   4 +
 Documentation/sections/index.rst                   |  13 +
 Documentation/sections/linker-tables.rst           | 202 +++++++
 Documentation/sections/ranges.rst                  |  49 ++
 Documentation/sections/section-core.rst            | 153 +++++
 MAINTAINERS                                        |  37 ++
 Makefile                                           |   6 +-
 arch/alpha/include/asm/Kbuild                      |   4 +
 arch/arc/include/asm/Kbuild                        |   3 +
 arch/arc/include/asm/kprobes.h                     |   6 +-
 arch/arc/kernel/vmlinux.lds.S                      |   1 -
 arch/arm/include/asm/Kbuild                        |   3 +
 arch/arm/include/asm/jump_label.h                  |   6 +-
 arch/arm/include/asm/kprobes.h                     |   4 +
 arch/arm/kernel/entry-armv.S                       |   3 +-
 arch/arm/kernel/vmlinux-xip.lds.S                  |   1 -
 arch/arm/kernel/vmlinux.lds.S                      |   1 -
 arch/arm/probes/decode.h                           |   1 +
 arch/arm64/include/asm/Kbuild                      |   3 +
 arch/arm64/include/asm/jump_label.h                |   6 +-
 arch/arm64/include/asm/kprobes.h                   |   4 +
 arch/arm64/kernel/armv8_deprecated.c               |   1 +
 arch/arm64/kernel/insn.c                           |   1 +
 arch/arm64/kernel/probes/kprobes.c                 |   4 +-
 arch/arm64/kernel/vmlinux.lds.S                    |   1 -
 arch/avr32/include/asm/Kbuild                      |   3 +
 arch/avr32/include/asm/kprobes.h                   |   4 +
 arch/avr32/kernel/entry-avr32b.S                   |  13 +-
 arch/avr32/kernel/vmlinux.lds.S                    |   1 -
 arch/blackfin/include/asm/Kbuild                   |   4 +
 arch/blackfin/kernel/vmlinux.lds.S                 |   1 -
 arch/c6x/include/asm/Kbuild                        |   3 +
 arch/c6x/include/asm/tables.h                      |  26 +
 arch/c6x/kernel/vmlinux.lds.S                      |   1 -
 arch/cris/include/asm/Kbuild                       |   4 +
 arch/frv/include/asm/Kbuild                        |   4 +
 arch/h8300/include/asm/Kbuild                      |   4 +
 arch/hexagon/include/asm/Kbuild                    |   4 +
 arch/hexagon/kernel/vmlinux.lds.S                  |   1 -
 arch/ia64/include/asm/Kbuild                       |   3 +
 arch/ia64/include/asm/kprobes.h                    |   7 +-
 arch/ia64/kernel/jprobes.S                         |   3 +-
 arch/ia64/kernel/vmlinux.lds.S                     |   1 -
 arch/ia64/lib/flush.S                              |   6 +-
 arch/m32r/include/asm/Kbuild                       |   4 +
 arch/m68k/include/asm/Kbuild                       |   4 +
 arch/metag/include/asm/Kbuild                      |   4 +
 arch/metag/kernel/vmlinux.lds.S                    |   1 -
 arch/microblaze/include/asm/Kbuild                 |   4 +
 arch/microblaze/kernel/vmlinux.lds.S               |   1 -
 arch/mips/include/asm/Kbuild                       |   3 +
 arch/mips/include/asm/jump_label.h                 |   6 +-
 arch/mips/include/asm/kprobes.h                    |   6 +-
 arch/mips/kernel/vmlinux.lds.S                     |   1 -
 arch/mn10300/include/asm/Kbuild                    |   3 +
 arch/mn10300/include/asm/kprobes.h                 |   4 +
 arch/mn10300/kernel/vmlinux.lds.S                  |   1 -
 arch/nios2/include/asm/Kbuild                      |   4 +
 arch/nios2/kernel/vmlinux.lds.S                    |   1 -
 arch/openrisc/include/asm/Kbuild                   |   4 +
 arch/openrisc/kernel/vmlinux.lds.S                 |   1 -
 arch/parisc/include/asm/Kbuild                     |   4 +
 arch/parisc/kernel/vmlinux.lds.S                   |   1 -
 arch/powerpc/include/asm/Kbuild                    |   3 +
 arch/powerpc/include/asm/jump_label.h              |   8 +-
 arch/powerpc/include/asm/kprobes.h                 |   6 +
 arch/powerpc/include/asm/ppc_asm.h                 |   7 +-
 arch/powerpc/kernel/vmlinux.lds.S                  |   1 -
 arch/s390/include/asm/Kbuild                       |   3 +
 arch/s390/include/asm/jump_label.h                 |   6 +-
 arch/s390/include/asm/kprobes.h                    |   4 +
 arch/s390/kernel/entry.S                           |   5 +-
 arch/s390/kernel/kprobes.c                         |   6 +-
 arch/s390/kernel/mcount.S                          |   3 +-
 arch/s390/kernel/vmlinux.lds.S                     |   1 -
 arch/score/include/asm/Kbuild                      |   4 +
 arch/score/kernel/vmlinux.lds.S                    |   1 -
 arch/sh/include/asm/Kbuild                         |   3 +
 arch/sh/include/asm/kprobes.h                      |   2 +
 arch/sh/kernel/vmlinux.lds.S                       |   1 -
 arch/sparc/include/asm/Kbuild                      |   3 +
 arch/sparc/include/asm/jump_label.h                |   6 +-
 arch/sparc/include/asm/kprobes.h                   |   5 +
 arch/sparc/kernel/vmlinux.lds.S                    |   1 -
 arch/sparc/mm/ultra.S                              |   3 +-
 arch/tile/include/asm/Kbuild                       |   3 +
 arch/tile/include/asm/kprobes.h                    |   6 +-
 arch/tile/kernel/vmlinux.lds.S                     |   1 -
 arch/um/include/asm/Kbuild                         |   4 +
 arch/unicore32/include/asm/Kbuild                  |   3 +
 arch/unicore32/include/asm/section-core.h          |  19 +
 arch/x86/include/asm/Kbuild                        |   3 +
 arch/x86/include/asm/jump_label.h                  |  10 +-
 arch/x86/include/asm/kprobes.h                     |   6 +
 arch/x86/kernel/cpu/microcode/core.c               |   8 +-
 arch/x86/kernel/kprobes/core.c                     |  11 +-
 arch/x86/kernel/vmlinux.lds.S                      |   1 -
 arch/x86/tools/relocs.c                            |   4 +
 arch/xtensa/include/asm/Kbuild                     |   4 +
 arch/xtensa/kernel/Makefile                        |   8 +-
 drivers/base/firmware_class.c                      |  12 +-
 drivers/platform/x86/dell-smo8800.c                |   1 +
 firmware/Makefile                                  |   6 +-
 include/asm-generic/kprobes.h                      |  26 +
 include/asm-generic/ranges.h                       | 103 ++++
 include/asm-generic/section-core.h                 | 341 +++++++++++
 include/asm-generic/sections.h                     |   4 +-
 include/asm-generic/tables.h                       |  50 ++
 include/asm-generic/vmlinux.lds.h                  |  73 +--
 include/linux/compiler.h                           |   8 -
 include/linux/dynamic_debug.h                      |   5 +-
 include/linux/init.h                               |  20 +-
 include/linux/jump_label.h                         |   8 +-
 include/linux/kprobes.h                            |  24 +-
 include/linux/ranges.h                             | 128 +++++
 include/linux/sections.h                           | 111 ++++
 include/linux/tables.h                             | 638 +++++++++++++++++++++
 init/Kconfig                                       |  22 +
 kernel/jump_label.c                                |  17 +-
 kernel/kprobes.c                                   |  17 +-
 lib/dynamic_debug.c                                |  13 +-
 scripts/Makefile.build                             |   7 +-
 scripts/Makefile.clean                             |   2 +
 scripts/Makefile.lib                               |  11 +
 scripts/Makefile.modpost                           |   2 +-
 scripts/mod/modpost.c                              |   2 +-
 scripts/{module-common.lds => module-common.lds.S} |   6 +
 scripts/recordmcount.c                             |   2 +-
 scripts/recordmcount.pl                            |   2 +-
 tools/objtool/special.c                            |   2 +-
 133 files changed, 2328 insertions(+), 214 deletions(-)
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/linker-tables.rst
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/c6x/include/asm/tables.h
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/kprobes.h
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/asm-generic/tables.h
 create mode 100644 include/linux/ranges.h
 create mode 100644 include/linux/sections.h
 create mode 100644 include/linux/tables.h
 rename scripts/{module-common.lds => module-common.lds.S} (80%)

-- 
2.9.2


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v4 00/16] linux: generalize sections, ranges and linker tables
@ 2016-08-19 21:33   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:33 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This v4 addresses feedback from the previous v3 series [0], and also
addresses a huge array of additional tests against many architectures
outside of what 0-day provides. As I mentioned in my last v3 series,
0-day had only found one issue with the series, a blackfin architecture
linker issue with the last series. Guenter Rock was kind enough to give
my series a test spin on his test bed and he found quite a bit of other
oddball issues with obscure architectures, and even on x86 with an old
toolchain. After a lot of work and coordinating with a few maintainers
I'm happy to report all issues found so far through all possible testing
I could do are now fixed, this series also addresses all feedback from
the last series, as such this goes submitted as PATCH form.

In addressing fixing this work on a few architectures some of the previous
patches are further simplified. The kprobes port to linker tables is made
much easier now that I've addressed moving out core kprobe declarations
into asm-generic/kprobes.h. Refer to the patch "kprobes: move kprobe
declarations to asm-generic/kprobes.h". This makes for a much cleaner
solution across architectures.

Boris feedback on making the code bit rot feature optional is addressed
by using a new Kconfig symbol for this, CONFIG_BUILD_AVOID_BITROT,
but given Greg's concerns over lack of clarity over what this was all about
I've ripped that functionality out into its own patch with a bit more
extensive documentation and re-wording. See the patch "kbuild: enable option
to force compile force-obj-y and force-lib-y". I hope makes it clear how
linker tables can help with avoiding code bit rot. I've gone with a new
Kconfig symbol CONFIG_BUILD_AVOID_BITROT given CONFIG_COMPILE_TEST is
not available on UML, this feature is desirable on all architectures.

The documentation is revamped, now that the DocBook format is deprecated
I ported the documention into the trendy hipster Sphinx documentation
format.

AT Boris' request I've adapated the userspace linker table application
forintegration into the kernel under tools/ to make it easier to keep
things in sync, however since this requires a bit of changes to some headers
in tools/ I'll submit that separately.

[0] https://lkml.kernel.org/r/1469222687-1600-1-git-send-email-mcgrof@kernel.org

If you'd like this in git-form, you can get it on the 20160819-linker-table-v4
branch of my linux-next tree on kernel.org, this also includes the series of
the linker table userspace sandbox:

https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h=20160819-linker-table-v4

Please let me know if there are any concerns or questions.

Luis R. Rodriguez (16):
  x86: remove LTO_REFERENCE_INITCALL()
  dell-smo8800: include uaccess.h
  scripts/module-common.lds: enable generation
  generic-sections: add section core helpers
  xtensa: skip adding literal when SORT() is used
  ranges.h: add helpers to build and identify Linux section ranges
  tables.h: add linker table support
  kbuild: enable option to force compile force-obj-y and force-lib-y
  firmware/Makefile: force recompilation if makefile changes
  firmware: port built-in section to linker table
  jump_label: move guard #endif down where it belongs
  jump_label: port __jump_table to linker tables
  dynamic_debug: port to use linker tables
  kprobes: move kprobe declarations to asm-generic/kprobes.h
  kprobes: port .kprobes.text to section range
  kprobes: port blacklist kprobes to linker table

 .gitignore                                         |   2 +
 Documentation/index.rst                            |   1 +
 Documentation/kbuild/makefiles.txt                 |  36 ++
 Documentation/sections/conf.py                     |   4 +
 Documentation/sections/index.rst                   |  13 +
 Documentation/sections/linker-tables.rst           | 202 +++++++
 Documentation/sections/ranges.rst                  |  49 ++
 Documentation/sections/section-core.rst            | 153 +++++
 MAINTAINERS                                        |  37 ++
 Makefile                                           |   6 +-
 arch/alpha/include/asm/Kbuild                      |   4 +
 arch/arc/include/asm/Kbuild                        |   3 +
 arch/arc/include/asm/kprobes.h                     |   6 +-
 arch/arc/kernel/vmlinux.lds.S                      |   1 -
 arch/arm/include/asm/Kbuild                        |   3 +
 arch/arm/include/asm/jump_label.h                  |   6 +-
 arch/arm/include/asm/kprobes.h                     |   4 +
 arch/arm/kernel/entry-armv.S                       |   3 +-
 arch/arm/kernel/vmlinux-xip.lds.S                  |   1 -
 arch/arm/kernel/vmlinux.lds.S                      |   1 -
 arch/arm/probes/decode.h                           |   1 +
 arch/arm64/include/asm/Kbuild                      |   3 +
 arch/arm64/include/asm/jump_label.h                |   6 +-
 arch/arm64/include/asm/kprobes.h                   |   4 +
 arch/arm64/kernel/armv8_deprecated.c               |   1 +
 arch/arm64/kernel/insn.c                           |   1 +
 arch/arm64/kernel/probes/kprobes.c                 |   4 +-
 arch/arm64/kernel/vmlinux.lds.S                    |   1 -
 arch/avr32/include/asm/Kbuild                      |   3 +
 arch/avr32/include/asm/kprobes.h                   |   4 +
 arch/avr32/kernel/entry-avr32b.S                   |  13 +-
 arch/avr32/kernel/vmlinux.lds.S                    |   1 -
 arch/blackfin/include/asm/Kbuild                   |   4 +
 arch/blackfin/kernel/vmlinux.lds.S                 |   1 -
 arch/c6x/include/asm/Kbuild                        |   3 +
 arch/c6x/include/asm/tables.h                      |  26 +
 arch/c6x/kernel/vmlinux.lds.S                      |   1 -
 arch/cris/include/asm/Kbuild                       |   4 +
 arch/frv/include/asm/Kbuild                        |   4 +
 arch/h8300/include/asm/Kbuild                      |   4 +
 arch/hexagon/include/asm/Kbuild                    |   4 +
 arch/hexagon/kernel/vmlinux.lds.S                  |   1 -
 arch/ia64/include/asm/Kbuild                       |   3 +
 arch/ia64/include/asm/kprobes.h                    |   7 +-
 arch/ia64/kernel/jprobes.S                         |   3 +-
 arch/ia64/kernel/vmlinux.lds.S                     |   1 -
 arch/ia64/lib/flush.S                              |   6 +-
 arch/m32r/include/asm/Kbuild                       |   4 +
 arch/m68k/include/asm/Kbuild                       |   4 +
 arch/metag/include/asm/Kbuild                      |   4 +
 arch/metag/kernel/vmlinux.lds.S                    |   1 -
 arch/microblaze/include/asm/Kbuild                 |   4 +
 arch/microblaze/kernel/vmlinux.lds.S               |   1 -
 arch/mips/include/asm/Kbuild                       |   3 +
 arch/mips/include/asm/jump_label.h                 |   6 +-
 arch/mips/include/asm/kprobes.h                    |   6 +-
 arch/mips/kernel/vmlinux.lds.S                     |   1 -
 arch/mn10300/include/asm/Kbuild                    |   3 +
 arch/mn10300/include/asm/kprobes.h                 |   4 +
 arch/mn10300/kernel/vmlinux.lds.S                  |   1 -
 arch/nios2/include/asm/Kbuild                      |   4 +
 arch/nios2/kernel/vmlinux.lds.S                    |   1 -
 arch/openrisc/include/asm/Kbuild                   |   4 +
 arch/openrisc/kernel/vmlinux.lds.S                 |   1 -
 arch/parisc/include/asm/Kbuild                     |   4 +
 arch/parisc/kernel/vmlinux.lds.S                   |   1 -
 arch/powerpc/include/asm/Kbuild                    |   3 +
 arch/powerpc/include/asm/jump_label.h              |   8 +-
 arch/powerpc/include/asm/kprobes.h                 |   6 +
 arch/powerpc/include/asm/ppc_asm.h                 |   7 +-
 arch/powerpc/kernel/vmlinux.lds.S                  |   1 -
 arch/s390/include/asm/Kbuild                       |   3 +
 arch/s390/include/asm/jump_label.h                 |   6 +-
 arch/s390/include/asm/kprobes.h                    |   4 +
 arch/s390/kernel/entry.S                           |   5 +-
 arch/s390/kernel/kprobes.c                         |   6 +-
 arch/s390/kernel/mcount.S                          |   3 +-
 arch/s390/kernel/vmlinux.lds.S                     |   1 -
 arch/score/include/asm/Kbuild                      |   4 +
 arch/score/kernel/vmlinux.lds.S                    |   1 -
 arch/sh/include/asm/Kbuild                         |   3 +
 arch/sh/include/asm/kprobes.h                      |   2 +
 arch/sh/kernel/vmlinux.lds.S                       |   1 -
 arch/sparc/include/asm/Kbuild                      |   3 +
 arch/sparc/include/asm/jump_label.h                |   6 +-
 arch/sparc/include/asm/kprobes.h                   |   5 +
 arch/sparc/kernel/vmlinux.lds.S                    |   1 -
 arch/sparc/mm/ultra.S                              |   3 +-
 arch/tile/include/asm/Kbuild                       |   3 +
 arch/tile/include/asm/kprobes.h                    |   6 +-
 arch/tile/kernel/vmlinux.lds.S                     |   1 -
 arch/um/include/asm/Kbuild                         |   4 +
 arch/unicore32/include/asm/Kbuild                  |   3 +
 arch/unicore32/include/asm/section-core.h          |  19 +
 arch/x86/include/asm/Kbuild                        |   3 +
 arch/x86/include/asm/jump_label.h                  |  10 +-
 arch/x86/include/asm/kprobes.h                     |   6 +
 arch/x86/kernel/cpu/microcode/core.c               |   8 +-
 arch/x86/kernel/kprobes/core.c                     |  11 +-
 arch/x86/kernel/vmlinux.lds.S                      |   1 -
 arch/x86/tools/relocs.c                            |   4 +
 arch/xtensa/include/asm/Kbuild                     |   4 +
 arch/xtensa/kernel/Makefile                        |   8 +-
 drivers/base/firmware_class.c                      |  12 +-
 drivers/platform/x86/dell-smo8800.c                |   1 +
 firmware/Makefile                                  |   6 +-
 include/asm-generic/kprobes.h                      |  26 +
 include/asm-generic/ranges.h                       | 103 ++++
 include/asm-generic/section-core.h                 | 341 +++++++++++
 include/asm-generic/sections.h                     |   4 +-
 include/asm-generic/tables.h                       |  50 ++
 include/asm-generic/vmlinux.lds.h                  |  73 +--
 include/linux/compiler.h                           |   8 -
 include/linux/dynamic_debug.h                      |   5 +-
 include/linux/init.h                               |  20 +-
 include/linux/jump_label.h                         |   8 +-
 include/linux/kprobes.h                            |  24 +-
 include/linux/ranges.h                             | 128 +++++
 include/linux/sections.h                           | 111 ++++
 include/linux/tables.h                             | 638 +++++++++++++++++++++
 init/Kconfig                                       |  22 +
 kernel/jump_label.c                                |  17 +-
 kernel/kprobes.c                                   |  17 +-
 lib/dynamic_debug.c                                |  13 +-
 scripts/Makefile.build                             |   7 +-
 scripts/Makefile.clean                             |   2 +
 scripts/Makefile.lib                               |  11 +
 scripts/Makefile.modpost                           |   2 +-
 scripts/mod/modpost.c                              |   2 +-
 scripts/{module-common.lds => module-common.lds.S} |   6 +
 scripts/recordmcount.c                             |   2 +-
 scripts/recordmcount.pl                            |   2 +-
 tools/objtool/special.c                            |   2 +-
 133 files changed, 2328 insertions(+), 214 deletions(-)
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/linker-tables.rst
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/c6x/include/asm/tables.h
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/kprobes.h
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/asm-generic/tables.h
 create mode 100644 include/linux/ranges.h
 create mode 100644 include/linux/sections.h
 create mode 100644 include/linux/tables.h
 rename scripts/{module-common.lds => module-common.lds.S} (80%)

-- 
2.9.2


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v4 00/16] linux: generalize sections, ranges and linker tables
@ 2016-08-19 21:33   ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:33 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This v4 addresses feedback from the previous v3 series [0], and also
addresses a huge array of additional tests against many architectures
outside of what 0-day provides. As I mentioned in my last v3 series,
0-day had only found one issue with the series, a blackfin architecture
linker issue with the last series. Guenter Rock was kind enough to give
my series a test spin on his test bed and he found quite a bit of other
oddball issues with obscure architectures, and even on x86 with an old
toolchain. After a lot of work and coordinating with a few maintainers
I'm happy to report all issues found so far through all possible testing
I could do are now fixed, this series also addresses all feedback from
the last series, as such this goes submitted as PATCH form.

In addressing fixing this work on a few architectures some of the previous
patches are further simplified. The kprobes port to linker tables is made
much easier now that I've addressed moving out core kprobe declarations
into asm-generic/kprobes.h. Refer to the patch "kprobes: move kprobe
declarations to asm-generic/kprobes.h". This makes for a much cleaner
solution across architectures.

Boris feedback on making the code bit rot feature optional is addressed
by using a new Kconfig symbol for this, CONFIG_BUILD_AVOID_BITROT,
but given Greg's concerns over lack of clarity over what this was all about
I've ripped that functionality out into its own patch with a bit more
extensive documentation and re-wording. See the patch "kbuild: enable option
to force compile force-obj-y and force-lib-y". I hope makes it clear how
linker tables can help with avoiding code bit rot. I've gone with a new
Kconfig symbol CONFIG_BUILD_AVOID_BITROT given CONFIG_COMPILE_TEST is
not available on UML, this feature is desirable on all architectures.

The documentation is revamped, now that the DocBook format is deprecated
I ported the documention into the trendy hipster Sphinx documentation
format.

AT Boris' request I've adapated the userspace linker table application
forintegration into the kernel under tools/ to make it easier to keep
things in sync, however since this requires a bit of changes to some headers
in tools/ I'll submit that separately.

[0] https://lkml.kernel.org/r/1469222687-1600-1-git-send-email-mcgrof@kernel.org

If you'd like this in git-form, you can get it on the 20160819-linker-table-v4
branch of my linux-next tree on kernel.org, this also includes the series of
the linker table userspace sandbox:

https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h=20160819-linker-table-v4

Please let me know if there are any concerns or questions.

Luis R. Rodriguez (16):
  x86: remove LTO_REFERENCE_INITCALL()
  dell-smo8800: include uaccess.h
  scripts/module-common.lds: enable generation
  generic-sections: add section core helpers
  xtensa: skip adding literal when SORT() is used
  ranges.h: add helpers to build and identify Linux section ranges
  tables.h: add linker table support
  kbuild: enable option to force compile force-obj-y and force-lib-y
  firmware/Makefile: force recompilation if makefile changes
  firmware: port built-in section to linker table
  jump_label: move guard #endif down where it belongs
  jump_label: port __jump_table to linker tables
  dynamic_debug: port to use linker tables
  kprobes: move kprobe declarations to asm-generic/kprobes.h
  kprobes: port .kprobes.text to section range
  kprobes: port blacklist kprobes to linker table

 .gitignore                                         |   2 +
 Documentation/index.rst                            |   1 +
 Documentation/kbuild/makefiles.txt                 |  36 ++
 Documentation/sections/conf.py                     |   4 +
 Documentation/sections/index.rst                   |  13 +
 Documentation/sections/linker-tables.rst           | 202 +++++++
 Documentation/sections/ranges.rst                  |  49 ++
 Documentation/sections/section-core.rst            | 153 +++++
 MAINTAINERS                                        |  37 ++
 Makefile                                           |   6 +-
 arch/alpha/include/asm/Kbuild                      |   4 +
 arch/arc/include/asm/Kbuild                        |   3 +
 arch/arc/include/asm/kprobes.h                     |   6 +-
 arch/arc/kernel/vmlinux.lds.S                      |   1 -
 arch/arm/include/asm/Kbuild                        |   3 +
 arch/arm/include/asm/jump_label.h                  |   6 +-
 arch/arm/include/asm/kprobes.h                     |   4 +
 arch/arm/kernel/entry-armv.S                       |   3 +-
 arch/arm/kernel/vmlinux-xip.lds.S                  |   1 -
 arch/arm/kernel/vmlinux.lds.S                      |   1 -
 arch/arm/probes/decode.h                           |   1 +
 arch/arm64/include/asm/Kbuild                      |   3 +
 arch/arm64/include/asm/jump_label.h                |   6 +-
 arch/arm64/include/asm/kprobes.h                   |   4 +
 arch/arm64/kernel/armv8_deprecated.c               |   1 +
 arch/arm64/kernel/insn.c                           |   1 +
 arch/arm64/kernel/probes/kprobes.c                 |   4 +-
 arch/arm64/kernel/vmlinux.lds.S                    |   1 -
 arch/avr32/include/asm/Kbuild                      |   3 +
 arch/avr32/include/asm/kprobes.h                   |   4 +
 arch/avr32/kernel/entry-avr32b.S                   |  13 +-
 arch/avr32/kernel/vmlinux.lds.S                    |   1 -
 arch/blackfin/include/asm/Kbuild                   |   4 +
 arch/blackfin/kernel/vmlinux.lds.S                 |   1 -
 arch/c6x/include/asm/Kbuild                        |   3 +
 arch/c6x/include/asm/tables.h                      |  26 +
 arch/c6x/kernel/vmlinux.lds.S                      |   1 -
 arch/cris/include/asm/Kbuild                       |   4 +
 arch/frv/include/asm/Kbuild                        |   4 +
 arch/h8300/include/asm/Kbuild                      |   4 +
 arch/hexagon/include/asm/Kbuild                    |   4 +
 arch/hexagon/kernel/vmlinux.lds.S                  |   1 -
 arch/ia64/include/asm/Kbuild                       |   3 +
 arch/ia64/include/asm/kprobes.h                    |   7 +-
 arch/ia64/kernel/jprobes.S                         |   3 +-
 arch/ia64/kernel/vmlinux.lds.S                     |   1 -
 arch/ia64/lib/flush.S                              |   6 +-
 arch/m32r/include/asm/Kbuild                       |   4 +
 arch/m68k/include/asm/Kbuild                       |   4 +
 arch/metag/include/asm/Kbuild                      |   4 +
 arch/metag/kernel/vmlinux.lds.S                    |   1 -
 arch/microblaze/include/asm/Kbuild                 |   4 +
 arch/microblaze/kernel/vmlinux.lds.S               |   1 -
 arch/mips/include/asm/Kbuild                       |   3 +
 arch/mips/include/asm/jump_label.h                 |   6 +-
 arch/mips/include/asm/kprobes.h                    |   6 +-
 arch/mips/kernel/vmlinux.lds.S                     |   1 -
 arch/mn10300/include/asm/Kbuild                    |   3 +
 arch/mn10300/include/asm/kprobes.h                 |   4 +
 arch/mn10300/kernel/vmlinux.lds.S                  |   1 -
 arch/nios2/include/asm/Kbuild                      |   4 +
 arch/nios2/kernel/vmlinux.lds.S                    |   1 -
 arch/openrisc/include/asm/Kbuild                   |   4 +
 arch/openrisc/kernel/vmlinux.lds.S                 |   1 -
 arch/parisc/include/asm/Kbuild                     |   4 +
 arch/parisc/kernel/vmlinux.lds.S                   |   1 -
 arch/powerpc/include/asm/Kbuild                    |   3 +
 arch/powerpc/include/asm/jump_label.h              |   8 +-
 arch/powerpc/include/asm/kprobes.h                 |   6 +
 arch/powerpc/include/asm/ppc_asm.h                 |   7 +-
 arch/powerpc/kernel/vmlinux.lds.S                  |   1 -
 arch/s390/include/asm/Kbuild                       |   3 +
 arch/s390/include/asm/jump_label.h                 |   6 +-
 arch/s390/include/asm/kprobes.h                    |   4 +
 arch/s390/kernel/entry.S                           |   5 +-
 arch/s390/kernel/kprobes.c                         |   6 +-
 arch/s390/kernel/mcount.S                          |   3 +-
 arch/s390/kernel/vmlinux.lds.S                     |   1 -
 arch/score/include/asm/Kbuild                      |   4 +
 arch/score/kernel/vmlinux.lds.S                    |   1 -
 arch/sh/include/asm/Kbuild                         |   3 +
 arch/sh/include/asm/kprobes.h                      |   2 +
 arch/sh/kernel/vmlinux.lds.S                       |   1 -
 arch/sparc/include/asm/Kbuild                      |   3 +
 arch/sparc/include/asm/jump_label.h                |   6 +-
 arch/sparc/include/asm/kprobes.h                   |   5 +
 arch/sparc/kernel/vmlinux.lds.S                    |   1 -
 arch/sparc/mm/ultra.S                              |   3 +-
 arch/tile/include/asm/Kbuild                       |   3 +
 arch/tile/include/asm/kprobes.h                    |   6 +-
 arch/tile/kernel/vmlinux.lds.S                     |   1 -
 arch/um/include/asm/Kbuild                         |   4 +
 arch/unicore32/include/asm/Kbuild                  |   3 +
 arch/unicore32/include/asm/section-core.h          |  19 +
 arch/x86/include/asm/Kbuild                        |   3 +
 arch/x86/include/asm/jump_label.h                  |  10 +-
 arch/x86/include/asm/kprobes.h                     |   6 +
 arch/x86/kernel/cpu/microcode/core.c               |   8 +-
 arch/x86/kernel/kprobes/core.c                     |  11 +-
 arch/x86/kernel/vmlinux.lds.S                      |   1 -
 arch/x86/tools/relocs.c                            |   4 +
 arch/xtensa/include/asm/Kbuild                     |   4 +
 arch/xtensa/kernel/Makefile                        |   8 +-
 drivers/base/firmware_class.c                      |  12 +-
 drivers/platform/x86/dell-smo8800.c                |   1 +
 firmware/Makefile                                  |   6 +-
 include/asm-generic/kprobes.h                      |  26 +
 include/asm-generic/ranges.h                       | 103 ++++
 include/asm-generic/section-core.h                 | 341 +++++++++++
 include/asm-generic/sections.h                     |   4 +-
 include/asm-generic/tables.h                       |  50 ++
 include/asm-generic/vmlinux.lds.h                  |  73 +--
 include/linux/compiler.h                           |   8 -
 include/linux/dynamic_debug.h                      |   5 +-
 include/linux/init.h                               |  20 +-
 include/linux/jump_label.h                         |   8 +-
 include/linux/kprobes.h                            |  24 +-
 include/linux/ranges.h                             | 128 +++++
 include/linux/sections.h                           | 111 ++++
 include/linux/tables.h                             | 638 +++++++++++++++++++++
 init/Kconfig                                       |  22 +
 kernel/jump_label.c                                |  17 +-
 kernel/kprobes.c                                   |  17 +-
 lib/dynamic_debug.c                                |  13 +-
 scripts/Makefile.build                             |   7 +-
 scripts/Makefile.clean                             |   2 +
 scripts/Makefile.lib                               |  11 +
 scripts/Makefile.modpost                           |   2 +-
 scripts/mod/modpost.c                              |   2 +-
 scripts/{module-common.lds => module-common.lds.S} |   6 +
 scripts/recordmcount.c                             |   2 +-
 scripts/recordmcount.pl                            |   2 +-
 tools/objtool/special.c                            |   2 +-
 133 files changed, 2328 insertions(+), 214 deletions(-)
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/linker-tables.rst
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/c6x/include/asm/tables.h
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/kprobes.h
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/asm-generic/tables.h
 create mode 100644 include/linux/ranges.h
 create mode 100644 include/linux/sections.h
 create mode 100644 include/linux/tables.h
 rename scripts/{module-common.lds => module-common.lds.S} (80%)

-- 
2.9.2


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v4 01/16] x86: remove LTO_REFERENCE_INITCALL()
  2016-08-19 21:33   ` mcgrof
  (?)
@ 2016-08-19 21:33     ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:33 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

The setup for LTO never made it upstream, and although this has
some users, this is now really old stuff for a gcc 4.7 LTO problem.
We know that at least LTO_REFERENCE_INITCALL() work around can
be removed if LTO is not supported on v4.7 anymore.

As per Andi the DISABLE_LTO and LTO_CFLAGS are still neeeded though.

v3: added to this series, removing LTO_REFERENCE_INITCALL()
    justifies that other future similar macros do not need
    a respective LTO_REFERENCE_INITCALL() on them therefore
    simplifying new code.

Acked-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/linux/init.h | 20 +-------------------
 1 file changed, 1 insertion(+), 19 deletions(-)

diff --git a/include/linux/init.h b/include/linux/init.h
index 1e5c131d5c9a..aa662ad80d9c 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -151,23 +151,6 @@ extern bool initcall_debug;
 
 #ifndef __ASSEMBLY__
 
-#ifdef CONFIG_LTO
-/* Work around a LTO gcc problem: when there is no reference to a variable
- * in a module it will be moved to the end of the program. This causes
- * reordering of initcalls which the kernel does not like.
- * Add a dummy reference function to avoid this. The function is
- * deleted by the linker.
- */
-#define LTO_REFERENCE_INITCALL(x) \
-	; /* yes this is needed */			\
-	static __used __exit void *reference_##x(void)	\
-	{						\
-		return &x;				\
-	}
-#else
-#define LTO_REFERENCE_INITCALL(x)
-#endif
-
 /* initcalls are now grouped by functionality into separate 
  * subsections. Ordering inside the subsections is determined
  * by link order. 
@@ -180,8 +163,7 @@ extern bool initcall_debug;
 
 #define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
-	__attribute__((__section__(".initcall" #id ".init"))) = fn; \
-	LTO_REFERENCE_INITCALL(__initcall_##fn##id)
+	__attribute__((__section__(".initcall" #id ".init"))) = fn;
 
 /*
  * Early initcalls run before initializing SMP.
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 01/16] x86: remove LTO_REFERENCE_INITCALL()
@ 2016-08-19 21:33     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:33 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

The setup for LTO never made it upstream, and although this has
some users, this is now really old stuff for a gcc 4.7 LTO problem.
We know that at least LTO_REFERENCE_INITCALL() work around can
be removed if LTO is not supported on v4.7 anymore.

As per Andi the DISABLE_LTO and LTO_CFLAGS are still neeeded though.

v3: added to this series, removing LTO_REFERENCE_INITCALL()
    justifies that other future similar macros do not need
    a respective LTO_REFERENCE_INITCALL() on them therefore
    simplifying new code.

Acked-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/linux/init.h | 20 +-------------------
 1 file changed, 1 insertion(+), 19 deletions(-)

diff --git a/include/linux/init.h b/include/linux/init.h
index 1e5c131d5c9a..aa662ad80d9c 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -151,23 +151,6 @@ extern bool initcall_debug;
 
 #ifndef __ASSEMBLY__
 
-#ifdef CONFIG_LTO
-/* Work around a LTO gcc problem: when there is no reference to a variable
- * in a module it will be moved to the end of the program. This causes
- * reordering of initcalls which the kernel does not like.
- * Add a dummy reference function to avoid this. The function is
- * deleted by the linker.
- */
-#define LTO_REFERENCE_INITCALL(x) \
-	; /* yes this is needed */			\
-	static __used __exit void *reference_##x(void)	\
-	{						\
-		return &x;				\
-	}
-#else
-#define LTO_REFERENCE_INITCALL(x)
-#endif
-
 /* initcalls are now grouped by functionality into separate 
  * subsections. Ordering inside the subsections is determined
  * by link order. 
@@ -180,8 +163,7 @@ extern bool initcall_debug;
 
 #define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
-	__attribute__((__section__(".initcall" #id ".init"))) = fn; \
-	LTO_REFERENCE_INITCALL(__initcall_##fn##id)
+	__attribute__((__section__(".initcall" #id ".init"))) = fn;
 
 /*
  * Early initcalls run before initializing SMP.
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 01/16] x86: remove LTO_REFERENCE_INITCALL()
@ 2016-08-19 21:33     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:33 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

The setup for LTO never made it upstream, and although this has
some users, this is now really old stuff for a gcc 4.7 LTO problem.
We know that at least LTO_REFERENCE_INITCALL() work around can
be removed if LTO is not supported on v4.7 anymore.

As per Andi the DISABLE_LTO and LTO_CFLAGS are still neeeded though.

v3: added to this series, removing LTO_REFERENCE_INITCALL()
    justifies that other future similar macros do not need
    a respective LTO_REFERENCE_INITCALL() on them therefore
    simplifying new code.

Acked-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/linux/init.h | 20 +-------------------
 1 file changed, 1 insertion(+), 19 deletions(-)

diff --git a/include/linux/init.h b/include/linux/init.h
index 1e5c131d5c9a..aa662ad80d9c 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -151,23 +151,6 @@ extern bool initcall_debug;
 
 #ifndef __ASSEMBLY__
 
-#ifdef CONFIG_LTO
-/* Work around a LTO gcc problem: when there is no reference to a variable
- * in a module it will be moved to the end of the program. This causes
- * reordering of initcalls which the kernel does not like.
- * Add a dummy reference function to avoid this. The function is
- * deleted by the linker.
- */
-#define LTO_REFERENCE_INITCALL(x) \
-	; /* yes this is needed */			\
-	static __used __exit void *reference_##x(void)	\
-	{						\
-		return &x;				\
-	}
-#else
-#define LTO_REFERENCE_INITCALL(x)
-#endif
-
 /* initcalls are now grouped by functionality into separate 
  * subsections. Ordering inside the subsections is determined
  * by link order. 
@@ -180,8 +163,7 @@ extern bool initcall_debug;
 
 #define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
-	__attribute__((__section__(".initcall" #id ".init"))) = fn; \
-	LTO_REFERENCE_INITCALL(__initcall_##fn##id)
+	__attribute__((__section__(".initcall" #id ".init"))) = fn;
 
 /*
  * Early initcalls run before initializing SMP.
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 02/16] dell-smo8800: include uaccess.h
  2016-08-19 21:33   ` mcgrof
  (?)
  (?)
@ 2016-08-19 21:34     ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

sections.h is currently included and it provides dell-smo8800
with what it needs, an upcoming change will decouple uaccess.h
from sections.h. This driver needs to explicitly require uaccess.h
before this change.

v3: new to this series -- needed due to collateral of the split of
    old linker tables from tables.h into 3 files: sections.h, ranges.h
    and tables.h

Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 drivers/platform/x86/dell-smo8800.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/platform/x86/dell-smo8800.c b/drivers/platform/x86/dell-smo8800.c
index 0aec4fd4c48e..37e646034ef8 100644
--- a/drivers/platform/x86/dell-smo8800.c
+++ b/drivers/platform/x86/dell-smo8800.c
@@ -24,6 +24,7 @@
 #include <linux/acpi.h>
 #include <linux/interrupt.h>
 #include <linux/miscdevice.h>
+#include <linux/uaccess.h>
 
 struct smo8800_device {
 	u32 irq;                     /* acpi device irq */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 02/16] dell-smo8800: include uaccess.h
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

sections.h is currently included and it provides dell-smo8800
with what it needs, an upcoming change will decouple uaccess.h
from sections.h. This driver needs to explicitly require uaccess.h
before this change.

v3: new to this series -- needed due to collateral of the split of
    old linker tables from tables.h into 3 files: sections.h, ranges.h
    and tables.h

Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 drivers/platform/x86/dell-smo8800.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/platform/x86/dell-smo8800.c b/drivers/platform/x86/dell-smo8800.c
index 0aec4fd4c48e..37e646034ef8 100644
--- a/drivers/platform/x86/dell-smo8800.c
+++ b/drivers/platform/x86/dell-smo8800.c
@@ -24,6 +24,7 @@
 #include <linux/acpi.h>
 #include <linux/interrupt.h>
 #include <linux/miscdevice.h>
+#include <linux/uaccess.h>
 
 struct smo8800_device {
 	u32 irq;                     /* acpi device irq */
-- 
2.9.2


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 02/16] dell-smo8800: include uaccess.h
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

sections.h is currently included and it provides dell-smo8800
with what it needs, an upcoming change will decouple uaccess.h
from sections.h. This driver needs to explicitly require uaccess.h
before this change.

v3: new to this series -- needed due to collateral of the split of
    old linker tables from tables.h into 3 files: sections.h, ranges.h
    and tables.h

Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 drivers/platform/x86/dell-smo8800.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/platform/x86/dell-smo8800.c b/drivers/platform/x86/dell-smo8800.c
index 0aec4fd4c48e..37e646034ef8 100644
--- a/drivers/platform/x86/dell-smo8800.c
+++ b/drivers/platform/x86/dell-smo8800.c
@@ -24,6 +24,7 @@
 #include <linux/acpi.h>
 #include <linux/interrupt.h>
 #include <linux/miscdevice.h>
+#include <linux/uaccess.h>
 
 struct smo8800_device {
 	u32 irq;                     /* acpi device irq */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 02/16] dell-smo8800: include uaccess.h
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

sections.h is currently included and it provides dell-smo8800
with what it needs, an upcoming change will decouple uaccess.h
from sections.h. This driver needs to explicitly require uaccess.h
before this change.

v3: new to this series -- needed due to collateral of the split of
    old linker tables from tables.h into 3 files: sections.h, ranges.h
    and tables.h

Reviewed-by: Pali Roh√°r <pali.rohar@gmail.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 drivers/platform/x86/dell-smo8800.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/platform/x86/dell-smo8800.c b/drivers/platform/x86/dell-smo8800.c
index 0aec4fd4c48e..37e646034ef8 100644
--- a/drivers/platform/x86/dell-smo8800.c
+++ b/drivers/platform/x86/dell-smo8800.c
@@ -24,6 +24,7 @@
 #include <linux/acpi.h>
 #include <linux/interrupt.h>
 #include <linux/miscdevice.h>
+#include <linux/uaccess.h>
 
 struct smo8800_device {
 	u32 irq;                     /* acpi device irq */
-- 
2.9.2

--
To unsubscribe from this list: send the line "unsubscribe linux-ia64" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 03/16] scripts/module-common.lds: enable generation
  2016-08-19 21:33   ` mcgrof
  (?)
@ 2016-08-19 21:34     ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

scripts/module-common.lds is currently pretty static, in the
future this may change and we will want access to kernel macros
to help expands certain areas. To get access to use macros we
need to generate module-common.lds from module-common.lds.S, for
now though only enable the generation. We'll later expand on this
as needed.

Since this file is now generated add it to .gitignore.

v4: add file to MAINTAINERS
v3: new to this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 .gitignore                                         | 2 ++
 MAINTAINERS                                        | 1 +
 Makefile                                           | 6 +++++-
 scripts/Makefile.modpost                           | 2 +-
 scripts/{module-common.lds => module-common.lds.S} | 0
 5 files changed, 9 insertions(+), 2 deletions(-)
 rename scripts/{module-common.lds => module-common.lds.S} (100%)

diff --git a/.gitignore b/.gitignore
index c2ed4ecb0acd..0f0702054fdb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -114,3 +114,5 @@ all.config
 
 # Kdevelop4
 *.kdev4
+
+scripts/module-common.lds
diff --git a/MAINTAINERS b/MAINTAINERS
index d635ab047f3a..5aec01883020 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7887,6 +7887,7 @@ M:	Rusty Russell <rusty@rustcorp.com.au>
 S:	Maintained
 F:	include/linux/module.h
 F:	kernel/module.c
+F:	scripts/module-common.lds.S
 
 MOTION EYE VAIO PICTUREBOOK CAMERA DRIVER
 W:	http://popies.net/meye/
diff --git a/Makefile b/Makefile
index 5c18baad7218..b3e5ea78d582 100644
--- a/Makefile
+++ b/Makefile
@@ -408,6 +408,10 @@ KBUILD_AFLAGS_MODULE  := -DMODULE
 KBUILD_CFLAGS_MODULE  := -DMODULE
 KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
 
+$(srctree)/scripts/module-common.lds: $(srctree)/scripts/module-common.lds.S
+	$(Q)$(CC) $(CFLAGS) $(INCLUDES) $(LINUXINCLUDE) -E -P \
+		-D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
+
 # Read KERNELRELEASE from include/config/kernel.release (if it exists)
 KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
 KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
@@ -1174,7 +1178,7 @@ all: modules
 # using awk while concatenating to the final file.
 
 PHONY += modules
-modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin
+modules: $(srctree)/scripts/module-common.lds $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin
 	$(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order
 	@$(kecho) '  Building modules, stage 2.';
 	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 1366a94b6c39..2d8aff7735d6 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -121,7 +121,7 @@ quiet_cmd_ld_ko_o = LD [M]  $@
                              $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
                              -o $@ $(filter-out FORCE,$^)
 
-$(modules): %.ko :%.o %.mod.o FORCE
+$(modules): %.ko : $(srctree)/scripts/module-common.lds %.o %.mod.o FORCE
 	$(call if_changed,ld_ko_o)
 
 targets += $(modules)
diff --git a/scripts/module-common.lds b/scripts/module-common.lds.S
similarity index 100%
rename from scripts/module-common.lds
rename to scripts/module-common.lds.S
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 03/16] scripts/module-common.lds: enable generation
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

scripts/module-common.lds is currently pretty static, in the
future this may change and we will want access to kernel macros
to help expands certain areas. To get access to use macros we
need to generate module-common.lds from module-common.lds.S, for
now though only enable the generation. We'll later expand on this
as needed.

Since this file is now generated add it to .gitignore.

v4: add file to MAINTAINERS
v3: new to this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 .gitignore                                         | 2 ++
 MAINTAINERS                                        | 1 +
 Makefile                                           | 6 +++++-
 scripts/Makefile.modpost                           | 2 +-
 scripts/{module-common.lds => module-common.lds.S} | 0
 5 files changed, 9 insertions(+), 2 deletions(-)
 rename scripts/{module-common.lds => module-common.lds.S} (100%)

diff --git a/.gitignore b/.gitignore
index c2ed4ecb0acd..0f0702054fdb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -114,3 +114,5 @@ all.config
 
 # Kdevelop4
 *.kdev4
+
+scripts/module-common.lds
diff --git a/MAINTAINERS b/MAINTAINERS
index d635ab047f3a..5aec01883020 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7887,6 +7887,7 @@ M:	Rusty Russell <rusty@rustcorp.com.au>
 S:	Maintained
 F:	include/linux/module.h
 F:	kernel/module.c
+F:	scripts/module-common.lds.S
 
 MOTION EYE VAIO PICTUREBOOK CAMERA DRIVER
 W:	http://popies.net/meye/
diff --git a/Makefile b/Makefile
index 5c18baad7218..b3e5ea78d582 100644
--- a/Makefile
+++ b/Makefile
@@ -408,6 +408,10 @@ KBUILD_AFLAGS_MODULE  := -DMODULE
 KBUILD_CFLAGS_MODULE  := -DMODULE
 KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
 
+$(srctree)/scripts/module-common.lds: $(srctree)/scripts/module-common.lds.S
+	$(Q)$(CC) $(CFLAGS) $(INCLUDES) $(LINUXINCLUDE) -E -P \
+		-D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
+
 # Read KERNELRELEASE from include/config/kernel.release (if it exists)
 KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
 KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
@@ -1174,7 +1178,7 @@ all: modules
 # using awk while concatenating to the final file.
 
 PHONY += modules
-modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin
+modules: $(srctree)/scripts/module-common.lds $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin
 	$(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order
 	@$(kecho) '  Building modules, stage 2.';
 	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 1366a94b6c39..2d8aff7735d6 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -121,7 +121,7 @@ quiet_cmd_ld_ko_o = LD [M]  $@
                              $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
                              -o $@ $(filter-out FORCE,$^)
 
-$(modules): %.ko :%.o %.mod.o FORCE
+$(modules): %.ko : $(srctree)/scripts/module-common.lds %.o %.mod.o FORCE
 	$(call if_changed,ld_ko_o)
 
 targets += $(modules)
diff --git a/scripts/module-common.lds b/scripts/module-common.lds.S
similarity index 100%
rename from scripts/module-common.lds
rename to scripts/module-common.lds.S
-- 
2.9.2


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 03/16] scripts/module-common.lds: enable generation
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

scripts/module-common.lds is currently pretty static, in the
future this may change and we will want access to kernel macros
to help expands certain areas. To get access to use macros we
need to generate module-common.lds from module-common.lds.S, for
now though only enable the generation. We'll later expand on this
as needed.

Since this file is now generated add it to .gitignore.

v4: add file to MAINTAINERS
v3: new to this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 .gitignore                                         | 2 ++
 MAINTAINERS                                        | 1 +
 Makefile                                           | 6 +++++-
 scripts/Makefile.modpost                           | 2 +-
 scripts/{module-common.lds => module-common.lds.S} | 0
 5 files changed, 9 insertions(+), 2 deletions(-)
 rename scripts/{module-common.lds => module-common.lds.S} (100%)

diff --git a/.gitignore b/.gitignore
index c2ed4ecb0acd..0f0702054fdb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -114,3 +114,5 @@ all.config
 
 # Kdevelop4
 *.kdev4
+
+scripts/module-common.lds
diff --git a/MAINTAINERS b/MAINTAINERS
index d635ab047f3a..5aec01883020 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7887,6 +7887,7 @@ M:	Rusty Russell <rusty@rustcorp.com.au>
 S:	Maintained
 F:	include/linux/module.h
 F:	kernel/module.c
+F:	scripts/module-common.lds.S
 
 MOTION EYE VAIO PICTUREBOOK CAMERA DRIVER
 W:	http://popies.net/meye/
diff --git a/Makefile b/Makefile
index 5c18baad7218..b3e5ea78d582 100644
--- a/Makefile
+++ b/Makefile
@@ -408,6 +408,10 @@ KBUILD_AFLAGS_MODULE  := -DMODULE
 KBUILD_CFLAGS_MODULE  := -DMODULE
 KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds
 
+$(srctree)/scripts/module-common.lds: $(srctree)/scripts/module-common.lds.S
+	$(Q)$(CC) $(CFLAGS) $(INCLUDES) $(LINUXINCLUDE) -E -P \
+		-D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
+
 # Read KERNELRELEASE from include/config/kernel.release (if it exists)
 KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
 KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
@@ -1174,7 +1178,7 @@ all: modules
 # using awk while concatenating to the final file.
 
 PHONY += modules
-modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin
+modules: $(srctree)/scripts/module-common.lds $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin
 	$(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order
 	@$(kecho) '  Building modules, stage 2.';
 	$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 1366a94b6c39..2d8aff7735d6 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -121,7 +121,7 @@ quiet_cmd_ld_ko_o = LD [M]  $@
                              $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
                              -o $@ $(filter-out FORCE,$^)
 
-$(modules): %.ko :%.o %.mod.o FORCE
+$(modules): %.ko : $(srctree)/scripts/module-common.lds %.o %.mod.o FORCE
 	$(call if_changed,ld_ko_o)
 
 targets += $(modules)
diff --git a/scripts/module-common.lds b/scripts/module-common.lds.S
similarity index 100%
rename from scripts/module-common.lds
rename to scripts/module-common.lds.S
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 04/16] generic-sections: add section core helpers
  2016-08-19 21:33   ` mcgrof
  (?)
@ 2016-08-19 21:34     ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Linux makes extensive use of custom ELF header sections,
documentation for these are well scatterred. Unify this
documentation in a central place and provide helpers to
build custom Linux sections.

This also generalizes sections code to enable avoiding
modifying the linker scripts when we want to add new
custom Linux sections. In order to make this generally
useful we need to ensure all architectures can make use of
core section helpers but that they can also override should
this be needed. Instead of relying on section.h this adds
a sections-core.h since this will be targetted to be safe
to be used on asm code, linker scripts and C code.

v4:

o Port to shiny new sphinx documentation format

o fix a unicore32 build, turns out this actually fixes unicore32
  defconfig builds which were failing for a long while. unicore32
  does not seem to grok well the type passed on a section declaration,
  this ignores it.

o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
  this was causing final linker issues with blackfin -- this is
  a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
  being metatag. metatag is not supported on 0-day so I cannot confirm
  compilation there.

o Added SECTION_CORE() for C code, used later by __LINUX_RANGE()

o Since SECTION_CORE() is defined for linker script and C code, share
  the same helper and just use a __stringify() for the C code as is done
  for the other C helpers.

o move generic sections to asm-generic/section-core.h instead.
  PowerPC compilation blows up if asm/jump_labels.h gets
  section.h included, fixing this is not in any way easy.
  The list of issues are endless. Moving new data to a new
  simple file resolves this.

o since things are now in asm-generic/section-core.h the
  guard changes on asm-generic/sections.h and each architecture
  sections.h are no longer needed

o Give generic sections some maintainer love, that change is
  Acked-by Arnd Bergmann, Josh and hpa.

o A few checkpatch.pl style fixes

o As suggested by James Hogan use generic-y to copy generic
  header files on architectures that do not have a sections.h
  instead of writing a simple file only to include the generic one.

v3:

o add missing sections.h for architectures that did not
  have it

o move generic sections to asm-generic/sections.h

o add generic asm helpers section_type(), section_type_asmtype(),
  push_section_type() -- these helpers enable easy use for
  for later declaring and using of custom linux sections using
  more standard APIs in both C code, asm code (C asm calls, or
  asm files), enabling future standardized section types to
  be more immediately accessible to asm code, not just C code.
  Note for ASM_CMD_SEP we use by default "\n", architectures needed
  to override can do so on their own sections.h prior to inclusion
  of asm-generic/sections.h

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/index.rst                   |   1 +
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  11 +
 Documentation/sections/section-core.rst   | 153 ++++++++++++++
 MAINTAINERS                               |  14 ++
 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/Kbuild               |   1 +
 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/section-core.h |  19 ++
 arch/x86/include/asm/Kbuild               |   1 +
 arch/xtensa/include/asm/Kbuild            |   1 +
 include/asm-generic/section-core.h        | 341 ++++++++++++++++++++++++++++++
 include/asm-generic/sections.h            |   2 +
 include/asm-generic/vmlinux.lds.h         |  27 +--
 include/linux/sections.h                  | 111 ++++++++++
 40 files changed, 700 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/linux/sections.h

diff --git a/Documentation/index.rst b/Documentation/index.rst
index a15f81855b39..10c9b867e326 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -14,6 +14,7 @@ Contents:
    kernel-documentation
    media/index
    gpu/index
+   sections/index
 
 Indices and tables
 =========
diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
new file mode 100644
index 000000000000..faa1c57595e1
--- /dev/null
+++ b/Documentation/sections/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel ELF sections'
+html_search_language = 'en'
diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
new file mode 100644
index 000000000000..d411e9b22eb3
--- /dev/null
+++ b/Documentation/sections/index.rst
@@ -0,0 +1,11 @@
+============+Linux Kernel ELF sections
+============+
+This book documents the Linux kernel's use of ELF sections, as well as helpers
+used throughout the kernel to help declare and define them.
+
+.. toctree::
+   :maxdepth: 4
+
+   section-core
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
new file mode 100644
index 000000000000..ecf4228bc4f8
--- /dev/null
+++ b/Documentation/sections/section-core.rst
@@ -0,0 +1,153 @@
+===============
+Core Linux kernel ELF sections
+===============
+
+About
+==+
+This book documents the different standard and custom ELF sections used
+on the Linux kernel, which we refer to as the ``core Linux sections``. We
+start off by documenting the standard ELF sections used by Linux and move
+on to the basic custom ELF sections, followed by a set of helpers. Each
+section documented describes the goal of the section, and addresses
+concurrency considerations when applicable.
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Custom linker script
+
+Standard ELF section use in Linux
+================+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Standard ELF section use in Linux
+
+SECTION_RODATA
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_RODATA
+
+SECTION_RODATA
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_TEXT
+
+SECTION_DATA
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_DATA
+
+Linux .init\* sections
+===========
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux init sections
+
+SECTION_INIT_DATA
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_INIT_DATA
+
+SECTION_INIT_RODATA
+-------------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_INIT_RODATA
+
+SECTION_INIT_CALL
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_INIT_CALL
+
+Linux .exit\* sections
+===========
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux exit sections
+
+SECTION_EXIT
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_EXIT
+
+SECTION_EXIT_DATA
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_EXIT_DATA
+
+SECTION_EXIT_CALL
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_EXIT_CALL
+
+Linux .ref\* sections
+==========+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux references to init sections
+
+SECTION_REF
+-----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_REF
+
+SECTION_REF_DATA
+----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_REF_DATA
+
+SECTION_REF_RODATA
+------------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_REF_RODATA
+
+Linux section ordering
+===========
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux section ordering
+
+SECTION_ORDER_ANY
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_ORDER_ANY
+
+Generic Linux kernel section helpers
+==================
+
+Introduction
+-------------
+.. kernel-doc:: include/linux/sections.h
+   :doc: Introduction
+
+LINUX_SECTION_ALIGNMENT
+-----------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_ALIGNMENT
+
+LINUX_SECTION_SIZE
+------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_SIZE
+
+LINUX_SECTION_EMPTY
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_EMPTY
+
+LINUX_SECTION_START
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_START
+
+LINUX_SECTION_END
+-----------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_END
+
+DECLARE_LINUX_SECTION
+---------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION
+
+DECLARE_LINUX_SECTION_RO
+------------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION_RO
diff --git a/MAINTAINERS b/MAINTAINERS
index 5aec01883020..689c12075842 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5217,6 +5217,20 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTIONS
+M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
+M:	Josh Poimboeuf <jpoimboe@redhat.com>
+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 for-arnd
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux-next.git for-arnd
+S:	Supported
+F:	include/asm-generic/section-core.h
+F:	include/asm-generic/sections.h
+F:	include/asm-generic/vmlinux.lds.h
+F:	Documentation/sections/section-core.rst
+
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index bf8475ce85ee..5422827f1585 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += section-core.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 0b10ef2a4372..9a0929576de1 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -50,3 +50,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 0745538b26d3..47923635be16 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += timex.h
 generic-y += trace_clock.h
 generic-y += unaligned.h
+generic-y += section-core.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index f43d2c44c765..42d00806e4fb 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -52,3 +52,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 241b9b9729d8..f2c3b656a0e7 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 91d49c0a3118..7de674411bed 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 64465e7e2245..38127ce747be 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -62,3 +62,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 1778805f6380..385cd88a9d9e 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += types.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 1fa084cf1a43..46d7c599d9b8 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 373cb23301e3..1ec04ec1c82b 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -75,3 +75,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index db8ddabc6bd2..37d7bfae7619 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -60,3 +60,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 502a91d8dbbd..672c6d5da18c 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 860e440611c9..6111e1523750 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index eb85bd9c6180..eef72c464c9b 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 29acb89daaaa..50ebd5a30d16 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -56,3 +56,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index b0ae88c9fed9..c6c2cf6edc98 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 9740066cc631..12f7c5984c03 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -20,3 +20,4 @@ generic-y += trace_clock.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 1c8dd0f5cd5d..f8145bc85835 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index d63330e88379..c9c7cb82b00f 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 2832f031fb11..86175e701869 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -71,3 +71,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index f9b3a81aefcd..6f43f33f0e0f 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index ab9f4e0ed4cf..b49fab7bab2f 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -7,3 +7,4 @@ generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
+generic-y += section-core.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 20f196b82a6e..89e74b59f32d 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index a05218ff3fe4..f089a264cd38 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 751c3373a92c..7b0356dca562 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index cfc918067f80..d51b84d6b4b7 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index ba35c41c71ff..7b8a652e43ae 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 904f3ebf4220..e9849834d55e 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -27,3 +27,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
new file mode 100644
index 000000000000..ebffeed8835d
--- /dev/null
+++ b/arch/unicore32/include/asm/section-core.h
@@ -0,0 +1,19 @@
+#ifndef __UNICORE_SECTION_CORE_ASM_H__
+#define __UNICORE_SECTION_CORE_ASM_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/.
+ */
+
+/* Unicore32 has known to not work properly with the type set, so ignore it */
+
+#define __set_section_core_type(___section, ___core, ___name,		\
+				___level, ___flags, ___type)		\
+	.section ___section.___core.___name.___level, ___flags
+
+#include <asm-generic/section-core.h>
+
+#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 2cfed174e3c9..f6914a57bc16 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -16,3 +16,4 @@ generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
+generic-y += section-core.h
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index 28cf4c5d65ef..81ca6816bd72 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -31,3 +31,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..2ab57e2c4117
--- /dev/null
+++ b/include/asm-generic/section-core.h
@@ -0,0 +1,341 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Custom linker script
+ *
+ * The Linux vmlinux binary uses a custom linker script on each architecture
+ * which it uses to strategically place standard ELF sections and also adds
+ * custom specialized ELF sections. Each architecture defines its own custom
+ * linker defined in arch/$(ARCH)/kernel/vmlinux.lds.S -- these in turn
+ * include and use definitions in include/asm-generic/vmlinux.lds.h as well
+ * as some helpers documented in this chaper.
+ */
+
+/**
+ * DOC: Standard ELF section use in Linux
+ *
+ * Linux makes use of the standard ELF sections, this sections documents
+ * these.
+ */
+
+/**
+ * DOC: SECTION_RODATA
+ *
+ * Macro name for code which must be protected from write access, read only
+ * data.
+ */
+#define SECTION_RODATA			.rodata
+
+/**
+ * DOC: SECTION_TEXT
+ *
+ * Macro name used to annotate code (functions) used during regular
+ * kernel run time. This is combined with `SECTION_RODATA`, only this
+ * section also allows for execution.
+ *
+ */
+#define SECTION_TEXT			.text
+
+/**
+ * DOC: SECTION_DATA
+ *
+ * Macro name for read-write data.
+ */
+#define SECTION_DATA			.data
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: SECTION_INIT
+ *
+ * Macro name used to annotate code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+#define SECTION_INIT			.init.text
+
+/**
+ * DOC: SECTION_INIT_DATA
+ *
+ * Macro name used to annotate data structures used only during boot or driver
+ * initialization.
+ */
+#define SECTION_INIT_DATA		.init.data
+
+/**
+ * DOC: SECTION_INIT_RODATA
+ *
+ * Macro name used to annotate read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+#define SECTION_INIT_RODATA		.init.rodata
+
+/**
+ * DOC: SECTION_INIT_CALL
+ *
+ * Special macro name used to annotate subsystem init call. These calls are
+ * are now grouped by functionality into separate subsections. Ordering inside
+ * the subsections is determined by link order.
+ */
+#define SECTION_INIT_CALL		.initcall
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: SECTION_EXIT
+ *
+ * Macro name used to annotate code (functions) used only during module
+ * unload.
+ */
+#define SECTION_EXIT			.exit.text
+
+/**
+ * DOC: SECTION_EXIT_DATA
+ *
+ * Macro name used to annotate data structures used only during module
+ * unload.
+ */
+#define SECTION_EXIT_DATA		.exit.data
+
+/**
+ * DOC: SECTION_EXIT_CALL
+ *
+ * Special macro name used to annotate an exit exit routine, order
+ * is important and maintained by link order.
+ */
+#define SECTION_EXIT_CALL		.exitcall.exit
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: SECTION_REF
+ *
+ * Macro name used to annotate that code (functions) declared with this section
+ * has been vetteed as valid for its reference or use of other code (functions)
+ * or data structures which are part of the init sections.
+ */
+#define SECTION_REF			.ref.text
+
+/**
+ * DOC: SECTION_REF_DATA
+ *
+ * Macro name used to annotate data structures declared with this section have
+ * been vetteed for its reference or use of other code (functions) or data
+ * structures part of the init sections.
+ */
+#define SECTION_REF_DATA		.ref.data
+
+/**
+ * DOC: SECTION_REF_RODATA
+ *
+ * Macro name used to annotate const code (functions) const data structures
+ * which has been vetteed for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+#define SECTION_REF_RODATA		.ref.rodata
+
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections. Linux has used 'SORT()' in ``include/asm-generic/vmlinux.lds.h``
+ * for years.
+ */
+
+/**
+ * DOC: SECTION_ORDER_ANY
+ *
+ * Macro name which can be used as helper to annotate custom section
+ * ordering at link time is not relevant for specific sections.
+ */
+#define SECTION_ORDER_ANY	any
+
+/*
+ * These section _ALL() helpers are for use on linker scripts and helpers
+ */
+#define SECTION_ALL(__section)						\
+	__section##.*
+
+#define __SECTION_CORE(__section, __core, __name, __level)		\
+	__section.__core.__name.__level
+
+#define SECTION_CORE_ALL(__section, __core)				\
+	__section##.##__core##.*
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section.___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section.___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section.__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifdef LINKER_SCRIPT
+
+#  ifndef SECTION_CORE
+#   define SECTION_CORE(__section, __core, __name, __level)		\
+	__SECTION_CORE(__section,__core,__name,__level)
+#  endif
+
+# else
+
+#  ifndef SECTION_CORE
+#   define SECTION_CORE(__section, __core, __name, __level)		\
+	push_section_core(__section, __core, __name, __level,)
+#  endif
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+# ifndef SECTION_CORE
+#  define SECTION_CORE(__section, __core, __name, __level)		\
+	__stringify(__SECTION_CORE(__section,__core,__name,__level))
+# endif
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align\x16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index af0254c09424..298252df3c81 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_GENERIC_SECTIONS_H_
 #define _ASM_GENERIC_SECTIONS_H_
 
+#include <asm/section-core.h>
+
 /* References to section boundaries */
 
 #include <linux/compiler.h>
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 24563970ff7b..731087276a32 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -55,6 +55,7 @@
 #endif
 
 #include <linux/export.h>
+#include <asm/section-core.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
@@ -198,8 +199,8 @@
 
 /* .data section */
 #define DATA_DATA							\
-	*(.data)							\
-	*(.ref.data)							\
+	*(SECTION_DATA)							\
+	*(SECTION_REF_DATA)						\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
 	MEM_KEEP(exit.data)						\
@@ -262,9 +263,9 @@
  */
 #define RO_DATA_SECTION(align)						\
 	. = ALIGN((align));						\
-	.rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {		\
+	SECTION_RODATA    : AT(ADDR(SECTION_RODATA) - LOAD_OFFSET) {	\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
-		*(.rodata) *(.rodata.*)					\
+		*(SECTION_RODATA) *(SECTION_ALL(SECTION_RODATA))	\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		*(__vermagic)		/* Kernel version magic */	\
 		. = ALIGN(8);						\
@@ -394,7 +395,7 @@
 									\
 	/* __*init sections */						\
 	__init_rodata : AT(ADDR(__init_rodata) - LOAD_OFFSET) {		\
-		*(.ref.rodata)						\
+		*(SECTION_REF_RODATA)					\
 		MEM_KEEP(init.rodata)					\
 		MEM_KEEP(exit.rodata)					\
 	}								\
@@ -432,8 +433,8 @@
  * during second ld run in second ld pass when generating System.map */
 #define TEXT_TEXT							\
 		ALIGN_FUNCTION();					\
-		*(.text.hot .text .text.fixup .text.unlikely)		\
-		*(.ref.text)						\
+		*(.text.hot SECTION_TEXT .text.fixup .text.unlikely)	\
+		*(SECTION_REF)						\
 	MEM_KEEP(init.text)						\
 	MEM_KEEP(exit.text)						\
 
@@ -527,11 +528,11 @@
 
 /* init and exit section handling */
 #define INIT_DATA							\
-	*(.init.data)							\
+	*(SECTION_INIT_DATA)						\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
-	*(.init.rodata)							\
+	*(SECTION_INIT_RODATA)						\
 	FTRACE_EVENTS()							\
 	TRACE_SYSCALLS()						\
 	KPROBE_BLACKLIST()						\
@@ -549,24 +550,24 @@
 	EARLYCON_TABLE()
 
 #define INIT_TEXT							\
-	*(.init.text)							\
+	*(SECTION_INIT)							\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
 #define EXIT_DATA							\
-	*(.exit.data)							\
+	*(SECTION_EXIT_DATA)						\
 	*(.fini_array)							\
 	*(.dtors)							\
 	MEM_DISCARD(exit.data)						\
 	MEM_DISCARD(exit.rodata)
 
 #define EXIT_TEXT							\
-	*(.exit.text)							\
+	*(SECTION_EXIT)							\
 	*(.text.exit)							\
 	MEM_DISCARD(exit.text)
 
 #define EXIT_CALL							\
-	*(.exitcall.exit)
+	*(SECTION_EXIT_CALL)
 
 /*
  * bss (Block Started by Symbol) - uninitialized data
diff --git a/include/linux/sections.h b/include/linux/sections.h
new file mode 100644
index 000000000000..f21c6ee88ded
--- /dev/null
+++ b/include/linux/sections.h
@@ -0,0 +1,111 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_SIZE - get number of entries in the section
+ *
+ * @name: section name
+ *
+ * This gives you the number of entries in the section.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINUX_SECTION_SIZE(frobnicator_fns);
+ */
+#define LINUX_SECTION_SIZE(name)					\
+	((VMLINUX_SYMBOL(name##__end)) - (VMLINUX_SYMBOL(name)))
+
+/**
+ * LINUX_SECTION_EMPTY - check if section has no entries
+ *
+ * @name: section name
+ *
+ * Returns true if section is emtpy.
+ *
+ *   bool is_empty = LINUX_SECTION_EMPTY(frobnicator_fns);
+ */
+#define LINUX_SECTION_EMPTY(name)	(LINUX_SECTION_SIZE(name) = 0)
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_TYPE(section, type, name, level)			\
+	#section "." #type "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Linux makes extensive use of custom ELF header sections,
documentation for these are well scatterred. Unify this
documentation in a central place and provide helpers to
build custom Linux sections.

This also generalizes sections code to enable avoiding
modifying the linker scripts when we want to add new
custom Linux sections. In order to make this generally
useful we need to ensure all architectures can make use of
core section helpers but that they can also override should
this be needed. Instead of relying on section.h this adds
a sections-core.h since this will be targetted to be safe
to be used on asm code, linker scripts and C code.

v4:

o Port to shiny new sphinx documentation format

o fix a unicore32 build, turns out this actually fixes unicore32
  defconfig builds which were failing for a long while. unicore32
  does not seem to grok well the type passed on a section declaration,
  this ignores it.

o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
  this was causing final linker issues with blackfin -- this is
  a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
  being metatag. metatag is not supported on 0-day so I cannot confirm
  compilation there.

o Added SECTION_CORE() for C code, used later by __LINUX_RANGE()

o Since SECTION_CORE() is defined for linker script and C code, share
  the same helper and just use a __stringify() for the C code as is done
  for the other C helpers.

o move generic sections to asm-generic/section-core.h instead.
  PowerPC compilation blows up if asm/jump_labels.h gets
  section.h included, fixing this is not in any way easy.
  The list of issues are endless. Moving new data to a new
  simple file resolves this.

o since things are now in asm-generic/section-core.h the
  guard changes on asm-generic/sections.h and each architecture
  sections.h are no longer needed

o Give generic sections some maintainer love, that change is
  Acked-by Arnd Bergmann, Josh and hpa.

o A few checkpatch.pl style fixes

o As suggested by James Hogan use generic-y to copy generic
  header files on architectures that do not have a sections.h
  instead of writing a simple file only to include the generic one.

v3:

o add missing sections.h for architectures that did not
  have it

o move generic sections to asm-generic/sections.h

o add generic asm helpers section_type(), section_type_asmtype(),
  push_section_type() -- these helpers enable easy use for
  for later declaring and using of custom linux sections using
  more standard APIs in both C code, asm code (C asm calls, or
  asm files), enabling future standardized section types to
  be more immediately accessible to asm code, not just C code.
  Note for ASM_CMD_SEP we use by default "\n", architectures needed
  to override can do so on their own sections.h prior to inclusion
  of asm-generic/sections.h

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/index.rst                   |   1 +
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  11 +
 Documentation/sections/section-core.rst   | 153 ++++++++++++++
 MAINTAINERS                               |  14 ++
 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/Kbuild               |   1 +
 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/section-core.h |  19 ++
 arch/x86/include/asm/Kbuild               |   1 +
 arch/xtensa/include/asm/Kbuild            |   1 +
 include/asm-generic/section-core.h        | 341 ++++++++++++++++++++++++++++++
 include/asm-generic/sections.h            |   2 +
 include/asm-generic/vmlinux.lds.h         |  27 +--
 include/linux/sections.h                  | 111 ++++++++++
 40 files changed, 700 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/linux/sections.h

diff --git a/Documentation/index.rst b/Documentation/index.rst
index a15f81855b39..10c9b867e326 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -14,6 +14,7 @@ Contents:
    kernel-documentation
    media/index
    gpu/index
+   sections/index
 
 Indices and tables
 ==================
diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
new file mode 100644
index 000000000000..faa1c57595e1
--- /dev/null
+++ b/Documentation/sections/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel ELF sections'
+html_search_language = 'en'
diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
new file mode 100644
index 000000000000..d411e9b22eb3
--- /dev/null
+++ b/Documentation/sections/index.rst
@@ -0,0 +1,11 @@
+=========================
+Linux Kernel ELF sections
+=========================
+
+This book documents the Linux kernel's use of ELF sections, as well as helpers
+used throughout the kernel to help declare and define them.
+
+.. toctree::
+   :maxdepth: 4
+
+   section-core
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
new file mode 100644
index 000000000000..ecf4228bc4f8
--- /dev/null
+++ b/Documentation/sections/section-core.rst
@@ -0,0 +1,153 @@
+==============================
+Core Linux kernel ELF sections
+==============================
+
+About
+=====
+
+This book documents the different standard and custom ELF sections used
+on the Linux kernel, which we refer to as the ``core Linux sections``. We
+start off by documenting the standard ELF sections used by Linux and move
+on to the basic custom ELF sections, followed by a set of helpers. Each
+section documented describes the goal of the section, and addresses
+concurrency considerations when applicable.
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Custom linker script
+
+Standard ELF section use in Linux
+=================================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Standard ELF section use in Linux
+
+SECTION_RODATA
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_RODATA
+
+SECTION_RODATA
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_TEXT
+
+SECTION_DATA
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_DATA
+
+Linux .init\* sections
+======================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux init sections
+
+SECTION_INIT_DATA
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_INIT_DATA
+
+SECTION_INIT_RODATA
+-------------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_INIT_RODATA
+
+SECTION_INIT_CALL
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_INIT_CALL
+
+Linux .exit\* sections
+======================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux exit sections
+
+SECTION_EXIT
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_EXIT
+
+SECTION_EXIT_DATA
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_EXIT_DATA
+
+SECTION_EXIT_CALL
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_EXIT_CALL
+
+Linux .ref\* sections
+=====================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux references to init sections
+
+SECTION_REF
+-----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_REF
+
+SECTION_REF_DATA
+----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_REF_DATA
+
+SECTION_REF_RODATA
+------------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_REF_RODATA
+
+Linux section ordering
+======================
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux section ordering
+
+SECTION_ORDER_ANY
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_ORDER_ANY
+
+Generic Linux kernel section helpers
+====================================
+
+Introduction
+-------------
+.. kernel-doc:: include/linux/sections.h
+   :doc: Introduction
+
+LINUX_SECTION_ALIGNMENT
+-----------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_ALIGNMENT
+
+LINUX_SECTION_SIZE
+------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_SIZE
+
+LINUX_SECTION_EMPTY
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_EMPTY
+
+LINUX_SECTION_START
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_START
+
+LINUX_SECTION_END
+-----------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_END
+
+DECLARE_LINUX_SECTION
+---------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION
+
+DECLARE_LINUX_SECTION_RO
+------------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION_RO
diff --git a/MAINTAINERS b/MAINTAINERS
index 5aec01883020..689c12075842 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5217,6 +5217,20 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTIONS
+M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
+M:	Josh Poimboeuf <jpoimboe@redhat.com>
+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 for-arnd
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux-next.git for-arnd
+S:	Supported
+F:	include/asm-generic/section-core.h
+F:	include/asm-generic/sections.h
+F:	include/asm-generic/vmlinux.lds.h
+F:	Documentation/sections/section-core.rst
+
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index bf8475ce85ee..5422827f1585 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += section-core.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 0b10ef2a4372..9a0929576de1 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -50,3 +50,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 0745538b26d3..47923635be16 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += timex.h
 generic-y += trace_clock.h
 generic-y += unaligned.h
+generic-y += section-core.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index f43d2c44c765..42d00806e4fb 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -52,3 +52,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 241b9b9729d8..f2c3b656a0e7 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 91d49c0a3118..7de674411bed 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 64465e7e2245..38127ce747be 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -62,3 +62,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 1778805f6380..385cd88a9d9e 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += types.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 1fa084cf1a43..46d7c599d9b8 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 373cb23301e3..1ec04ec1c82b 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -75,3 +75,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index db8ddabc6bd2..37d7bfae7619 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -60,3 +60,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 502a91d8dbbd..672c6d5da18c 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 860e440611c9..6111e1523750 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index eb85bd9c6180..eef72c464c9b 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 29acb89daaaa..50ebd5a30d16 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -56,3 +56,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index b0ae88c9fed9..c6c2cf6edc98 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 9740066cc631..12f7c5984c03 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -20,3 +20,4 @@ generic-y += trace_clock.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 1c8dd0f5cd5d..f8145bc85835 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index d63330e88379..c9c7cb82b00f 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 2832f031fb11..86175e701869 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -71,3 +71,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index f9b3a81aefcd..6f43f33f0e0f 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index ab9f4e0ed4cf..b49fab7bab2f 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -7,3 +7,4 @@ generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
+generic-y += section-core.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 20f196b82a6e..89e74b59f32d 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index a05218ff3fe4..f089a264cd38 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 751c3373a92c..7b0356dca562 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index cfc918067f80..d51b84d6b4b7 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index ba35c41c71ff..7b8a652e43ae 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 904f3ebf4220..e9849834d55e 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -27,3 +27,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
new file mode 100644
index 000000000000..ebffeed8835d
--- /dev/null
+++ b/arch/unicore32/include/asm/section-core.h
@@ -0,0 +1,19 @@
+#ifndef __UNICORE_SECTION_CORE_ASM_H__
+#define __UNICORE_SECTION_CORE_ASM_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/.
+ */
+
+/* Unicore32 has known to not work properly with the type set, so ignore it */
+
+#define __set_section_core_type(___section, ___core, ___name,		\
+				___level, ___flags, ___type)		\
+	.section ___section.___core.___name.___level, ___flags
+
+#include <asm-generic/section-core.h>
+
+#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 2cfed174e3c9..f6914a57bc16 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -16,3 +16,4 @@ generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
+generic-y += section-core.h
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index 28cf4c5d65ef..81ca6816bd72 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -31,3 +31,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..2ab57e2c4117
--- /dev/null
+++ b/include/asm-generic/section-core.h
@@ -0,0 +1,341 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Custom linker script
+ *
+ * The Linux vmlinux binary uses a custom linker script on each architecture
+ * which it uses to strategically place standard ELF sections and also adds
+ * custom specialized ELF sections. Each architecture defines its own custom
+ * linker defined in arch/$(ARCH)/kernel/vmlinux.lds.S -- these in turn
+ * include and use definitions in include/asm-generic/vmlinux.lds.h as well
+ * as some helpers documented in this chaper.
+ */
+
+/**
+ * DOC: Standard ELF section use in Linux
+ *
+ * Linux makes use of the standard ELF sections, this sections documents
+ * these.
+ */
+
+/**
+ * DOC: SECTION_RODATA
+ *
+ * Macro name for code which must be protected from write access, read only
+ * data.
+ */
+#define SECTION_RODATA			.rodata
+
+/**
+ * DOC: SECTION_TEXT
+ *
+ * Macro name used to annotate code (functions) used during regular
+ * kernel run time. This is combined with `SECTION_RODATA`, only this
+ * section also allows for execution.
+ *
+ */
+#define SECTION_TEXT			.text
+
+/**
+ * DOC: SECTION_DATA
+ *
+ * Macro name for read-write data.
+ */
+#define SECTION_DATA			.data
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: SECTION_INIT
+ *
+ * Macro name used to annotate code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+#define SECTION_INIT			.init.text
+
+/**
+ * DOC: SECTION_INIT_DATA
+ *
+ * Macro name used to annotate data structures used only during boot or driver
+ * initialization.
+ */
+#define SECTION_INIT_DATA		.init.data
+
+/**
+ * DOC: SECTION_INIT_RODATA
+ *
+ * Macro name used to annotate read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+#define SECTION_INIT_RODATA		.init.rodata
+
+/**
+ * DOC: SECTION_INIT_CALL
+ *
+ * Special macro name used to annotate subsystem init call. These calls are
+ * are now grouped by functionality into separate subsections. Ordering inside
+ * the subsections is determined by link order.
+ */
+#define SECTION_INIT_CALL		.initcall
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: SECTION_EXIT
+ *
+ * Macro name used to annotate code (functions) used only during module
+ * unload.
+ */
+#define SECTION_EXIT			.exit.text
+
+/**
+ * DOC: SECTION_EXIT_DATA
+ *
+ * Macro name used to annotate data structures used only during module
+ * unload.
+ */
+#define SECTION_EXIT_DATA		.exit.data
+
+/**
+ * DOC: SECTION_EXIT_CALL
+ *
+ * Special macro name used to annotate an exit exit routine, order
+ * is important and maintained by link order.
+ */
+#define SECTION_EXIT_CALL		.exitcall.exit
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: SECTION_REF
+ *
+ * Macro name used to annotate that code (functions) declared with this section
+ * has been vetteed as valid for its reference or use of other code (functions)
+ * or data structures which are part of the init sections.
+ */
+#define SECTION_REF			.ref.text
+
+/**
+ * DOC: SECTION_REF_DATA
+ *
+ * Macro name used to annotate data structures declared with this section have
+ * been vetteed for its reference or use of other code (functions) or data
+ * structures part of the init sections.
+ */
+#define SECTION_REF_DATA		.ref.data
+
+/**
+ * DOC: SECTION_REF_RODATA
+ *
+ * Macro name used to annotate const code (functions) const data structures
+ * which has been vetteed for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+#define SECTION_REF_RODATA		.ref.rodata
+
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections. Linux has used 'SORT()' in ``include/asm-generic/vmlinux.lds.h``
+ * for years.
+ */
+
+/**
+ * DOC: SECTION_ORDER_ANY
+ *
+ * Macro name which can be used as helper to annotate custom section
+ * ordering at link time is not relevant for specific sections.
+ */
+#define SECTION_ORDER_ANY	any
+
+/*
+ * These section _ALL() helpers are for use on linker scripts and helpers
+ */
+#define SECTION_ALL(__section)						\
+	__section##.*
+
+#define __SECTION_CORE(__section, __core, __name, __level)		\
+	__section.__core.__name.__level
+
+#define SECTION_CORE_ALL(__section, __core)				\
+	__section##.##__core##.*
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section.___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section.___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section.__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifdef LINKER_SCRIPT
+
+#  ifndef SECTION_CORE
+#   define SECTION_CORE(__section, __core, __name, __level)		\
+	__SECTION_CORE(__section,__core,__name,__level)
+#  endif
+
+# else
+
+#  ifndef SECTION_CORE
+#   define SECTION_CORE(__section, __core, __name, __level)		\
+	push_section_core(__section, __core, __name, __level,)
+#  endif
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+# ifndef SECTION_CORE
+#  define SECTION_CORE(__section, __core, __name, __level)		\
+	__stringify(__SECTION_CORE(__section,__core,__name,__level))
+# endif
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align=16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index af0254c09424..298252df3c81 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_GENERIC_SECTIONS_H_
 #define _ASM_GENERIC_SECTIONS_H_
 
+#include <asm/section-core.h>
+
 /* References to section boundaries */
 
 #include <linux/compiler.h>
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 24563970ff7b..731087276a32 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -55,6 +55,7 @@
 #endif
 
 #include <linux/export.h>
+#include <asm/section-core.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
@@ -198,8 +199,8 @@
 
 /* .data section */
 #define DATA_DATA							\
-	*(.data)							\
-	*(.ref.data)							\
+	*(SECTION_DATA)							\
+	*(SECTION_REF_DATA)						\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
 	MEM_KEEP(exit.data)						\
@@ -262,9 +263,9 @@
  */
 #define RO_DATA_SECTION(align)						\
 	. = ALIGN((align));						\
-	.rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {		\
+	SECTION_RODATA    : AT(ADDR(SECTION_RODATA) - LOAD_OFFSET) {	\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
-		*(.rodata) *(.rodata.*)					\
+		*(SECTION_RODATA) *(SECTION_ALL(SECTION_RODATA))	\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		*(__vermagic)		/* Kernel version magic */	\
 		. = ALIGN(8);						\
@@ -394,7 +395,7 @@
 									\
 	/* __*init sections */						\
 	__init_rodata : AT(ADDR(__init_rodata) - LOAD_OFFSET) {		\
-		*(.ref.rodata)						\
+		*(SECTION_REF_RODATA)					\
 		MEM_KEEP(init.rodata)					\
 		MEM_KEEP(exit.rodata)					\
 	}								\
@@ -432,8 +433,8 @@
  * during second ld run in second ld pass when generating System.map */
 #define TEXT_TEXT							\
 		ALIGN_FUNCTION();					\
-		*(.text.hot .text .text.fixup .text.unlikely)		\
-		*(.ref.text)						\
+		*(.text.hot SECTION_TEXT .text.fixup .text.unlikely)	\
+		*(SECTION_REF)						\
 	MEM_KEEP(init.text)						\
 	MEM_KEEP(exit.text)						\
 
@@ -527,11 +528,11 @@
 
 /* init and exit section handling */
 #define INIT_DATA							\
-	*(.init.data)							\
+	*(SECTION_INIT_DATA)						\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
-	*(.init.rodata)							\
+	*(SECTION_INIT_RODATA)						\
 	FTRACE_EVENTS()							\
 	TRACE_SYSCALLS()						\
 	KPROBE_BLACKLIST()						\
@@ -549,24 +550,24 @@
 	EARLYCON_TABLE()
 
 #define INIT_TEXT							\
-	*(.init.text)							\
+	*(SECTION_INIT)							\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
 #define EXIT_DATA							\
-	*(.exit.data)							\
+	*(SECTION_EXIT_DATA)						\
 	*(.fini_array)							\
 	*(.dtors)							\
 	MEM_DISCARD(exit.data)						\
 	MEM_DISCARD(exit.rodata)
 
 #define EXIT_TEXT							\
-	*(.exit.text)							\
+	*(SECTION_EXIT)							\
 	*(.text.exit)							\
 	MEM_DISCARD(exit.text)
 
 #define EXIT_CALL							\
-	*(.exitcall.exit)
+	*(SECTION_EXIT_CALL)
 
 /*
  * bss (Block Started by Symbol) - uninitialized data
diff --git a/include/linux/sections.h b/include/linux/sections.h
new file mode 100644
index 000000000000..f21c6ee88ded
--- /dev/null
+++ b/include/linux/sections.h
@@ -0,0 +1,111 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_SIZE - get number of entries in the section
+ *
+ * @name: section name
+ *
+ * This gives you the number of entries in the section.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINUX_SECTION_SIZE(frobnicator_fns);
+ */
+#define LINUX_SECTION_SIZE(name)					\
+	((VMLINUX_SYMBOL(name##__end)) - (VMLINUX_SYMBOL(name)))
+
+/**
+ * LINUX_SECTION_EMPTY - check if section has no entries
+ *
+ * @name: section name
+ *
+ * Returns true if section is emtpy.
+ *
+ *   bool is_empty = LINUX_SECTION_EMPTY(frobnicator_fns);
+ */
+#define LINUX_SECTION_EMPTY(name)	(LINUX_SECTION_SIZE(name) == 0)
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_TYPE(section, type, name, level)			\
+	#section "." #type "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
-- 
2.9.2


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Linux makes extensive use of custom ELF header sections,
documentation for these are well scatterred. Unify this
documentation in a central place and provide helpers to
build custom Linux sections.

This also generalizes sections code to enable avoiding
modifying the linker scripts when we want to add new
custom Linux sections. In order to make this generally
useful we need to ensure all architectures can make use of
core section helpers but that they can also override should
this be needed. Instead of relying on section.h this adds
a sections-core.h since this will be targetted to be safe
to be used on asm code, linker scripts and C code.

v4:

o Port to shiny new sphinx documentation format

o fix a unicore32 build, turns out this actually fixes unicore32
  defconfig builds which were failing for a long while. unicore32
  does not seem to grok well the type passed on a section declaration,
  this ignores it.

o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
  this was causing final linker issues with blackfin -- this is
  a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
  being metatag. metatag is not supported on 0-day so I cannot confirm
  compilation there.

o Added SECTION_CORE() for C code, used later by __LINUX_RANGE()

o Since SECTION_CORE() is defined for linker script and C code, share
  the same helper and just use a __stringify() for the C code as is done
  for the other C helpers.

o move generic sections to asm-generic/section-core.h instead.
  PowerPC compilation blows up if asm/jump_labels.h gets
  section.h included, fixing this is not in any way easy.
  The list of issues are endless. Moving new data to a new
  simple file resolves this.

o since things are now in asm-generic/section-core.h the
  guard changes on asm-generic/sections.h and each architecture
  sections.h are no longer needed

o Give generic sections some maintainer love, that change is
  Acked-by Arnd Bergmann, Josh and hpa.

o A few checkpatch.pl style fixes

o As suggested by James Hogan use generic-y to copy generic
  header files on architectures that do not have a sections.h
  instead of writing a simple file only to include the generic one.

v3:

o add missing sections.h for architectures that did not
  have it

o move generic sections to asm-generic/sections.h

o add generic asm helpers section_type(), section_type_asmtype(),
  push_section_type() -- these helpers enable easy use for
  for later declaring and using of custom linux sections using
  more standard APIs in both C code, asm code (C asm calls, or
  asm files), enabling future standardized section types to
  be more immediately accessible to asm code, not just C code.
  Note for ASM_CMD_SEP we use by default "\n", architectures needed
  to override can do so on their own sections.h prior to inclusion
  of asm-generic/sections.h

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/index.rst                   |   1 +
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  11 +
 Documentation/sections/section-core.rst   | 153 ++++++++++++++
 MAINTAINERS                               |  14 ++
 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/Kbuild               |   1 +
 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/section-core.h |  19 ++
 arch/x86/include/asm/Kbuild               |   1 +
 arch/xtensa/include/asm/Kbuild            |   1 +
 include/asm-generic/section-core.h        | 341 ++++++++++++++++++++++++++++++
 include/asm-generic/sections.h            |   2 +
 include/asm-generic/vmlinux.lds.h         |  27 +--
 include/linux/sections.h                  | 111 ++++++++++
 40 files changed, 700 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/linux/sections.h

diff --git a/Documentation/index.rst b/Documentation/index.rst
index a15f81855b39..10c9b867e326 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -14,6 +14,7 @@ Contents:
    kernel-documentation
    media/index
    gpu/index
+   sections/index
 
 Indices and tables
 ==================
diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
new file mode 100644
index 000000000000..faa1c57595e1
--- /dev/null
+++ b/Documentation/sections/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel ELF sections'
+html_search_language = 'en'
diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
new file mode 100644
index 000000000000..d411e9b22eb3
--- /dev/null
+++ b/Documentation/sections/index.rst
@@ -0,0 +1,11 @@
+=========================
+Linux Kernel ELF sections
+=========================
+
+This book documents the Linux kernel's use of ELF sections, as well as helpers
+used throughout the kernel to help declare and define them.
+
+.. toctree::
+   :maxdepth: 4
+
+   section-core
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
new file mode 100644
index 000000000000..ecf4228bc4f8
--- /dev/null
+++ b/Documentation/sections/section-core.rst
@@ -0,0 +1,153 @@
+==============================
+Core Linux kernel ELF sections
+==============================
+
+About
+=====
+
+This book documents the different standard and custom ELF sections used
+on the Linux kernel, which we refer to as the ``core Linux sections``. We
+start off by documenting the standard ELF sections used by Linux and move
+on to the basic custom ELF sections, followed by a set of helpers. Each
+section documented describes the goal of the section, and addresses
+concurrency considerations when applicable.
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Custom linker script
+
+Standard ELF section use in Linux
+=================================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Standard ELF section use in Linux
+
+SECTION_RODATA
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_RODATA
+
+SECTION_RODATA
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_TEXT
+
+SECTION_DATA
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_DATA
+
+Linux .init\* sections
+======================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux init sections
+
+SECTION_INIT_DATA
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_INIT_DATA
+
+SECTION_INIT_RODATA
+-------------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_INIT_RODATA
+
+SECTION_INIT_CALL
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_INIT_CALL
+
+Linux .exit\* sections
+======================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux exit sections
+
+SECTION_EXIT
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_EXIT
+
+SECTION_EXIT_DATA
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_EXIT_DATA
+
+SECTION_EXIT_CALL
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_EXIT_CALL
+
+Linux .ref\* sections
+=====================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux references to init sections
+
+SECTION_REF
+-----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_REF
+
+SECTION_REF_DATA
+----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_REF_DATA
+
+SECTION_REF_RODATA
+------------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_REF_RODATA
+
+Linux section ordering
+======================
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux section ordering
+
+SECTION_ORDER_ANY
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: SECTION_ORDER_ANY
+
+Generic Linux kernel section helpers
+====================================
+
+Introduction
+-------------
+.. kernel-doc:: include/linux/sections.h
+   :doc: Introduction
+
+LINUX_SECTION_ALIGNMENT
+-----------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_ALIGNMENT
+
+LINUX_SECTION_SIZE
+------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_SIZE
+
+LINUX_SECTION_EMPTY
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_EMPTY
+
+LINUX_SECTION_START
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_START
+
+LINUX_SECTION_END
+-----------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_END
+
+DECLARE_LINUX_SECTION
+---------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION
+
+DECLARE_LINUX_SECTION_RO
+------------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION_RO
diff --git a/MAINTAINERS b/MAINTAINERS
index 5aec01883020..689c12075842 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5217,6 +5217,20 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTIONS
+M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
+M:	Josh Poimboeuf <jpoimboe@redhat.com>
+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 for-arnd
+T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux-next.git for-arnd
+S:	Supported
+F:	include/asm-generic/section-core.h
+F:	include/asm-generic/sections.h
+F:	include/asm-generic/vmlinux.lds.h
+F:	Documentation/sections/section-core.rst
+
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index bf8475ce85ee..5422827f1585 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += section-core.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 0b10ef2a4372..9a0929576de1 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -50,3 +50,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 0745538b26d3..47923635be16 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += timex.h
 generic-y += trace_clock.h
 generic-y += unaligned.h
+generic-y += section-core.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index f43d2c44c765..42d00806e4fb 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -52,3 +52,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 241b9b9729d8..f2c3b656a0e7 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 91d49c0a3118..7de674411bed 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 64465e7e2245..38127ce747be 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -62,3 +62,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 1778805f6380..385cd88a9d9e 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += types.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 1fa084cf1a43..46d7c599d9b8 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 373cb23301e3..1ec04ec1c82b 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -75,3 +75,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index db8ddabc6bd2..37d7bfae7619 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -60,3 +60,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 502a91d8dbbd..672c6d5da18c 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 860e440611c9..6111e1523750 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index eb85bd9c6180..eef72c464c9b 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 29acb89daaaa..50ebd5a30d16 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -56,3 +56,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index b0ae88c9fed9..c6c2cf6edc98 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 9740066cc631..12f7c5984c03 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -20,3 +20,4 @@ generic-y += trace_clock.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 1c8dd0f5cd5d..f8145bc85835 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index d63330e88379..c9c7cb82b00f 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 2832f031fb11..86175e701869 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -71,3 +71,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index f9b3a81aefcd..6f43f33f0e0f 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index ab9f4e0ed4cf..b49fab7bab2f 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -7,3 +7,4 @@ generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
+generic-y += section-core.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 20f196b82a6e..89e74b59f32d 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index a05218ff3fe4..f089a264cd38 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 751c3373a92c..7b0356dca562 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index cfc918067f80..d51b84d6b4b7 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index ba35c41c71ff..7b8a652e43ae 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 904f3ebf4220..e9849834d55e 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -27,3 +27,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
new file mode 100644
index 000000000000..ebffeed8835d
--- /dev/null
+++ b/arch/unicore32/include/asm/section-core.h
@@ -0,0 +1,19 @@
+#ifndef __UNICORE_SECTION_CORE_ASM_H__
+#define __UNICORE_SECTION_CORE_ASM_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/.
+ */
+
+/* Unicore32 has known to not work properly with the type set, so ignore it */
+
+#define __set_section_core_type(___section, ___core, ___name,		\
+				___level, ___flags, ___type)		\
+	.section ___section.___core.___name.___level, ___flags
+
+#include <asm-generic/section-core.h>
+
+#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 2cfed174e3c9..f6914a57bc16 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -16,3 +16,4 @@ generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
+generic-y += section-core.h
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index 28cf4c5d65ef..81ca6816bd72 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -31,3 +31,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..2ab57e2c4117
--- /dev/null
+++ b/include/asm-generic/section-core.h
@@ -0,0 +1,341 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Custom linker script
+ *
+ * The Linux vmlinux binary uses a custom linker script on each architecture
+ * which it uses to strategically place standard ELF sections and also adds
+ * custom specialized ELF sections. Each architecture defines its own custom
+ * linker defined in arch/$(ARCH)/kernel/vmlinux.lds.S -- these in turn
+ * include and use definitions in include/asm-generic/vmlinux.lds.h as well
+ * as some helpers documented in this chaper.
+ */
+
+/**
+ * DOC: Standard ELF section use in Linux
+ *
+ * Linux makes use of the standard ELF sections, this sections documents
+ * these.
+ */
+
+/**
+ * DOC: SECTION_RODATA
+ *
+ * Macro name for code which must be protected from write access, read only
+ * data.
+ */
+#define SECTION_RODATA			.rodata
+
+/**
+ * DOC: SECTION_TEXT
+ *
+ * Macro name used to annotate code (functions) used during regular
+ * kernel run time. This is combined with `SECTION_RODATA`, only this
+ * section also allows for execution.
+ *
+ */
+#define SECTION_TEXT			.text
+
+/**
+ * DOC: SECTION_DATA
+ *
+ * Macro name for read-write data.
+ */
+#define SECTION_DATA			.data
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: SECTION_INIT
+ *
+ * Macro name used to annotate code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+#define SECTION_INIT			.init.text
+
+/**
+ * DOC: SECTION_INIT_DATA
+ *
+ * Macro name used to annotate data structures used only during boot or driver
+ * initialization.
+ */
+#define SECTION_INIT_DATA		.init.data
+
+/**
+ * DOC: SECTION_INIT_RODATA
+ *
+ * Macro name used to annotate read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+#define SECTION_INIT_RODATA		.init.rodata
+
+/**
+ * DOC: SECTION_INIT_CALL
+ *
+ * Special macro name used to annotate subsystem init call. These calls are
+ * are now grouped by functionality into separate subsections. Ordering inside
+ * the subsections is determined by link order.
+ */
+#define SECTION_INIT_CALL		.initcall
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: SECTION_EXIT
+ *
+ * Macro name used to annotate code (functions) used only during module
+ * unload.
+ */
+#define SECTION_EXIT			.exit.text
+
+/**
+ * DOC: SECTION_EXIT_DATA
+ *
+ * Macro name used to annotate data structures used only during module
+ * unload.
+ */
+#define SECTION_EXIT_DATA		.exit.data
+
+/**
+ * DOC: SECTION_EXIT_CALL
+ *
+ * Special macro name used to annotate an exit exit routine, order
+ * is important and maintained by link order.
+ */
+#define SECTION_EXIT_CALL		.exitcall.exit
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: SECTION_REF
+ *
+ * Macro name used to annotate that code (functions) declared with this section
+ * has been vetteed as valid for its reference or use of other code (functions)
+ * or data structures which are part of the init sections.
+ */
+#define SECTION_REF			.ref.text
+
+/**
+ * DOC: SECTION_REF_DATA
+ *
+ * Macro name used to annotate data structures declared with this section have
+ * been vetteed for its reference or use of other code (functions) or data
+ * structures part of the init sections.
+ */
+#define SECTION_REF_DATA		.ref.data
+
+/**
+ * DOC: SECTION_REF_RODATA
+ *
+ * Macro name used to annotate const code (functions) const data structures
+ * which has been vetteed for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+#define SECTION_REF_RODATA		.ref.rodata
+
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections. Linux has used 'SORT()' in ``include/asm-generic/vmlinux.lds.h``
+ * for years.
+ */
+
+/**
+ * DOC: SECTION_ORDER_ANY
+ *
+ * Macro name which can be used as helper to annotate custom section
+ * ordering at link time is not relevant for specific sections.
+ */
+#define SECTION_ORDER_ANY	any
+
+/*
+ * These section _ALL() helpers are for use on linker scripts and helpers
+ */
+#define SECTION_ALL(__section)						\
+	__section##.*
+
+#define __SECTION_CORE(__section, __core, __name, __level)		\
+	__section.__core.__name.__level
+
+#define SECTION_CORE_ALL(__section, __core)				\
+	__section##.##__core##.*
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section.___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section.___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section.__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifdef LINKER_SCRIPT
+
+#  ifndef SECTION_CORE
+#   define SECTION_CORE(__section, __core, __name, __level)		\
+	__SECTION_CORE(__section,__core,__name,__level)
+#  endif
+
+# else
+
+#  ifndef SECTION_CORE
+#   define SECTION_CORE(__section, __core, __name, __level)		\
+	push_section_core(__section, __core, __name, __level,)
+#  endif
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+# ifndef SECTION_CORE
+#  define SECTION_CORE(__section, __core, __name, __level)		\
+	__stringify(__SECTION_CORE(__section,__core,__name,__level))
+# endif
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align=16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index af0254c09424..298252df3c81 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_GENERIC_SECTIONS_H_
 #define _ASM_GENERIC_SECTIONS_H_
 
+#include <asm/section-core.h>
+
 /* References to section boundaries */
 
 #include <linux/compiler.h>
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 24563970ff7b..731087276a32 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -55,6 +55,7 @@
 #endif
 
 #include <linux/export.h>
+#include <asm/section-core.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
@@ -198,8 +199,8 @@
 
 /* .data section */
 #define DATA_DATA							\
-	*(.data)							\
-	*(.ref.data)							\
+	*(SECTION_DATA)							\
+	*(SECTION_REF_DATA)						\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
 	MEM_KEEP(exit.data)						\
@@ -262,9 +263,9 @@
  */
 #define RO_DATA_SECTION(align)						\
 	. = ALIGN((align));						\
-	.rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {		\
+	SECTION_RODATA    : AT(ADDR(SECTION_RODATA) - LOAD_OFFSET) {	\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
-		*(.rodata) *(.rodata.*)					\
+		*(SECTION_RODATA) *(SECTION_ALL(SECTION_RODATA))	\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		*(__vermagic)		/* Kernel version magic */	\
 		. = ALIGN(8);						\
@@ -394,7 +395,7 @@
 									\
 	/* __*init sections */						\
 	__init_rodata : AT(ADDR(__init_rodata) - LOAD_OFFSET) {		\
-		*(.ref.rodata)						\
+		*(SECTION_REF_RODATA)					\
 		MEM_KEEP(init.rodata)					\
 		MEM_KEEP(exit.rodata)					\
 	}								\
@@ -432,8 +433,8 @@
  * during second ld run in second ld pass when generating System.map */
 #define TEXT_TEXT							\
 		ALIGN_FUNCTION();					\
-		*(.text.hot .text .text.fixup .text.unlikely)		\
-		*(.ref.text)						\
+		*(.text.hot SECTION_TEXT .text.fixup .text.unlikely)	\
+		*(SECTION_REF)						\
 	MEM_KEEP(init.text)						\
 	MEM_KEEP(exit.text)						\
 
@@ -527,11 +528,11 @@
 
 /* init and exit section handling */
 #define INIT_DATA							\
-	*(.init.data)							\
+	*(SECTION_INIT_DATA)						\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
-	*(.init.rodata)							\
+	*(SECTION_INIT_RODATA)						\
 	FTRACE_EVENTS()							\
 	TRACE_SYSCALLS()						\
 	KPROBE_BLACKLIST()						\
@@ -549,24 +550,24 @@
 	EARLYCON_TABLE()
 
 #define INIT_TEXT							\
-	*(.init.text)							\
+	*(SECTION_INIT)							\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
 #define EXIT_DATA							\
-	*(.exit.data)							\
+	*(SECTION_EXIT_DATA)						\
 	*(.fini_array)							\
 	*(.dtors)							\
 	MEM_DISCARD(exit.data)						\
 	MEM_DISCARD(exit.rodata)
 
 #define EXIT_TEXT							\
-	*(.exit.text)							\
+	*(SECTION_EXIT)							\
 	*(.text.exit)							\
 	MEM_DISCARD(exit.text)
 
 #define EXIT_CALL							\
-	*(.exitcall.exit)
+	*(SECTION_EXIT_CALL)
 
 /*
  * bss (Block Started by Symbol) - uninitialized data
diff --git a/include/linux/sections.h b/include/linux/sections.h
new file mode 100644
index 000000000000..f21c6ee88ded
--- /dev/null
+++ b/include/linux/sections.h
@@ -0,0 +1,111 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_SIZE - get number of entries in the section
+ *
+ * @name: section name
+ *
+ * This gives you the number of entries in the section.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINUX_SECTION_SIZE(frobnicator_fns);
+ */
+#define LINUX_SECTION_SIZE(name)					\
+	((VMLINUX_SYMBOL(name##__end)) - (VMLINUX_SYMBOL(name)))
+
+/**
+ * LINUX_SECTION_EMPTY - check if section has no entries
+ *
+ * @name: section name
+ *
+ * Returns true if section is emtpy.
+ *
+ *   bool is_empty = LINUX_SECTION_EMPTY(frobnicator_fns);
+ */
+#define LINUX_SECTION_EMPTY(name)	(LINUX_SECTION_SIZE(name) == 0)
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_TYPE(section, type, name, level)			\
+	#section "." #type "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 05/16] xtensa: skip adding literal when SORT() is used
  2016-08-19 21:33   ` mcgrof
  (?)
@ 2016-08-19 21:34     ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

When SORT(foo.*) is used the current sed replacements add
SORT(foo.literal foo.*), this breaks linking. Avoid adding
literals for SORT globs, if needed, these need to be added
manually.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/xtensa/kernel/Makefile | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index c31f5d5afc7d..8180850ed147 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -29,10 +29,10 @@ AFLAGS_mxhead.o += -mtext-section-literals
 #
 # Replicate rules in scripts/Makefile.build
 
-sed-y = -e ':a; s/\*(\([^)]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
-	-e ':b; s/\*(\([^)]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
-	-e ':c; s/\*(\([^)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
-	-e ':d; s/\*(\([^)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
+sed-y = -e ':a; s/\*(\([^)SORT]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
+	-e ':b; s/\*(\([^)SORT]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
+	-e ':c; s/\*(\([^SORT)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
+	-e ':d; s/\*(\([^SORT)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
 	-e 's/\.{text}/.text/g'
 
 quiet_cmd__cpp_lds_S = LDS     $@
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 05/16] xtensa: skip adding literal when SORT() is used
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

When SORT(foo.*) is used the current sed replacements add
SORT(foo.literal foo.*), this breaks linking. Avoid adding
literals for SORT globs, if needed, these need to be added
manually.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/xtensa/kernel/Makefile | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index c31f5d5afc7d..8180850ed147 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -29,10 +29,10 @@ AFLAGS_mxhead.o += -mtext-section-literals
 #
 # Replicate rules in scripts/Makefile.build
 
-sed-y = -e ':a; s/\*(\([^)]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
-	-e ':b; s/\*(\([^)]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
-	-e ':c; s/\*(\([^)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
-	-e ':d; s/\*(\([^)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
+sed-y = -e ':a; s/\*(\([^)SORT]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
+	-e ':b; s/\*(\([^)SORT]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
+	-e ':c; s/\*(\([^SORT)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
+	-e ':d; s/\*(\([^SORT)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
 	-e 's/\.{text}/.text/g'
 
 quiet_cmd__cpp_lds_S = LDS     $@
-- 
2.9.2


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 05/16] xtensa: skip adding literal when SORT() is used
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

When SORT(foo.*) is used the current sed replacements add
SORT(foo.literal foo.*), this breaks linking. Avoid adding
literals for SORT globs, if needed, these need to be added
manually.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/xtensa/kernel/Makefile | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index c31f5d5afc7d..8180850ed147 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -29,10 +29,10 @@ AFLAGS_mxhead.o += -mtext-section-literals
 #
 # Replicate rules in scripts/Makefile.build
 
-sed-y = -e ':a; s/\*(\([^)]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
-	-e ':b; s/\*(\([^)]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
-	-e ':c; s/\*(\([^)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
-	-e ':d; s/\*(\([^)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
+sed-y = -e ':a; s/\*(\([^)SORT]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
+	-e ':b; s/\*(\([^)SORT]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
+	-e ':c; s/\*(\([^SORT)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
+	-e ':d; s/\*(\([^SORT)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
 	-e 's/\.{text}/.text/g'
 
 quiet_cmd__cpp_lds_S = LDS     $@
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 06/16] ranges.h: add helpers to build and identify Linux section ranges
  2016-08-19 21:33   ` mcgrof
  (?)
@ 2016-08-19 21:34     ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Section ranges are on one of the types of custom sections
types used in Linux. This provides a series of helpers for
defining them and using them. Most importantly this also
enables us to avoid modifying the linker script when we
add a new section range.

It turns out a lot of custom sections are actually section ranges,
and these are typically spelled out in their architecture specific
asm/sections.h file -- we anable architectures to override what asm
is used for section ranges but start by default trusting the
asm-generic version all around.

v4:

o tons of documentation love
o fix arch/x86/tools/relocs.c typo - which caused compilation issues
  on old toolchains
o port to new shiny sphinx documentation
o sprinkle a few more needed VMLINUX_SYMBOL() - fixes
  compilation on blackfin
o name changes as suggested 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
- rebrand DECLARE_SECTION_RNG() as DEFINE_SECTION_RANGE() - this is
  the asm version of the respective C version, this will have a
  userspace C demo added later.
o move __LINUX_RANGE() and __LINUX_RANGE_ORDER() - fixes builds
  on sparc
o adds section ranges to linker script
o rename SECTION_RANGE_ALL()
o use default alignment, fixes builds on powerpc and arm for both
  __LINUX_RANGE() and __LINUX_RANGE_ORDER()
o expand documentation to document modules support
o add maintainers
o use generic-y

v3: new in this series, uses copyleft-next

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst   |   1 +
 Documentation/sections/ranges.rst  |  49 ++++++++++++++
 MAINTAINERS                        |  10 +++
 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/Kbuild        |   1 +
 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       |  89 ++++++++++++++++++++++++++
 include/asm-generic/vmlinux.lds.h  |  12 +++-
 include/linux/ranges.h             | 128 +++++++++++++++++++++++++++++++++++++
 38 files changed, 320 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/linux/ranges.h

diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
index d411e9b22eb3..6dd93ddd5dbe 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -9,3 +9,4 @@ used throughout the kernel to help declare and define them.
    :maxdepth: 4
 
    section-core
+   ranges
diff --git a/Documentation/sections/ranges.rst b/Documentation/sections/ranges.rst
new file mode 100644
index 000000000000..1293dcb3ab38
--- /dev/null
+++ b/Documentation/sections/ranges.rst
@@ -0,0 +1,49 @@
+==========
+Linux section ranges
+==========
+
+This documents Linux' use of section ranges, how you can use
+them and how they work.
+
+About section ranges
+==========
+
+Introduction
+------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Introduction
+
+Section range module support
+----------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range module support
+
+Section range helpers
+==========+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range helpers
+
+DECLARE_SECTION_RANGE
+---------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DECLARE_SECTION_RANGE
+
+DEFINE_SECTION_RANGE
+--------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DEFINE_SECTION_RANGE
+
+SECTION_ADDR_IN_RANGE
+---------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_ADDR_IN_RANGE
+
+__LINUX_RANGE
+-------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE
+
+__LINUX_RANGE_ORDER
+-------------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE_ORDER
diff --git a/MAINTAINERS b/MAINTAINERS
index 689c12075842..1a217751aa8a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5217,6 +5217,16 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTION RANGES
+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
+S:	Supported
+F:	include/asm-generic/ranges.h
+F:	include/linux/ranges.h
+F:	Documentation/sections/ranges.rst
+
 GENERIC SECTIONS
 M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
 M:	Josh Poimboeuf <jpoimboe@redhat.com>
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index 5422827f1585..e44c896b91c4 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 9a0929576de1..e5295413fdf8 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 47923635be16..8e52300e1eed 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += timex.h
 generic-y += trace_clock.h
 generic-y += unaligned.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 42d00806e4fb..5ff184574976 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -53,3 +53,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index f2c3b656a0e7..edc176348d7c 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -23,3 +23,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 7de674411bed..35b7752e65c0 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -49,3 +49,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 38127ce747be..cede2a950fbf 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 385cd88a9d9e..fb8bb4112773 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 46d7c599d9b8..5191fec655d7 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 1ec04ec1c82b..7929a992566c 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -76,3 +76,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index 37d7bfae7619..af17ee334788 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 672c6d5da18c..d8f226b35a0a 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 6111e1523750..1c6504d29312 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index eef72c464c9b..d465f51c2088 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -36,3 +36,4 @@ generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 50ebd5a30d16..c869b1ebd583 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -57,3 +57,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index c6c2cf6edc98..63c083a1f8da 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 12f7c5984c03..ed225600c8a4 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index f8145bc85835..656af7b69940 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index c9c7cb82b00f..c55880659d67 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 86175e701869..7d6a704b808c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -72,3 +72,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 6f43f33f0e0f..1a263a7158e2 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -30,3 +30,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index b49fab7bab2f..065c6e84fb67 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 89e74b59f32d..3e8b95927cb5 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index f089a264cd38..f0cdb2cbca4d 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -15,3 +15,4 @@ generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 7b0356dca562..c9bb7932a3d1 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index d51b84d6b4b7..79664d10e63b 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -23,3 +23,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 7b8a652e43ae..951fa4be571d 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -42,3 +42,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index e9849834d55e..99be54949b99 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -28,3 +28,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 256c45b3ae34..6c35905fe371 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += ranges.h
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index f6914a57bc16..f790756fdb48 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -17,3 +17,4 @@ generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index 0c2fae8d929d..c215db049920 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -68,6 +68,8 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
 	"__end_rodata|"
 	"__initramfs_start|"
 	"(jiffies|jiffies_64)|"
+	".rodata.rng.*|"
+	".init.text.rng.*|"
 #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 81ca6816bd72..221b6b652500 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/include/asm-generic/ranges.h b/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..74cd941aa2f8
--- /dev/null
+++ b/include/asm-generic/ranges.h
@@ -0,0 +1,89 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#define SECTION_RNG(section, name)					\
+	SECTION_CORE(section, rng, name,				\
+		     SECTION_ORDER_ANY)
+
+#define SECTION_RNG_LEVEL(section, name, level)				\
+	SECTION_CORE(section, rng, name, level)
+
+#define SECTION_RNG_ALL(section)					\
+	SECTION_CORE_ALL(section,rng)
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  SECTION_ORDER_ANY, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       SECTION_ORDER_ANY, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   SECTION_ORDER_ANY, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(SECTION_RNG(section, name))))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using
+ * 	binutils SORT(), the number is sorted as a string, as such be
+ * 	sure to fill with zeroes any empty digits. For instance if you are
+ * 	using 3 levels of digits for order levels, use 001 for the first entry,
+ * 	0002 for the second, 999 for the last entry. You can use however many
+ * 	digits you need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(SECTION_RNG_LEVEL(section, name, level))))
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_GENERIC_RANGES_H_ */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 731087276a32..ad843555e6a4 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -56,6 +56,7 @@
 
 #include <linux/export.h>
 #include <asm/section-core.h>
+#include <asm/ranges.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
@@ -200,6 +201,7 @@
 /* .data section */
 #define DATA_DATA							\
 	*(SECTION_DATA)							\
+	*(SORT(SECTION_RNG_ALL(SECTION_DATA)))				\
 	*(SECTION_REF_DATA)						\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -265,7 +267,9 @@
 	. = ALIGN((align));						\
 	SECTION_RODATA    : AT(ADDR(SECTION_RODATA) - LOAD_OFFSET) {	\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
-		*(SECTION_RODATA) *(SECTION_ALL(SECTION_RODATA))	\
+		*(SECTION_RODATA)					\
+		*(SORT(SECTION_RNG_ALL(SECTION_RODATA)))		\
+		*(SECTION_ALL(SECTION_RODATA))				\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		*(__vermagic)		/* Kernel version magic */	\
 		. = ALIGN(8);						\
@@ -433,7 +437,9 @@
  * during second ld run in second ld pass when generating System.map */
 #define TEXT_TEXT							\
 		ALIGN_FUNCTION();					\
-		*(.text.hot SECTION_TEXT .text.fixup .text.unlikely)	\
+		*(.text.hot SECTION_TEXT)				\
+		*(SORT(SECTION_RNG_ALL(SECTION_TEXT)))			\
+		*(.text.fixup .text.unlikely)				\
 		*(SECTION_REF)						\
 	MEM_KEEP(init.text)						\
 	MEM_KEEP(exit.text)						\
@@ -529,6 +535,7 @@
 /* init and exit section handling */
 #define INIT_DATA							\
 	*(SECTION_INIT_DATA)						\
+	*(SORT(SECTION_RNG_ALL(SECTION_INIT_DATA)))			\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -551,6 +558,7 @@
 
 #define INIT_TEXT							\
 	*(SECTION_INIT)							\
+	*(SORT(SECTION_RNG_ALL(SECTION_INIT)))				\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/ranges.h b/include/linux/ranges.h
new file mode 100644
index 000000000000..30b2182bd484
--- /dev/null
+++ b/include/linux/ranges.h
@@ -0,0 +1,128 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(VMLINUX_SYMBOL(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+			     section(SECTION_RNG_LEVEL(__section, name,))))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(VMLINUX_SYMBOL(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+			     section(SECTION_RNG_LEVEL(__section, name, ~))))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) VMLINUX_SYMBOL(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) VMLINUX_SYMBOL(name##__end)[0] = {}
+
+/**
+ * SECTION_ADDR_IN_RANGE - returns true if address is in range
+ *
+ * @name: section range name
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_ADDR_IN_RANGE(name, addr)				\
+	 (addr >= (unsigned long) LINUX_SECTION_START(name) &&		\
+	  addr <  (unsigned long) LINUX_SECTION_END(name))
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 06/16] ranges.h: add helpers to build and identify Linux section ranges
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, mchehab, linux-arch, markus.heiser, xen-devel,
	msalter, linux-sh, mpe, x86, fontana, linux-arm-kernel,
	catalin.marinas, dvhart, dwmw2, linux-xtensa, pali.rohar,
	keescook, arnd, jani.nikula, will.deacon, rusty, rostedt, acme,
	ak, andriy.shevchenko, mcb30

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Section ranges are on one of the types of custom sections
types used in Linux. This provides a series of helpers for
defining them and using them. Most importantly this also
enables us to avoid modifying the linker script when we
add a new section range.

It turns out a lot of custom sections are actually section ranges,
and these are typically spelled out in their architecture specific
asm/sections.h file -- we anable architectures to override what asm
is used for section ranges but start by default trusting the
asm-generic version all around.

v4:

o tons of documentation love
o fix arch/x86/tools/relocs.c typo - which caused compilation issues
  on old toolchains
o port to new shiny sphinx documentation
o sprinkle a few more needed VMLINUX_SYMBOL() - fixes
  compilation on blackfin
o name changes as suggested 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
- rebrand DECLARE_SECTION_RNG() as DEFINE_SECTION_RANGE() - this is
  the asm version of the respective C version, this will have a
  userspace C demo added later.
o move __LINUX_RANGE() and __LINUX_RANGE_ORDER() - fixes builds
  on sparc
o adds section ranges to linker script
o rename SECTION_RANGE_ALL()
o use default alignment, fixes builds on powerpc and arm for both
  __LINUX_RANGE() and __LINUX_RANGE_ORDER()
o expand documentation to document modules support
o add maintainers
o use generic-y

v3: new in this series, uses copyleft-next

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst   |   1 +
 Documentation/sections/ranges.rst  |  49 ++++++++++++++
 MAINTAINERS                        |  10 +++
 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/Kbuild        |   1 +
 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       |  89 ++++++++++++++++++++++++++
 include/asm-generic/vmlinux.lds.h  |  12 +++-
 include/linux/ranges.h             | 128 +++++++++++++++++++++++++++++++++++++
 38 files changed, 320 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/linux/ranges.h

diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
index d411e9b22eb3..6dd93ddd5dbe 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -9,3 +9,4 @@ used throughout the kernel to help declare and define them.
    :maxdepth: 4
 
    section-core
+   ranges
diff --git a/Documentation/sections/ranges.rst b/Documentation/sections/ranges.rst
new file mode 100644
index 000000000000..1293dcb3ab38
--- /dev/null
+++ b/Documentation/sections/ranges.rst
@@ -0,0 +1,49 @@
+====================
+Linux section ranges
+====================
+
+This documents Linux' use of section ranges, how you can use
+them and how they work.
+
+About section ranges
+====================
+
+Introduction
+------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Introduction
+
+Section range module support
+----------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range module support
+
+Section range helpers
+=====================
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range helpers
+
+DECLARE_SECTION_RANGE
+---------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DECLARE_SECTION_RANGE
+
+DEFINE_SECTION_RANGE
+--------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DEFINE_SECTION_RANGE
+
+SECTION_ADDR_IN_RANGE
+---------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_ADDR_IN_RANGE
+
+__LINUX_RANGE
+-------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE
+
+__LINUX_RANGE_ORDER
+-------------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE_ORDER
diff --git a/MAINTAINERS b/MAINTAINERS
index 689c12075842..1a217751aa8a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5217,6 +5217,16 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTION RANGES
+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
+S:	Supported
+F:	include/asm-generic/ranges.h
+F:	include/linux/ranges.h
+F:	Documentation/sections/ranges.rst
+
 GENERIC SECTIONS
 M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
 M:	Josh Poimboeuf <jpoimboe@redhat.com>
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index 5422827f1585..e44c896b91c4 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 9a0929576de1..e5295413fdf8 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 47923635be16..8e52300e1eed 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += timex.h
 generic-y += trace_clock.h
 generic-y += unaligned.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 42d00806e4fb..5ff184574976 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -53,3 +53,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index f2c3b656a0e7..edc176348d7c 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -23,3 +23,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 7de674411bed..35b7752e65c0 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -49,3 +49,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 38127ce747be..cede2a950fbf 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 385cd88a9d9e..fb8bb4112773 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 46d7c599d9b8..5191fec655d7 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 1ec04ec1c82b..7929a992566c 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -76,3 +76,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index 37d7bfae7619..af17ee334788 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 672c6d5da18c..d8f226b35a0a 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 6111e1523750..1c6504d29312 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index eef72c464c9b..d465f51c2088 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -36,3 +36,4 @@ generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 50ebd5a30d16..c869b1ebd583 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -57,3 +57,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index c6c2cf6edc98..63c083a1f8da 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 12f7c5984c03..ed225600c8a4 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index f8145bc85835..656af7b69940 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index c9c7cb82b00f..c55880659d67 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 86175e701869..7d6a704b808c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -72,3 +72,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 6f43f33f0e0f..1a263a7158e2 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -30,3 +30,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index b49fab7bab2f..065c6e84fb67 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 89e74b59f32d..3e8b95927cb5 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index f089a264cd38..f0cdb2cbca4d 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -15,3 +15,4 @@ generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 7b0356dca562..c9bb7932a3d1 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index d51b84d6b4b7..79664d10e63b 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -23,3 +23,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 7b8a652e43ae..951fa4be571d 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -42,3 +42,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index e9849834d55e..99be54949b99 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -28,3 +28,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 256c45b3ae34..6c35905fe371 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += ranges.h
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index f6914a57bc16..f790756fdb48 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -17,3 +17,4 @@ generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index 0c2fae8d929d..c215db049920 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -68,6 +68,8 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
 	"__end_rodata|"
 	"__initramfs_start|"
 	"(jiffies|jiffies_64)|"
+	".rodata.rng.*|"
+	".init.text.rng.*|"
 #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 81ca6816bd72..221b6b652500 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/include/asm-generic/ranges.h b/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..74cd941aa2f8
--- /dev/null
+++ b/include/asm-generic/ranges.h
@@ -0,0 +1,89 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#define SECTION_RNG(section, name)					\
+	SECTION_CORE(section, rng, name,				\
+		     SECTION_ORDER_ANY)
+
+#define SECTION_RNG_LEVEL(section, name, level)				\
+	SECTION_CORE(section, rng, name, level)
+
+#define SECTION_RNG_ALL(section)					\
+	SECTION_CORE_ALL(section,rng)
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  SECTION_ORDER_ANY, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       SECTION_ORDER_ANY, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   SECTION_ORDER_ANY, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(SECTION_RNG(section, name))))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using
+ * 	binutils SORT(), the number is sorted as a string, as such be
+ * 	sure to fill with zeroes any empty digits. For instance if you are
+ * 	using 3 levels of digits for order levels, use 001 for the first entry,
+ * 	0002 for the second, 999 for the last entry. You can use however many
+ * 	digits you need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(SECTION_RNG_LEVEL(section, name, level))))
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_GENERIC_RANGES_H_ */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 731087276a32..ad843555e6a4 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -56,6 +56,7 @@
 
 #include <linux/export.h>
 #include <asm/section-core.h>
+#include <asm/ranges.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
@@ -200,6 +201,7 @@
 /* .data section */
 #define DATA_DATA							\
 	*(SECTION_DATA)							\
+	*(SORT(SECTION_RNG_ALL(SECTION_DATA)))				\
 	*(SECTION_REF_DATA)						\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -265,7 +267,9 @@
 	. = ALIGN((align));						\
 	SECTION_RODATA    : AT(ADDR(SECTION_RODATA) - LOAD_OFFSET) {	\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
-		*(SECTION_RODATA) *(SECTION_ALL(SECTION_RODATA))	\
+		*(SECTION_RODATA)					\
+		*(SORT(SECTION_RNG_ALL(SECTION_RODATA)))		\
+		*(SECTION_ALL(SECTION_RODATA))				\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		*(__vermagic)		/* Kernel version magic */	\
 		. = ALIGN(8);						\
@@ -433,7 +437,9 @@
  * during second ld run in second ld pass when generating System.map */
 #define TEXT_TEXT							\
 		ALIGN_FUNCTION();					\
-		*(.text.hot SECTION_TEXT .text.fixup .text.unlikely)	\
+		*(.text.hot SECTION_TEXT)				\
+		*(SORT(SECTION_RNG_ALL(SECTION_TEXT)))			\
+		*(.text.fixup .text.unlikely)				\
 		*(SECTION_REF)						\
 	MEM_KEEP(init.text)						\
 	MEM_KEEP(exit.text)						\
@@ -529,6 +535,7 @@
 /* init and exit section handling */
 #define INIT_DATA							\
 	*(SECTION_INIT_DATA)						\
+	*(SORT(SECTION_RNG_ALL(SECTION_INIT_DATA)))			\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -551,6 +558,7 @@
 
 #define INIT_TEXT							\
 	*(SECTION_INIT)							\
+	*(SORT(SECTION_RNG_ALL(SECTION_INIT)))				\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/ranges.h b/include/linux/ranges.h
new file mode 100644
index 000000000000..30b2182bd484
--- /dev/null
+++ b/include/linux/ranges.h
@@ -0,0 +1,128 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(VMLINUX_SYMBOL(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+			     section(SECTION_RNG_LEVEL(__section, name,))))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(VMLINUX_SYMBOL(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+			     section(SECTION_RNG_LEVEL(__section, name, ~))))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) VMLINUX_SYMBOL(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) VMLINUX_SYMBOL(name##__end)[0] = {}
+
+/**
+ * SECTION_ADDR_IN_RANGE - returns true if address is in range
+ *
+ * @name: section range name
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_ADDR_IN_RANGE(name, addr)				\
+	 (addr >= (unsigned long) LINUX_SECTION_START(name) &&		\
+	  addr <  (unsigned long) LINUX_SECTION_END(name))
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
-- 
2.9.2


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 06/16] ranges.h: add helpers to build and identify Linux section ranges
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Section ranges are on one of the types of custom sections
types used in Linux. This provides a series of helpers for
defining them and using them. Most importantly this also
enables us to avoid modifying the linker script when we
add a new section range.

It turns out a lot of custom sections are actually section ranges,
and these are typically spelled out in their architecture specific
asm/sections.h file -- we anable architectures to override what asm
is used for section ranges but start by default trusting the
asm-generic version all around.

v4:

o tons of documentation love
o fix arch/x86/tools/relocs.c typo - which caused compilation issues
  on old toolchains
o port to new shiny sphinx documentation
o sprinkle a few more needed VMLINUX_SYMBOL() - fixes
  compilation on blackfin
o name changes as suggested 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
- rebrand DECLARE_SECTION_RNG() as DEFINE_SECTION_RANGE() - this is
  the asm version of the respective C version, this will have a
  userspace C demo added later.
o move __LINUX_RANGE() and __LINUX_RANGE_ORDER() - fixes builds
  on sparc
o adds section ranges to linker script
o rename SECTION_RANGE_ALL()
o use default alignment, fixes builds on powerpc and arm for both
  __LINUX_RANGE() and __LINUX_RANGE_ORDER()
o expand documentation to document modules support
o add maintainers
o use generic-y

v3: new in this series, uses copyleft-next

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst   |   1 +
 Documentation/sections/ranges.rst  |  49 ++++++++++++++
 MAINTAINERS                        |  10 +++
 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/Kbuild        |   1 +
 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       |  89 ++++++++++++++++++++++++++
 include/asm-generic/vmlinux.lds.h  |  12 +++-
 include/linux/ranges.h             | 128 +++++++++++++++++++++++++++++++++++++
 38 files changed, 320 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/linux/ranges.h

diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
index d411e9b22eb3..6dd93ddd5dbe 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -9,3 +9,4 @@ used throughout the kernel to help declare and define them.
    :maxdepth: 4
 
    section-core
+   ranges
diff --git a/Documentation/sections/ranges.rst b/Documentation/sections/ranges.rst
new file mode 100644
index 000000000000..1293dcb3ab38
--- /dev/null
+++ b/Documentation/sections/ranges.rst
@@ -0,0 +1,49 @@
+====================
+Linux section ranges
+====================
+
+This documents Linux' use of section ranges, how you can use
+them and how they work.
+
+About section ranges
+====================
+
+Introduction
+------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Introduction
+
+Section range module support
+----------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range module support
+
+Section range helpers
+=====================
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range helpers
+
+DECLARE_SECTION_RANGE
+---------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DECLARE_SECTION_RANGE
+
+DEFINE_SECTION_RANGE
+--------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DEFINE_SECTION_RANGE
+
+SECTION_ADDR_IN_RANGE
+---------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_ADDR_IN_RANGE
+
+__LINUX_RANGE
+-------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE
+
+__LINUX_RANGE_ORDER
+-------------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE_ORDER
diff --git a/MAINTAINERS b/MAINTAINERS
index 689c12075842..1a217751aa8a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5217,6 +5217,16 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTION RANGES
+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
+S:	Supported
+F:	include/asm-generic/ranges.h
+F:	include/linux/ranges.h
+F:	Documentation/sections/ranges.rst
+
 GENERIC SECTIONS
 M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
 M:	Josh Poimboeuf <jpoimboe@redhat.com>
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index 5422827f1585..e44c896b91c4 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 9a0929576de1..e5295413fdf8 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 47923635be16..8e52300e1eed 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += timex.h
 generic-y += trace_clock.h
 generic-y += unaligned.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 42d00806e4fb..5ff184574976 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -53,3 +53,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index f2c3b656a0e7..edc176348d7c 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -23,3 +23,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 7de674411bed..35b7752e65c0 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -49,3 +49,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 38127ce747be..cede2a950fbf 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 385cd88a9d9e..fb8bb4112773 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 46d7c599d9b8..5191fec655d7 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 1ec04ec1c82b..7929a992566c 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -76,3 +76,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index 37d7bfae7619..af17ee334788 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 672c6d5da18c..d8f226b35a0a 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 6111e1523750..1c6504d29312 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index eef72c464c9b..d465f51c2088 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -36,3 +36,4 @@ generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 50ebd5a30d16..c869b1ebd583 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -57,3 +57,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index c6c2cf6edc98..63c083a1f8da 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 12f7c5984c03..ed225600c8a4 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index f8145bc85835..656af7b69940 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index c9c7cb82b00f..c55880659d67 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 86175e701869..7d6a704b808c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -72,3 +72,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 6f43f33f0e0f..1a263a7158e2 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -30,3 +30,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index b49fab7bab2f..065c6e84fb67 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 89e74b59f32d..3e8b95927cb5 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index f089a264cd38..f0cdb2cbca4d 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -15,3 +15,4 @@ generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 7b0356dca562..c9bb7932a3d1 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index d51b84d6b4b7..79664d10e63b 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -23,3 +23,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 7b8a652e43ae..951fa4be571d 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -42,3 +42,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index e9849834d55e..99be54949b99 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -28,3 +28,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 256c45b3ae34..6c35905fe371 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += ranges.h
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index f6914a57bc16..f790756fdb48 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -17,3 +17,4 @@ generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index 0c2fae8d929d..c215db049920 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -68,6 +68,8 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
 	"__end_rodata|"
 	"__initramfs_start|"
 	"(jiffies|jiffies_64)|"
+	".rodata.rng.*|"
+	".init.text.rng.*|"
 #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 81ca6816bd72..221b6b652500 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/include/asm-generic/ranges.h b/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..74cd941aa2f8
--- /dev/null
+++ b/include/asm-generic/ranges.h
@@ -0,0 +1,89 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#define SECTION_RNG(section, name)					\
+	SECTION_CORE(section, rng, name,				\
+		     SECTION_ORDER_ANY)
+
+#define SECTION_RNG_LEVEL(section, name, level)				\
+	SECTION_CORE(section, rng, name, level)
+
+#define SECTION_RNG_ALL(section)					\
+	SECTION_CORE_ALL(section,rng)
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  SECTION_ORDER_ANY, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       SECTION_ORDER_ANY, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   SECTION_ORDER_ANY, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(SECTION_RNG(section, name))))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using
+ * 	binutils SORT(), the number is sorted as a string, as such be
+ * 	sure to fill with zeroes any empty digits. For instance if you are
+ * 	using 3 levels of digits for order levels, use 001 for the first entry,
+ * 	0002 for the second, 999 for the last entry. You can use however many
+ * 	digits you need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(SECTION_RNG_LEVEL(section, name, level))))
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_GENERIC_RANGES_H_ */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 731087276a32..ad843555e6a4 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -56,6 +56,7 @@
 
 #include <linux/export.h>
 #include <asm/section-core.h>
+#include <asm/ranges.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
@@ -200,6 +201,7 @@
 /* .data section */
 #define DATA_DATA							\
 	*(SECTION_DATA)							\
+	*(SORT(SECTION_RNG_ALL(SECTION_DATA)))				\
 	*(SECTION_REF_DATA)						\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -265,7 +267,9 @@
 	. = ALIGN((align));						\
 	SECTION_RODATA    : AT(ADDR(SECTION_RODATA) - LOAD_OFFSET) {	\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
-		*(SECTION_RODATA) *(SECTION_ALL(SECTION_RODATA))	\
+		*(SECTION_RODATA)					\
+		*(SORT(SECTION_RNG_ALL(SECTION_RODATA)))		\
+		*(SECTION_ALL(SECTION_RODATA))				\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		*(__vermagic)		/* Kernel version magic */	\
 		. = ALIGN(8);						\
@@ -433,7 +437,9 @@
  * during second ld run in second ld pass when generating System.map */
 #define TEXT_TEXT							\
 		ALIGN_FUNCTION();					\
-		*(.text.hot SECTION_TEXT .text.fixup .text.unlikely)	\
+		*(.text.hot SECTION_TEXT)				\
+		*(SORT(SECTION_RNG_ALL(SECTION_TEXT)))			\
+		*(.text.fixup .text.unlikely)				\
 		*(SECTION_REF)						\
 	MEM_KEEP(init.text)						\
 	MEM_KEEP(exit.text)						\
@@ -529,6 +535,7 @@
 /* init and exit section handling */
 #define INIT_DATA							\
 	*(SECTION_INIT_DATA)						\
+	*(SORT(SECTION_RNG_ALL(SECTION_INIT_DATA)))			\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -551,6 +558,7 @@
 
 #define INIT_TEXT							\
 	*(SECTION_INIT)							\
+	*(SORT(SECTION_RNG_ALL(SECTION_INIT)))				\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/ranges.h b/include/linux/ranges.h
new file mode 100644
index 000000000000..30b2182bd484
--- /dev/null
+++ b/include/linux/ranges.h
@@ -0,0 +1,128 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(VMLINUX_SYMBOL(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+			     section(SECTION_RNG_LEVEL(__section, name,))))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(VMLINUX_SYMBOL(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+			     section(SECTION_RNG_LEVEL(__section, name, ~))))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) VMLINUX_SYMBOL(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) VMLINUX_SYMBOL(name##__end)[0] = {}
+
+/**
+ * SECTION_ADDR_IN_RANGE - returns true if address is in range
+ *
+ * @name: section range name
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_ADDR_IN_RANGE(name, addr)				\
+	 (addr >= (unsigned long) LINUX_SECTION_START(name) &&		\
+	  addr <  (unsigned long) LINUX_SECTION_END(name))
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 07/16] tables.h: add linker table support
  2016-08-19 21:33   ` mcgrof
  (?)
@ 2016-08-19 21:34     ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

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@ipxe.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 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@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
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@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 */
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@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_ */
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@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 */
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


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 07/16] tables.h: add linker table support
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

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@ipxe.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 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@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
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@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 */
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@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_ */
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@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 */
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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 07/16] tables.h: add linker table support
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

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@ipxe.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 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@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
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@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 */
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@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_ */
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@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 */
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


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 08/16] kbuild: enable option to force compile force-obj-y and force-lib-y
  2016-08-19 21:33   ` mcgrof
  (?)
@ 2016-08-19 21:34     ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Linux provides a rich array of features, enabling each feature
however increases the size of the kernel and there are many
features which users often want disabled. The traditional
solution to this problem is for each feature to have its own
Kconfig symbol, followed by a series of #ifdef statements
in C code and header files, allowing the feature to be compiled
only when desirable. As the variability of Linux increases build
tests can and are often done with random kernel configurations,
allyesconfig, and allmodconfig to help find code issues. This
however doesn't catch all errors and as a consequence code that
is typically not enabled often can suffer from bit-rot over time.

An alternative approach for subsystems, which refer to as the 'build-all
link-selectively philosophy' is to keep the Kconfig symbols, replace
the #ifdef approach by having each feature implemented it its own C file,
and force compilation for all features to avoid the code bit-rot problem.
With this strategy only features that are enabled via Kconfig get
linked into the kernel, so the forced compilation has no size impact
on the kernel. The practice of having each feature implemented in its own
C file is already prevalent in many subsystems, however #ifdefs are still
typically required during feature initialization. For instance in:

  #ifdef CONFIG_FOO
  foo_init();
  #endif

We cannot remove the #ifdef and leave foo_init() as we'd either
need to always enable the feature or add a respective #ifdef in a
foo.h which makes foo_init() do nothing when CONFIG_FOO is disabled.

Linker tables enable lifting the requirement to use of #ifdefs during
initialization. With linker tables initialization sequences can instead
be aggregated into a custom ELF section at link time, during run time
the table can be iterated over and each init sequence enabled can be called.
A feature's init routine is only added to a table when its respective
Kconfig symbols has been enabled and therefore linked in. Linker tables
enable subsystems to completely do away with #ifdefs if one is comfortable
in accepting all subsystem's feature's structural size implications.

Subsystems which want to follow the 'build-all link-selectively
philosophy' still need a way to easily express and annotate that they
wish for all code to always be compiled to help avoid code bit rot,
as such two new targets force-obj-y and force-lib-y are provided to
help with this. Its not fair to require everyone to force compilation
of all features of a subsystem though, so as a compromise, the new
targets only force compilation when CONFIG_BUILD_AVOID_BITROT is
enabled.

Only built-in features are supported at the moment. Module support
is expected to be added after a generic solution to add linker
tables to modules more easily is developed.

v4: this patch was added to this series, it was split off from the
    linker tables addition due to the confusion over the code bit
    rot alternatives that are possible with linker tables.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/kbuild/makefiles.txt       | 36 ++++++++++++++++
 Documentation/sections/linker-tables.rst | 15 +++++++
 include/linux/tables.h                   | 71 ++++++++++++++++++++++++++++++++
 init/Kconfig                             | 22 ++++++++++
 scripts/Makefile.build                   |  7 ++--
 scripts/Makefile.lib                     | 11 +++++
 6 files changed, 159 insertions(+), 3 deletions(-)

diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 385a5ef41c17..01c260913f5c 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -1089,6 +1089,42 @@ When kbuild executes, the following steps are followed (roughly):
 	In this example, extra-y is used to list object files that
 	shall be built, but shall not be linked as part of built-in.o.
 
+    force-obj-y force-lib-y
+
+	When CONFIG_BUILD_AVOID_BITROT is enabled using these targets for your
+	kconfig symbols forces compilation of the associated objects if the
+	kconfig's symbol's dependencies are met, the objects however are only
+	linked into to the kernel if and only if the kconfig symbol was
+	enabled. If CONFIG_BUILD_AVOID_BITROT is disabled the force-obj-y and
+	force-lib-y targets are functionally equilvalent to obj-y and lib-y
+	respectively.
+
+	Using force-obj-y and force-lib-y are part of a code architecture and
+	build philosophy further enabled by linker tables, for more details
+	refer to the documention in include/linux/tables.h, refer to the
+	sections:
+
+		o The code bit-rot problem
+		o The build-all selective-link philosophy
+		o Avoiding the code bit-rot problem with linker tables
+		o Linker table module support
+
+	Modules support is expected to be enhanced in the future, so for now
+	only built-in features are supported.
+
+	Example use:
+
+		force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	An alternative to using force-obj-y, is to use extra-y followed by the
+	respective obj-y:
+
+		extra-y += foo.o
+		obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	Using force-obj-y and force-lib-y can be used to help annotate the
+	targets follow the 'build-all selective-link philosophy' further
+	enabled by linker tables.
 
 --- 6.7 Commands useful for building a boot image
 
diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index df11c632dca7..e425c5cd36d6 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -30,6 +30,21 @@ How linker tables simplify initialization code
 .. kernel-doc:: include/linux/tables.h
    :doc: How linker tables simplify initialization code
 
+The code bit-rot problem
+------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The code bit-rot problem
+
+The build-all selective-link philosophy
+---------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The build-all selective-link philosophy
+
+Avoiding the code bit-rot problem with linker tables
+----------------------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: Avoiding the code bit-rot problem with linker tables
+
 Using linker tables in Linux
 ==============
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
index 423827eafb52..bf8fae7f9246 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -169,6 +169,77 @@
  */
 
 /**
+ * DOC: The code bit-rot problem
+ *
+ * Linux provides a rich array of features, enabling each feature
+ * however increases the size of the kernel and there are many
+ * features which users often want disabled. The traditional
+ * solution to this problem is for each feature to have its own
+ * Kconfig symbol, followed by a series of #ifdef statements
+ * in C code and header files, allowing the feature to be compiled
+ * only when desirable. As the variability of Linux increases build
+ * tests can and are often done with random kernel configurations,
+ * allyesconfig, and allmodconfig to help find code issues. This
+ * however doesn't catch all errors and as a consequence code that
+ * is typically not enabled often can suffer from bit-rot over time.
+ */
+
+/**
+ * DOC: The build-all selective-link philosophy
+ *
+ * A code architecture philosophy to help avoid code bit-rot consists
+ * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
+ * by instead having each feature implemented it its own C file, and force
+ * compilation for all features. Only features that are enabled get linked in,
+ * the forced compilation therefore has no size impact on the final result of
+ * the kernel. The practice of having each feature implemented in its own C
+ * file is already prevalent in many subsystems, however #ifdefs are still
+ * typically required during feature initialization. For instance in::
+ *
+ *	#ifdef CONFIG_FOO
+ *	foo_init();
+ *	#endif
+ *
+ * We cannot remove the #ifdef and leave foo_init() as we'd either
+ * need to always enable the feature or add a respective #ifdef in a
+ * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem with linker tables
+ *
+ * Linker tables can be used to further help avoid the code bit-rot problem
+ * when embracing the 'build-all selective-link philosophy' by lifting the
+ * requirement to use of #ifdefs during initialization. With linker tables
+ * initialization sequences can be aggregated into a custom ELF section at
+ * link time, during run time the table can be iterated over and each init
+ * sequence enabled can be called. A feature's init routine is only added to a
+ * table when its respective Kconfig symbols has been enabled and therefore
+ * linked in. Linker tables enable subsystems to completely do away with
+ * #ifdefs if one is comfortable in accepting all subsystem's feature's
+ * structural size implications.
+ *
+ * To further help with this the Linux build system supports two special
+ * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
+ * follow the 'build-all selective-link philosophy' can use these targets for a
+ * feature's kconfig symbol. Using these targets will always require
+ * compilation of the kconfig's objects if the kconfig symbol's dependencies
+ * are met but only link the objects into the kernel, and therefore enable the
+ * feature, if and only if the kconfig symbol has been enabled.
+ *
+ * Not all users or build systems may want to opt-in to compile all objects
+ * following the 'build-all selective-link philosophy', as such the targets
+ * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
+ * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
+ * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
+ * ``obj-y`` and ``lib-y`` respectively.
+ *
+ * Example use::
+ *
+ * 	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+ */
+
+/**
  * DOC: Linker table module support
  *
  * Modules can use linker tables, however the linker table definition
diff --git a/init/Kconfig b/init/Kconfig
index cac3f096050d..ef09e83b9196 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -53,6 +53,28 @@ config CROSS_COMPILE
 	  need to set this unless you want the configured kernel build
 	  directory to select the cross-compiler automatically.
 
+config BUILD_AVOID_BITROT
+	bool "Enable force building of force-obj-y and force-lib-y"
+	default n
+	help
+	  When enabled objects under the force-obj-y and force-lib-y targets
+	  using a Kconfig symbol will be forced to compile if the Kconfig
+	  symbol's dependencies are met but only linked into the kernel if
+	  the Kconfig symbol is enabled. If a Kconfig symbol on a force-obj-y
+	  or force-lib-y target is disabled, it will be compiled but not linked
+	  into the kernel.
+
+	  The force-obj-y and force-lib-y targets can be used by subsystems
+	  which wish to want to follow the 'build-all selective-link philosophy'
+	  documented under include/linux/tables.h.
+
+	  Say Y if you have a decent build machine and would like to help test
+	  building code for more subsystems. Say N if you do you not have a
+	  good build machine or only want to compile what you've enabled for
+	  your kernel.
+
+	  Enabling this option never increases the size of your kernel.
+
 config COMPILE_TEST
 	bool "Compile also drivers which will not load"
 	depends on !UML
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index cd9bf22bb027..cc2c7241d193 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -92,7 +92,8 @@ modorder-target := $(obj)/modules.order
 
 # We keep a list of all modules in $(MODVERDIR)
 
-__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
+__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y) \
+				$(force-obj-y)) \
 	 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
 	 $(subdir-ym) $(always)
 	@:
@@ -326,8 +327,8 @@ cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $<
 $(obj)/%.o: $(src)/%.S $(objtool_obj) FORCE
 	$(call if_changed_rule,as_o_S)
 
-targets += $(real-objs-y) $(real-objs-m) $(lib-y)
-targets += $(extra-y) $(MAKECMDGOALS) $(always)
+targets += $(real-objs-y) $(real-objs-m) $(lib-y) $(force-lib-y)
+targets += $(extra-y) $(force-obj-y) $(MAKECMDGOALS) $(always)
 
 # Linker scripts preprocessor (.lds.S -> .lds)
 # ---------------------------------------------------------------------------
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 0a07f9014944..d1cb0cfdf1bf 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -12,6 +12,15 @@ export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y)
 # Figure out what we need to build from the various variables
 # ===================================== 
+ifeq ($(CONFIG_BUILD_AVOID_BITROT),y)
+extra-y += $(force-obj-) $(force-lib-)
+endif
+
+obj-m += $(force-obj-m)
+obj-y += $(force-obj-y)
+lib-m += $(force-lib-m)
+lib-y += $(force-lib-y)
+
 # When an object is listed to be built compiled-in and modular,
 # only build the compiled-in version
 
@@ -72,6 +81,8 @@ real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)
 # Add subdir path
 
 extra-y		:= $(addprefix $(obj)/,$(extra-y))
+force-obj-y		:= $(addprefix $(obj)/,$(force-obj-y))
+force-obj-m		:= $(addprefix $(obj)/,$(force-obj-m))
 always		:= $(addprefix $(obj)/,$(always))
 targets		:= $(addprefix $(obj)/,$(targets))
 modorder	:= $(addprefix $(obj)/,$(modorder))
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 08/16] kbuild: enable option to force compile force-obj-y and force-lib-y
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Linux provides a rich array of features, enabling each feature
however increases the size of the kernel and there are many
features which users often want disabled. The traditional
solution to this problem is for each feature to have its own
Kconfig symbol, followed by a series of #ifdef statements
in C code and header files, allowing the feature to be compiled
only when desirable. As the variability of Linux increases build
tests can and are often done with random kernel configurations,
allyesconfig, and allmodconfig to help find code issues. This
however doesn't catch all errors and as a consequence code that
is typically not enabled often can suffer from bit-rot over time.

An alternative approach for subsystems, which refer to as the 'build-all
link-selectively philosophy' is to keep the Kconfig symbols, replace
the #ifdef approach by having each feature implemented it its own C file,
and force compilation for all features to avoid the code bit-rot problem.
With this strategy only features that are enabled via Kconfig get
linked into the kernel, so the forced compilation has no size impact
on the kernel. The practice of having each feature implemented in its own
C file is already prevalent in many subsystems, however #ifdefs are still
typically required during feature initialization. For instance in:

  #ifdef CONFIG_FOO
  foo_init();
  #endif

We cannot remove the #ifdef and leave foo_init() as we'd either
need to always enable the feature or add a respective #ifdef in a
foo.h which makes foo_init() do nothing when CONFIG_FOO is disabled.

Linker tables enable lifting the requirement to use of #ifdefs during
initialization. With linker tables initialization sequences can instead
be aggregated into a custom ELF section at link time, during run time
the table can be iterated over and each init sequence enabled can be called.
A feature's init routine is only added to a table when its respective
Kconfig symbols has been enabled and therefore linked in. Linker tables
enable subsystems to completely do away with #ifdefs if one is comfortable
in accepting all subsystem's feature's structural size implications.

Subsystems which want to follow the 'build-all link-selectively
philosophy' still need a way to easily express and annotate that they
wish for all code to always be compiled to help avoid code bit rot,
as such two new targets force-obj-y and force-lib-y are provided to
help with this. Its not fair to require everyone to force compilation
of all features of a subsystem though, so as a compromise, the new
targets only force compilation when CONFIG_BUILD_AVOID_BITROT is
enabled.

Only built-in features are supported at the moment. Module support
is expected to be added after a generic solution to add linker
tables to modules more easily is developed.

v4: this patch was added to this series, it was split off from the
    linker tables addition due to the confusion over the code bit
    rot alternatives that are possible with linker tables.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/kbuild/makefiles.txt       | 36 ++++++++++++++++
 Documentation/sections/linker-tables.rst | 15 +++++++
 include/linux/tables.h                   | 71 ++++++++++++++++++++++++++++++++
 init/Kconfig                             | 22 ++++++++++
 scripts/Makefile.build                   |  7 ++--
 scripts/Makefile.lib                     | 11 +++++
 6 files changed, 159 insertions(+), 3 deletions(-)

diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 385a5ef41c17..01c260913f5c 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -1089,6 +1089,42 @@ When kbuild executes, the following steps are followed (roughly):
 	In this example, extra-y is used to list object files that
 	shall be built, but shall not be linked as part of built-in.o.
 
+    force-obj-y force-lib-y
+
+	When CONFIG_BUILD_AVOID_BITROT is enabled using these targets for your
+	kconfig symbols forces compilation of the associated objects if the
+	kconfig's symbol's dependencies are met, the objects however are only
+	linked into to the kernel if and only if the kconfig symbol was
+	enabled. If CONFIG_BUILD_AVOID_BITROT is disabled the force-obj-y and
+	force-lib-y targets are functionally equilvalent to obj-y and lib-y
+	respectively.
+
+	Using force-obj-y and force-lib-y are part of a code architecture and
+	build philosophy further enabled by linker tables, for more details
+	refer to the documention in include/linux/tables.h, refer to the
+	sections:
+
+		o The code bit-rot problem
+		o The build-all selective-link philosophy
+		o Avoiding the code bit-rot problem with linker tables
+		o Linker table module support
+
+	Modules support is expected to be enhanced in the future, so for now
+	only built-in features are supported.
+
+	Example use:
+
+		force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	An alternative to using force-obj-y, is to use extra-y followed by the
+	respective obj-y:
+
+		extra-y += foo.o
+		obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	Using force-obj-y and force-lib-y can be used to help annotate the
+	targets follow the 'build-all selective-link philosophy' further
+	enabled by linker tables.
 
 --- 6.7 Commands useful for building a boot image
 
diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index df11c632dca7..e425c5cd36d6 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -30,6 +30,21 @@ How linker tables simplify initialization code
 .. kernel-doc:: include/linux/tables.h
    :doc: How linker tables simplify initialization code
 
+The code bit-rot problem
+------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The code bit-rot problem
+
+The build-all selective-link philosophy
+---------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The build-all selective-link philosophy
+
+Avoiding the code bit-rot problem with linker tables
+----------------------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: Avoiding the code bit-rot problem with linker tables
+
 Using linker tables in Linux
 ============================
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
index 423827eafb52..bf8fae7f9246 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -169,6 +169,77 @@
  */
 
 /**
+ * DOC: The code bit-rot problem
+ *
+ * Linux provides a rich array of features, enabling each feature
+ * however increases the size of the kernel and there are many
+ * features which users often want disabled. The traditional
+ * solution to this problem is for each feature to have its own
+ * Kconfig symbol, followed by a series of #ifdef statements
+ * in C code and header files, allowing the feature to be compiled
+ * only when desirable. As the variability of Linux increases build
+ * tests can and are often done with random kernel configurations,
+ * allyesconfig, and allmodconfig to help find code issues. This
+ * however doesn't catch all errors and as a consequence code that
+ * is typically not enabled often can suffer from bit-rot over time.
+ */
+
+/**
+ * DOC: The build-all selective-link philosophy
+ *
+ * A code architecture philosophy to help avoid code bit-rot consists
+ * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
+ * by instead having each feature implemented it its own C file, and force
+ * compilation for all features. Only features that are enabled get linked in,
+ * the forced compilation therefore has no size impact on the final result of
+ * the kernel. The practice of having each feature implemented in its own C
+ * file is already prevalent in many subsystems, however #ifdefs are still
+ * typically required during feature initialization. For instance in::
+ *
+ *	#ifdef CONFIG_FOO
+ *	foo_init();
+ *	#endif
+ *
+ * We cannot remove the #ifdef and leave foo_init() as we'd either
+ * need to always enable the feature or add a respective #ifdef in a
+ * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem with linker tables
+ *
+ * Linker tables can be used to further help avoid the code bit-rot problem
+ * when embracing the 'build-all selective-link philosophy' by lifting the
+ * requirement to use of #ifdefs during initialization. With linker tables
+ * initialization sequences can be aggregated into a custom ELF section at
+ * link time, during run time the table can be iterated over and each init
+ * sequence enabled can be called. A feature's init routine is only added to a
+ * table when its respective Kconfig symbols has been enabled and therefore
+ * linked in. Linker tables enable subsystems to completely do away with
+ * #ifdefs if one is comfortable in accepting all subsystem's feature's
+ * structural size implications.
+ *
+ * To further help with this the Linux build system supports two special
+ * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
+ * follow the 'build-all selective-link philosophy' can use these targets for a
+ * feature's kconfig symbol. Using these targets will always require
+ * compilation of the kconfig's objects if the kconfig symbol's dependencies
+ * are met but only link the objects into the kernel, and therefore enable the
+ * feature, if and only if the kconfig symbol has been enabled.
+ *
+ * Not all users or build systems may want to opt-in to compile all objects
+ * following the 'build-all selective-link philosophy', as such the targets
+ * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
+ * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
+ * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
+ * ``obj-y`` and ``lib-y`` respectively.
+ *
+ * Example use::
+ *
+ * 	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+ */
+
+/**
  * DOC: Linker table module support
  *
  * Modules can use linker tables, however the linker table definition
diff --git a/init/Kconfig b/init/Kconfig
index cac3f096050d..ef09e83b9196 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -53,6 +53,28 @@ config CROSS_COMPILE
 	  need to set this unless you want the configured kernel build
 	  directory to select the cross-compiler automatically.
 
+config BUILD_AVOID_BITROT
+	bool "Enable force building of force-obj-y and force-lib-y"
+	default n
+	help
+	  When enabled objects under the force-obj-y and force-lib-y targets
+	  using a Kconfig symbol will be forced to compile if the Kconfig
+	  symbol's dependencies are met but only linked into the kernel if
+	  the Kconfig symbol is enabled. If a Kconfig symbol on a force-obj-y
+	  or force-lib-y target is disabled, it will be compiled but not linked
+	  into the kernel.
+
+	  The force-obj-y and force-lib-y targets can be used by subsystems
+	  which wish to want to follow the 'build-all selective-link philosophy'
+	  documented under include/linux/tables.h.
+
+	  Say Y if you have a decent build machine and would like to help test
+	  building code for more subsystems. Say N if you do you not have a
+	  good build machine or only want to compile what you've enabled for
+	  your kernel.
+
+	  Enabling this option never increases the size of your kernel.
+
 config COMPILE_TEST
 	bool "Compile also drivers which will not load"
 	depends on !UML
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index cd9bf22bb027..cc2c7241d193 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -92,7 +92,8 @@ modorder-target := $(obj)/modules.order
 
 # We keep a list of all modules in $(MODVERDIR)
 
-__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
+__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y) \
+				$(force-obj-y)) \
 	 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
 	 $(subdir-ym) $(always)
 	@:
@@ -326,8 +327,8 @@ cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $<
 $(obj)/%.o: $(src)/%.S $(objtool_obj) FORCE
 	$(call if_changed_rule,as_o_S)
 
-targets += $(real-objs-y) $(real-objs-m) $(lib-y)
-targets += $(extra-y) $(MAKECMDGOALS) $(always)
+targets += $(real-objs-y) $(real-objs-m) $(lib-y) $(force-lib-y)
+targets += $(extra-y) $(force-obj-y) $(MAKECMDGOALS) $(always)
 
 # Linker scripts preprocessor (.lds.S -> .lds)
 # ---------------------------------------------------------------------------
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 0a07f9014944..d1cb0cfdf1bf 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -12,6 +12,15 @@ export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y)
 # Figure out what we need to build from the various variables
 # ===========================================================================
 
+ifeq ($(CONFIG_BUILD_AVOID_BITROT),y)
+extra-y += $(force-obj-) $(force-lib-)
+endif
+
+obj-m += $(force-obj-m)
+obj-y += $(force-obj-y)
+lib-m += $(force-lib-m)
+lib-y += $(force-lib-y)
+
 # When an object is listed to be built compiled-in and modular,
 # only build the compiled-in version
 
@@ -72,6 +81,8 @@ real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)
 # Add subdir path
 
 extra-y		:= $(addprefix $(obj)/,$(extra-y))
+force-obj-y		:= $(addprefix $(obj)/,$(force-obj-y))
+force-obj-m		:= $(addprefix $(obj)/,$(force-obj-m))
 always		:= $(addprefix $(obj)/,$(always))
 targets		:= $(addprefix $(obj)/,$(targets))
 modorder	:= $(addprefix $(obj)/,$(modorder))
-- 
2.9.2

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 08/16] kbuild: enable option to force compile force-obj-y and force-lib-y
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Linux provides a rich array of features, enabling each feature
however increases the size of the kernel and there are many
features which users often want disabled. The traditional
solution to this problem is for each feature to have its own
Kconfig symbol, followed by a series of #ifdef statements
in C code and header files, allowing the feature to be compiled
only when desirable. As the variability of Linux increases build
tests can and are often done with random kernel configurations,
allyesconfig, and allmodconfig to help find code issues. This
however doesn't catch all errors and as a consequence code that
is typically not enabled often can suffer from bit-rot over time.

An alternative approach for subsystems, which refer to as the 'build-all
link-selectively philosophy' is to keep the Kconfig symbols, replace
the #ifdef approach by having each feature implemented it its own C file,
and force compilation for all features to avoid the code bit-rot problem.
With this strategy only features that are enabled via Kconfig get
linked into the kernel, so the forced compilation has no size impact
on the kernel. The practice of having each feature implemented in its own
C file is already prevalent in many subsystems, however #ifdefs are still
typically required during feature initialization. For instance in:

  #ifdef CONFIG_FOO
  foo_init();
  #endif

We cannot remove the #ifdef and leave foo_init() as we'd either
need to always enable the feature or add a respective #ifdef in a
foo.h which makes foo_init() do nothing when CONFIG_FOO is disabled.

Linker tables enable lifting the requirement to use of #ifdefs during
initialization. With linker tables initialization sequences can instead
be aggregated into a custom ELF section at link time, during run time
the table can be iterated over and each init sequence enabled can be called.
A feature's init routine is only added to a table when its respective
Kconfig symbols has been enabled and therefore linked in. Linker tables
enable subsystems to completely do away with #ifdefs if one is comfortable
in accepting all subsystem's feature's structural size implications.

Subsystems which want to follow the 'build-all link-selectively
philosophy' still need a way to easily express and annotate that they
wish for all code to always be compiled to help avoid code bit rot,
as such two new targets force-obj-y and force-lib-y are provided to
help with this. Its not fair to require everyone to force compilation
of all features of a subsystem though, so as a compromise, the new
targets only force compilation when CONFIG_BUILD_AVOID_BITROT is
enabled.

Only built-in features are supported at the moment. Module support
is expected to be added after a generic solution to add linker
tables to modules more easily is developed.

v4: this patch was added to this series, it was split off from the
    linker tables addition due to the confusion over the code bit
    rot alternatives that are possible with linker tables.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/kbuild/makefiles.txt       | 36 ++++++++++++++++
 Documentation/sections/linker-tables.rst | 15 +++++++
 include/linux/tables.h                   | 71 ++++++++++++++++++++++++++++++++
 init/Kconfig                             | 22 ++++++++++
 scripts/Makefile.build                   |  7 ++--
 scripts/Makefile.lib                     | 11 +++++
 6 files changed, 159 insertions(+), 3 deletions(-)

diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 385a5ef41c17..01c260913f5c 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -1089,6 +1089,42 @@ When kbuild executes, the following steps are followed (roughly):
 	In this example, extra-y is used to list object files that
 	shall be built, but shall not be linked as part of built-in.o.
 
+    force-obj-y force-lib-y
+
+	When CONFIG_BUILD_AVOID_BITROT is enabled using these targets for your
+	kconfig symbols forces compilation of the associated objects if the
+	kconfig's symbol's dependencies are met, the objects however are only
+	linked into to the kernel if and only if the kconfig symbol was
+	enabled. If CONFIG_BUILD_AVOID_BITROT is disabled the force-obj-y and
+	force-lib-y targets are functionally equilvalent to obj-y and lib-y
+	respectively.
+
+	Using force-obj-y and force-lib-y are part of a code architecture and
+	build philosophy further enabled by linker tables, for more details
+	refer to the documention in include/linux/tables.h, refer to the
+	sections:
+
+		o The code bit-rot problem
+		o The build-all selective-link philosophy
+		o Avoiding the code bit-rot problem with linker tables
+		o Linker table module support
+
+	Modules support is expected to be enhanced in the future, so for now
+	only built-in features are supported.
+
+	Example use:
+
+		force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	An alternative to using force-obj-y, is to use extra-y followed by the
+	respective obj-y:
+
+		extra-y += foo.o
+		obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	Using force-obj-y and force-lib-y can be used to help annotate the
+	targets follow the 'build-all selective-link philosophy' further
+	enabled by linker tables.
 
 --- 6.7 Commands useful for building a boot image
 
diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index df11c632dca7..e425c5cd36d6 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -30,6 +30,21 @@ How linker tables simplify initialization code
 .. kernel-doc:: include/linux/tables.h
    :doc: How linker tables simplify initialization code
 
+The code bit-rot problem
+------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The code bit-rot problem
+
+The build-all selective-link philosophy
+---------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The build-all selective-link philosophy
+
+Avoiding the code bit-rot problem with linker tables
+----------------------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: Avoiding the code bit-rot problem with linker tables
+
 Using linker tables in Linux
 ============================
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
index 423827eafb52..bf8fae7f9246 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -169,6 +169,77 @@
  */
 
 /**
+ * DOC: The code bit-rot problem
+ *
+ * Linux provides a rich array of features, enabling each feature
+ * however increases the size of the kernel and there are many
+ * features which users often want disabled. The traditional
+ * solution to this problem is for each feature to have its own
+ * Kconfig symbol, followed by a series of #ifdef statements
+ * in C code and header files, allowing the feature to be compiled
+ * only when desirable. As the variability of Linux increases build
+ * tests can and are often done with random kernel configurations,
+ * allyesconfig, and allmodconfig to help find code issues. This
+ * however doesn't catch all errors and as a consequence code that
+ * is typically not enabled often can suffer from bit-rot over time.
+ */
+
+/**
+ * DOC: The build-all selective-link philosophy
+ *
+ * A code architecture philosophy to help avoid code bit-rot consists
+ * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
+ * by instead having each feature implemented it its own C file, and force
+ * compilation for all features. Only features that are enabled get linked in,
+ * the forced compilation therefore has no size impact on the final result of
+ * the kernel. The practice of having each feature implemented in its own C
+ * file is already prevalent in many subsystems, however #ifdefs are still
+ * typically required during feature initialization. For instance in::
+ *
+ *	#ifdef CONFIG_FOO
+ *	foo_init();
+ *	#endif
+ *
+ * We cannot remove the #ifdef and leave foo_init() as we'd either
+ * need to always enable the feature or add a respective #ifdef in a
+ * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem with linker tables
+ *
+ * Linker tables can be used to further help avoid the code bit-rot problem
+ * when embracing the 'build-all selective-link philosophy' by lifting the
+ * requirement to use of #ifdefs during initialization. With linker tables
+ * initialization sequences can be aggregated into a custom ELF section at
+ * link time, during run time the table can be iterated over and each init
+ * sequence enabled can be called. A feature's init routine is only added to a
+ * table when its respective Kconfig symbols has been enabled and therefore
+ * linked in. Linker tables enable subsystems to completely do away with
+ * #ifdefs if one is comfortable in accepting all subsystem's feature's
+ * structural size implications.
+ *
+ * To further help with this the Linux build system supports two special
+ * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
+ * follow the 'build-all selective-link philosophy' can use these targets for a
+ * feature's kconfig symbol. Using these targets will always require
+ * compilation of the kconfig's objects if the kconfig symbol's dependencies
+ * are met but only link the objects into the kernel, and therefore enable the
+ * feature, if and only if the kconfig symbol has been enabled.
+ *
+ * Not all users or build systems may want to opt-in to compile all objects
+ * following the 'build-all selective-link philosophy', as such the targets
+ * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
+ * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
+ * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
+ * ``obj-y`` and ``lib-y`` respectively.
+ *
+ * Example use::
+ *
+ * 	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+ */
+
+/**
  * DOC: Linker table module support
  *
  * Modules can use linker tables, however the linker table definition
diff --git a/init/Kconfig b/init/Kconfig
index cac3f096050d..ef09e83b9196 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -53,6 +53,28 @@ config CROSS_COMPILE
 	  need to set this unless you want the configured kernel build
 	  directory to select the cross-compiler automatically.
 
+config BUILD_AVOID_BITROT
+	bool "Enable force building of force-obj-y and force-lib-y"
+	default n
+	help
+	  When enabled objects under the force-obj-y and force-lib-y targets
+	  using a Kconfig symbol will be forced to compile if the Kconfig
+	  symbol's dependencies are met but only linked into the kernel if
+	  the Kconfig symbol is enabled. If a Kconfig symbol on a force-obj-y
+	  or force-lib-y target is disabled, it will be compiled but not linked
+	  into the kernel.
+
+	  The force-obj-y and force-lib-y targets can be used by subsystems
+	  which wish to want to follow the 'build-all selective-link philosophy'
+	  documented under include/linux/tables.h.
+
+	  Say Y if you have a decent build machine and would like to help test
+	  building code for more subsystems. Say N if you do you not have a
+	  good build machine or only want to compile what you've enabled for
+	  your kernel.
+
+	  Enabling this option never increases the size of your kernel.
+
 config COMPILE_TEST
 	bool "Compile also drivers which will not load"
 	depends on !UML
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index cd9bf22bb027..cc2c7241d193 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -92,7 +92,8 @@ modorder-target := $(obj)/modules.order
 
 # We keep a list of all modules in $(MODVERDIR)
 
-__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
+__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y) \
+				$(force-obj-y)) \
 	 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
 	 $(subdir-ym) $(always)
 	@:
@@ -326,8 +327,8 @@ cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $<
 $(obj)/%.o: $(src)/%.S $(objtool_obj) FORCE
 	$(call if_changed_rule,as_o_S)
 
-targets += $(real-objs-y) $(real-objs-m) $(lib-y)
-targets += $(extra-y) $(MAKECMDGOALS) $(always)
+targets += $(real-objs-y) $(real-objs-m) $(lib-y) $(force-lib-y)
+targets += $(extra-y) $(force-obj-y) $(MAKECMDGOALS) $(always)
 
 # Linker scripts preprocessor (.lds.S -> .lds)
 # ---------------------------------------------------------------------------
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 0a07f9014944..d1cb0cfdf1bf 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -12,6 +12,15 @@ export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y)
 # Figure out what we need to build from the various variables
 # ===========================================================================
 
+ifeq ($(CONFIG_BUILD_AVOID_BITROT),y)
+extra-y += $(force-obj-) $(force-lib-)
+endif
+
+obj-m += $(force-obj-m)
+obj-y += $(force-obj-y)
+lib-m += $(force-lib-m)
+lib-y += $(force-lib-y)
+
 # When an object is listed to be built compiled-in and modular,
 # only build the compiled-in version
 
@@ -72,6 +81,8 @@ real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)
 # Add subdir path
 
 extra-y		:= $(addprefix $(obj)/,$(extra-y))
+force-obj-y		:= $(addprefix $(obj)/,$(force-obj-y))
+force-obj-m		:= $(addprefix $(obj)/,$(force-obj-m))
 always		:= $(addprefix $(obj)/,$(always))
 targets		:= $(addprefix $(obj)/,$(targets))
 modorder	:= $(addprefix $(obj)/,$(modorder))
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 09/16] firmware/Makefile: force recompilation if makefile changes
  2016-08-19 21:33   ` mcgrof
  (?)
@ 2016-08-19 21:34     ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

If you modify the target asm we currently do not force the
recompilation of the firmware files. The target asm is in
the firmware/Makefile, peg this file as a dependency to
require re-compilation of firmware targets when the asm
changes.

v3: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 firmware/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/firmware/Makefile b/firmware/Makefile
index e297e1b52636..fa3e81c2a97b 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -176,7 +176,8 @@ quiet_cmd_fwbin = MK_FW   $@
 wordsize_deps := $(wildcard include/config/64bit.h include/config/32bit.h \
 		include/config/ppc32.h include/config/ppc64.h \
 		include/config/superh32.h include/config/superh64.h \
-		include/config/x86_32.h include/config/x86_64.h)
+		include/config/x86_32.h include/config/x86_64.h \
+		firmware/Makefile)
 
 $(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)): %: $(wordsize_deps)
 	$(call cmd,fwbin,$(patsubst %.gen.S,%,$@))
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 09/16] firmware/Makefile: force recompilation if makefile changes
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

If you modify the target asm we currently do not force the
recompilation of the firmware files. The target asm is in
the firmware/Makefile, peg this file as a dependency to
require re-compilation of firmware targets when the asm
changes.

v3: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 firmware/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/firmware/Makefile b/firmware/Makefile
index e297e1b52636..fa3e81c2a97b 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -176,7 +176,8 @@ quiet_cmd_fwbin = MK_FW   $@
 wordsize_deps := $(wildcard include/config/64bit.h include/config/32bit.h \
 		include/config/ppc32.h include/config/ppc64.h \
 		include/config/superh32.h include/config/superh64.h \
-		include/config/x86_32.h include/config/x86_64.h)
+		include/config/x86_32.h include/config/x86_64.h \
+		firmware/Makefile)
 
 $(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)): %: $(wordsize_deps)
 	$(call cmd,fwbin,$(patsubst %.gen.S,%,$@))
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 09/16] firmware/Makefile: force recompilation if makefile changes
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

If you modify the target asm we currently do not force the
recompilation of the firmware files. The target asm is in
the firmware/Makefile, peg this file as a dependency to
require re-compilation of firmware targets when the asm
changes.

v3: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 firmware/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/firmware/Makefile b/firmware/Makefile
index e297e1b52636..fa3e81c2a97b 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -176,7 +176,8 @@ quiet_cmd_fwbin = MK_FW   $@
 wordsize_deps := $(wildcard include/config/64bit.h include/config/32bit.h \
 		include/config/ppc32.h include/config/ppc64.h \
 		include/config/superh32.h include/config/superh64.h \
-		include/config/x86_32.h include/config/x86_64.h)
+		include/config/x86_32.h include/config/x86_64.h \
+		firmware/Makefile)
 
 $(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)): %: $(wordsize_deps)
 	$(call cmd,fwbin,$(patsubst %.gen.S,%,$@))
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 10/16] firmware: port built-in section to linker table
  2016-08-19 21:33   ` mcgrof
  (?)
@ 2016-08-19 21:34     ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This ports built-in firmware to use linker tables,
this replaces the custom section solution with a
generic solution.

This also demos the use of the .rodata (SECTION_RO)
linker tables.

Tested with 0 built-in firmware, 1 and 2 built-in
firmwares successfully.

v4:

o work around c6x toolchain bug by using SECTION_TBL_RO

o fix compilation on blackfin

v3:
o explicitly include tables.h as we no longer include
  tables.h from sections.h

o use new section_tbl_asmtype() helper on firmware/Makefile
  to enable having to unfold things on our own.

v2: introduced this file in this version of the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/x86/kernel/cpu/microcode/core.c |  8 ++++----
 drivers/base/firmware_class.c        | 12 ++++++------
 firmware/Makefile                    |  3 ++-
 include/asm-generic/vmlinux.lds.h    |  7 -------
 4 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index df04b2d033f6..3e7c08d99601 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -31,6 +31,7 @@
 #include <linux/cpu.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/tables.h>
 
 #include <asm/microcode_intel.h>
 #include <asm/cpu_device_id.h>
@@ -91,15 +92,14 @@ static bool __init check_loader_disabled_bsp(void)
 	return *res;
 }
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DECLARE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 bool get_builtin_firmware(struct cpio_data *cd, const char *name)
 {
 #ifdef CONFIG_FW_LOADER
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw) {
 		if (!strcmp(name, b_fw->name)) {
 			cd->size = b_fw->size;
 			cd->data = b_fw->data;
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 22d1760a4278..8fbf03c3e4c2 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -30,6 +30,7 @@
 #include <linux/syscore_ops.h>
 #include <linux/reboot.h>
 #include <linux/security.h>
+#include <linux/tables.h>
 
 #include <generated/utsrelease.h>
 
@@ -43,15 +44,14 @@ MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_FW_LOADER
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DEFINE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 				    void *buf, size_t size)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw) {
 		if (strcmp(name, b_fw->name) = 0) {
 			fw->size = b_fw->size;
 			fw->data = b_fw->data;
@@ -67,9 +67,9 @@ static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 
 static bool fw_is_builtin_firmware(const struct firmware *fw)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++)
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw)
 		if (fw->data = b_fw->data)
 			return true;
 
diff --git a/firmware/Makefile b/firmware/Makefile
index fa3e81c2a97b..9e701bf4ced2 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -155,6 +155,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  ASM_ALIGN=$(if $(CONFIG_64BIT),3,2);			     \
 		  PROGBITS=$(if $(CONFIG_ARM),%,@)progbits;		     \
 		  echo "/* Generated by firmware/Makefile */"		> $@;\
+		  echo "\#include <asm/tables.h>"			>>$@;\
 		  echo "    .section .rodata"				>>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_bin:"				>>$@;\
@@ -164,7 +165,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_name:"				>>$@;\
 		  echo "    .string \"$$FWNAME\""			>>$@;\
-		  echo "    .section .builtin_fw,\"a\",$${PROGBITS}"	>>$@;\
+		  echo "    set_section_tbl_type(SECTION_TBL_RO, builtin_fw, SECTION_ORDER_ANY, a,$${PROGBITS})" >>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_name"		>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_bin"		>>$@;\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 4b6a3d820883..2413444c048d 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -316,13 +316,6 @@
 		VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .;	\
 	}								\
 									\
-	/* Built-in firmware blobs */					\
-	.builtin_fw        : AT(ADDR(.builtin_fw) - LOAD_OFFSET) {	\
-		VMLINUX_SYMBOL(__start_builtin_fw) = .;			\
-		*(.builtin_fw)						\
-		VMLINUX_SYMBOL(__end_builtin_fw) = .;			\
-	}								\
-									\
 	TRACEDATA							\
 									\
 	/* Kernel symbol table: Normal symbols */			\
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 10/16] firmware: port built-in section to linker table
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This ports built-in firmware to use linker tables,
this replaces the custom section solution with a
generic solution.

This also demos the use of the .rodata (SECTION_RO)
linker tables.

Tested with 0 built-in firmware, 1 and 2 built-in
firmwares successfully.

v4:

o work around c6x toolchain bug by using SECTION_TBL_RO

o fix compilation on blackfin

v3:
o explicitly include tables.h as we no longer include
  tables.h from sections.h

o use new section_tbl_asmtype() helper on firmware/Makefile
  to enable having to unfold things on our own.

v2: introduced this file in this version of the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/x86/kernel/cpu/microcode/core.c |  8 ++++----
 drivers/base/firmware_class.c        | 12 ++++++------
 firmware/Makefile                    |  3 ++-
 include/asm-generic/vmlinux.lds.h    |  7 -------
 4 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index df04b2d033f6..3e7c08d99601 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -31,6 +31,7 @@
 #include <linux/cpu.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/tables.h>
 
 #include <asm/microcode_intel.h>
 #include <asm/cpu_device_id.h>
@@ -91,15 +92,14 @@ static bool __init check_loader_disabled_bsp(void)
 	return *res;
 }
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DECLARE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 bool get_builtin_firmware(struct cpio_data *cd, const char *name)
 {
 #ifdef CONFIG_FW_LOADER
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw) {
 		if (!strcmp(name, b_fw->name)) {
 			cd->size = b_fw->size;
 			cd->data = b_fw->data;
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 22d1760a4278..8fbf03c3e4c2 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -30,6 +30,7 @@
 #include <linux/syscore_ops.h>
 #include <linux/reboot.h>
 #include <linux/security.h>
+#include <linux/tables.h>
 
 #include <generated/utsrelease.h>
 
@@ -43,15 +44,14 @@ MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_FW_LOADER
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DEFINE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 				    void *buf, size_t size)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw) {
 		if (strcmp(name, b_fw->name) == 0) {
 			fw->size = b_fw->size;
 			fw->data = b_fw->data;
@@ -67,9 +67,9 @@ static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 
 static bool fw_is_builtin_firmware(const struct firmware *fw)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++)
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw)
 		if (fw->data == b_fw->data)
 			return true;
 
diff --git a/firmware/Makefile b/firmware/Makefile
index fa3e81c2a97b..9e701bf4ced2 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -155,6 +155,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  ASM_ALIGN=$(if $(CONFIG_64BIT),3,2);			     \
 		  PROGBITS=$(if $(CONFIG_ARM),%,@)progbits;		     \
 		  echo "/* Generated by firmware/Makefile */"		> $@;\
+		  echo "\#include <asm/tables.h>"			>>$@;\
 		  echo "    .section .rodata"				>>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_bin:"				>>$@;\
@@ -164,7 +165,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_name:"				>>$@;\
 		  echo "    .string \"$$FWNAME\""			>>$@;\
-		  echo "    .section .builtin_fw,\"a\",$${PROGBITS}"	>>$@;\
+		  echo "    set_section_tbl_type(SECTION_TBL_RO, builtin_fw, SECTION_ORDER_ANY, a,$${PROGBITS})" >>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_name"		>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_bin"		>>$@;\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 4b6a3d820883..2413444c048d 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -316,13 +316,6 @@
 		VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .;	\
 	}								\
 									\
-	/* Built-in firmware blobs */					\
-	.builtin_fw        : AT(ADDR(.builtin_fw) - LOAD_OFFSET) {	\
-		VMLINUX_SYMBOL(__start_builtin_fw) = .;			\
-		*(.builtin_fw)						\
-		VMLINUX_SYMBOL(__end_builtin_fw) = .;			\
-	}								\
-									\
 	TRACEDATA							\
 									\
 	/* Kernel symbol table: Normal symbols */			\
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 10/16] firmware: port built-in section to linker table
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez, Barry Song, Mike Frysinger,
	Michael Matz, Guenter Roeck, Fengguang Wu

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This ports built-in firmware to use linker tables,
this replaces the custom section solution with a
generic solution.

This also demos the use of the .rodata (SECTION_RO)
linker tables.

Tested with 0 built-in firmware, 1 and 2 built-in
firmwares successfully.

v4:

o work around c6x toolchain bug by using SECTION_TBL_RO

o fix compilation on blackfin

v3:
o explicitly include tables.h as we no longer include
  tables.h from sections.h

o use new section_tbl_asmtype() helper on firmware/Makefile
  to enable having to unfold things on our own.

v2: introduced this file in this version of the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/x86/kernel/cpu/microcode/core.c |  8 ++++----
 drivers/base/firmware_class.c        | 12 ++++++------
 firmware/Makefile                    |  3 ++-
 include/asm-generic/vmlinux.lds.h    |  7 -------
 4 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index df04b2d033f6..3e7c08d99601 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -31,6 +31,7 @@
 #include <linux/cpu.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/tables.h>
 
 #include <asm/microcode_intel.h>
 #include <asm/cpu_device_id.h>
@@ -91,15 +92,14 @@ static bool __init check_loader_disabled_bsp(void)
 	return *res;
 }
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DECLARE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 bool get_builtin_firmware(struct cpio_data *cd, const char *name)
 {
 #ifdef CONFIG_FW_LOADER
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw) {
 		if (!strcmp(name, b_fw->name)) {
 			cd->size = b_fw->size;
 			cd->data = b_fw->data;
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 22d1760a4278..8fbf03c3e4c2 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -30,6 +30,7 @@
 #include <linux/syscore_ops.h>
 #include <linux/reboot.h>
 #include <linux/security.h>
+#include <linux/tables.h>
 
 #include <generated/utsrelease.h>
 
@@ -43,15 +44,14 @@ MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_FW_LOADER
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DEFINE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 				    void *buf, size_t size)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw) {
 		if (strcmp(name, b_fw->name) == 0) {
 			fw->size = b_fw->size;
 			fw->data = b_fw->data;
@@ -67,9 +67,9 @@ static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 
 static bool fw_is_builtin_firmware(const struct firmware *fw)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++)
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw)
 		if (fw->data == b_fw->data)
 			return true;
 
diff --git a/firmware/Makefile b/firmware/Makefile
index fa3e81c2a97b..9e701bf4ced2 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -155,6 +155,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  ASM_ALIGN=$(if $(CONFIG_64BIT),3,2);			     \
 		  PROGBITS=$(if $(CONFIG_ARM),%,@)progbits;		     \
 		  echo "/* Generated by firmware/Makefile */"		> $@;\
+		  echo "\#include <asm/tables.h>"			>>$@;\
 		  echo "    .section .rodata"				>>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_bin:"				>>$@;\
@@ -164,7 +165,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_name:"				>>$@;\
 		  echo "    .string \"$$FWNAME\""			>>$@;\
-		  echo "    .section .builtin_fw,\"a\",$${PROGBITS}"	>>$@;\
+		  echo "    set_section_tbl_type(SECTION_TBL_RO, builtin_fw, SECTION_ORDER_ANY, a,$${PROGBITS})" >>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_name"		>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_bin"		>>$@;\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 4b6a3d820883..2413444c048d 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -316,13 +316,6 @@
 		VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .;	\
 	}								\
 									\
-	/* Built-in firmware blobs */					\
-	.builtin_fw        : AT(ADDR(.builtin_fw) - LOAD_OFFSET) {	\
-		VMLINUX_SYMBOL(__start_builtin_fw) = .;			\
-		*(.builtin_fw)						\
-		VMLINUX_SYMBOL(__end_builtin_fw) = .;			\
-	}								\
-									\
 	TRACEDATA							\
 									\
 	/* Kernel symbol table: Normal symbols */			\
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 11/16] jump_label: move guard #endif down where it belongs
  2016-08-19 21:33   ` mcgrof
  (?)
@ 2016-08-19 21:34     ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

The ending header guard is misplaced. This has no
functional change, this is just an eye-sore.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/linux/jump_label.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index 661af564fae8..1256f543b002 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -384,6 +384,6 @@ extern bool ____wrong_branch_error(void);
 #define static_branch_enable(x)		static_key_enable(&(x)->key)
 #define static_branch_disable(x)	static_key_disable(&(x)->key)
 
-#endif	/* _LINUX_JUMP_LABEL_H */
-
 #endif /* __ASSEMBLY__ */
+
+#endif	/* _LINUX_JUMP_LABEL_H */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 11/16] jump_label: move guard #endif down where it belongs
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

The ending header guard is misplaced. This has no
functional change, this is just an eye-sore.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/linux/jump_label.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index 661af564fae8..1256f543b002 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -384,6 +384,6 @@ extern bool ____wrong_branch_error(void);
 #define static_branch_enable(x)		static_key_enable(&(x)->key)
 #define static_branch_disable(x)	static_key_disable(&(x)->key)
 
-#endif	/* _LINUX_JUMP_LABEL_H */
-
 #endif /* __ASSEMBLY__ */
+
+#endif	/* _LINUX_JUMP_LABEL_H */
-- 
2.9.2

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 11/16] jump_label: move guard #endif down where it belongs
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

The ending header guard is misplaced. This has no
functional change, this is just an eye-sore.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/linux/jump_label.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index 661af564fae8..1256f543b002 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -384,6 +384,6 @@ extern bool ____wrong_branch_error(void);
 #define static_branch_enable(x)		static_key_enable(&(x)->key)
 #define static_branch_disable(x)	static_key_disable(&(x)->key)
 
-#endif	/* _LINUX_JUMP_LABEL_H */
-
 #endif /* __ASSEMBLY__ */
+
+#endif	/* _LINUX_JUMP_LABEL_H */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 12/16] jump_label: port __jump_table to linker tables
  2016-08-19 21:33   ` mcgrof
  (?)
@ 2016-08-19 21:34     ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Move the __jump_table from the a custom section solution
to a generic solution, this avoiding extra vmlinux.lds.h
customizations.

This also demos the use of the .data (SECTION_DATA) linker
table and of the shared asm call push_section_tbl().

Built-in kernel functionality was tested with CONFIG_STATIC_KEYS_SELFTEST.
Moduler  kernel functionality was tested with CONFIG_TEST_STATIC_KEYS.
Both work as expected.

Since __jump_table sections are also supported per
module this also required expanding module-common.lds.S
to capture and fold all .data.tlb.__jump_table.* onto
the the section __jump_table -- in this case for modules
need to keep a reference in place, given the alternative
is to use DEFINE_LINKTABLE(struct jump_entry, __jump_table)
per module -- and later through macro hacks instantiate
the jump entries per module upon init. This is doable but
we'd loose out on the sorting of the table using the
linker, to sort we'd always still need to expand the
module common linker script. An alternative mechanism
is possible which would make these custom module sections
extensions dynamic without requiring manual changes, this
however is best done later through a separate evolution
once linker tables are in place.

A careful reviewer may note that some architectures use
"\n\t" to separate asm code, while others just use a new line.
Upon review last time it was deemed reasonable to for all
architectures to just use "\n", this is defined as ASM_CMD_SEP,
and if an architecture needs to override they can do so on their
architecture sections.h prior to including asm-generic/sections.h

v4:

o Some architectures allow linker scripts to follow including header
  files, some others do not, so if you need a helper on a linker script
  you need to explicitly include it. So for instance although
  scripts/module-common.lds.S includes <asm/tables.h> and this file
  includes <asm/section-core.h>, you still need to explicitly
  include it on the linker script. This issue is present on ARM.

o as per Josh Poimboeuf open code the section table name instead
  of including the kernel section headers, the simplicity and
  independence from the kernel is preferred.

v3:

o More elaborate tests performed
o first modular support use case, module tested was
  CONFIG_TEST_STATIC_KEYS (lib/test_static_keys.ko), this
  required us to extend module-common.lds.S
o use generic push_section_tbl_any() for all architectures
o Makes use of ASM_CMD_SEP to enable architectures to override later
  if needed
o guard tables.h inclusion and table definition with __KERNEL__

v2: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arm/include/asm/jump_label.h     |  6 ++++--
 arch/arm64/include/asm/jump_label.h   |  6 ++++--
 arch/mips/include/asm/jump_label.h    |  6 ++++--
 arch/powerpc/include/asm/jump_label.h |  8 +++++---
 arch/s390/include/asm/jump_label.h    |  6 ++++--
 arch/sparc/include/asm/jump_label.h   |  6 ++++--
 arch/x86/include/asm/jump_label.h     | 10 ++++++----
 include/asm-generic/vmlinux.lds.h     |  4 ----
 include/linux/jump_label.h            |  4 ++--
 kernel/jump_label.c                   | 17 ++++++++++-------
 scripts/module-common.lds.S           |  5 +++++
 tools/objtool/special.c               |  2 +-
 12 files changed, 49 insertions(+), 31 deletions(-)

diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h
index 34f7b6980d21..960135a7b88e 100644
--- a/arch/arm/include/asm/jump_label.h
+++ b/arch/arm/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_ARM_JUMP_LABEL_H
 #define _ASM_ARM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(nop) "\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
@@ -26,7 +28,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(b) " %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
diff --git a/arch/arm64/include/asm/jump_label.h b/arch/arm64/include/asm/jump_label.h
index 1b5e0e843c3a..aa52cd2607e3 100644
--- a/arch/arm64/include/asm/jump_label.h
+++ b/arch/arm64/include/asm/jump_label.h
@@ -19,6 +19,8 @@
 #ifndef __ASM_JUMP_LABEL_H
 #define __ASM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -29,7 +31,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm goto("1: nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
@@ -43,7 +45,7 @@ l_yes:
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm goto("1: b %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
diff --git a/arch/mips/include/asm/jump_label.h b/arch/mips/include/asm/jump_label.h
index e77672539e8e..78e70cb98592 100644
--- a/arch/mips/include/asm/jump_label.h
+++ b/arch/mips/include/asm/jump_label.h
@@ -8,6 +8,8 @@
 #ifndef _ASM_MIPS_JUMP_LABEL_H
 #define _ASM_MIPS_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -30,7 +32,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\t" NOP_INSN "\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -44,7 +46,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\tj %l[l_yes]\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
index 9a287e0ac8b1..a1225f66887e 100644
--- a/arch/powerpc/include/asm/jump_label.h
+++ b/arch/powerpc/include/asm/jump_label.h
@@ -10,6 +10,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
 
@@ -23,7 +25,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 "nop # arch_static_branch\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -37,7 +39,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes] # arch_static_branch_jump\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -62,7 +64,7 @@ struct jump_entry {
 #else
 #define ARCH_STATIC_BRANCH(LABEL, KEY)		\
 1098:	nop;					\
-	.pushsection __jump_table, "aw";	\
+	push_section_tbl_any(SECTION_DATA, __jump_table, aw); \
 	FTR_ENTRY_LONG 1098b, LABEL, KEY;	\
 	.popsection
 #endif
diff --git a/arch/s390/include/asm/jump_label.h b/arch/s390/include/asm/jump_label.h
index 9be198f5ee79..17f02aec4644 100644
--- a/arch/s390/include/asm/jump_label.h
+++ b/arch/s390/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_S390_JUMP_LABEL_H
 #define _ASM_S390_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -16,7 +18,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 0,"__stringify(JUMP_LABEL_NOP_OFFSET)"\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
@@ -30,7 +32,7 @@ label:
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 15, %l[label]\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
diff --git a/arch/sparc/include/asm/jump_label.h b/arch/sparc/include/asm/jump_label.h
index 62d0354d1727..dde1275233f7 100644
--- a/arch/sparc/include/asm/jump_label.h
+++ b/arch/sparc/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_SPARC_JUMP_LABEL_H
 #define _ASM_SPARC_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 	asm_volatile_goto("1:\n\t"
 		 "nop\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
@@ -28,7 +30,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes]\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h
index adc54c12cbd1..d25fafa3df4b 100644
--- a/arch/x86/include/asm/jump_label.h
+++ b/arch/x86/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_JUMP_LABEL_H
 #define _ASM_X86_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef HAVE_JUMP_LABEL
 /*
  * For better or for worse, if jump labels (the gcc extension) are missing,
@@ -34,7 +36,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:"
 		".byte " __stringify(STATIC_KEY_INIT_NOP) "\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -50,7 +52,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:"
 		".byte 0xe9\n\t .long %l[l_yes] - 2f\n\t"
 		"2:\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -85,7 +87,7 @@ struct jump_entry {
 	.else
 	.byte		STATIC_KEY_INIT_NOP
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key
 	.popsection
@@ -101,7 +103,7 @@ struct jump_entry {
 	.long		\target - .Lstatic_jump_after_\@
 .Lstatic_jump_after_\@:
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key + 1
 	.popsection
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 2413444c048d..140fbed4a817 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -212,10 +212,6 @@
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
 	/* implement dynamic printk debug */				\
-	. = ALIGN(8);                                                   \
-	VMLINUX_SYMBOL(__start___jump_table) = .;                       \
-	*(__jump_table)                                                 \
-	VMLINUX_SYMBOL(__stop___jump_table) = .;                        \
 	. = ALIGN(8);							\
 	VMLINUX_SYMBOL(__start___verbose) = .;                          \
 	*(__verbose)                                                    \
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index 1256f543b002..842a24892a91 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -115,6 +115,7 @@ enum jump_label_type {
 struct module;
 
 #ifdef HAVE_JUMP_LABEL
+#include <linux/tables.h>
 
 #define JUMP_TYPE_FALSE	0UL
 #define JUMP_TYPE_TRUE	1UL
@@ -130,8 +131,7 @@ static __always_inline bool static_key_true(struct static_key *key)
 	return !arch_static_branch(key, true);
 }
 
-extern struct jump_entry __start___jump_table[];
-extern struct jump_entry __stop___jump_table[];
+DECLARE_LINKTABLE(struct jump_entry, __jump_table);
 
 extern void jump_label_init(void);
 extern void jump_label_lock(void);
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 93ad6c1fb9b6..7582ca28e3b8 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -15,9 +15,12 @@
 #include <linux/static_key.h>
 #include <linux/jump_label_ratelimit.h>
 #include <linux/bug.h>
+#include <linux/tables.h>
 
 #ifdef HAVE_JUMP_LABEL
 
+DEFINE_LINKTABLE(struct jump_entry, __jump_table);
+
 /* mutex to protect coming/going of the the jump_label table */
 static DEFINE_MUTEX(jump_label_mutex);
 
@@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
 
 void __init jump_label_init(void)
 {
-	struct jump_entry *iter_start = __start___jump_table;
-	struct jump_entry *iter_stop = __stop___jump_table;
 	struct static_key *key = NULL;
 	struct jump_entry *iter;
 
@@ -292,9 +293,10 @@ void __init jump_label_init(void)
 		return;
 
 	jump_label_lock();
-	jump_label_sort_entries(iter_start, iter_stop);
+	jump_label_sort_entries(LINUX_SECTION_START(__jump_table),
+				LINUX_SECTION_END(__jump_table));
 
-	for (iter = iter_start; iter < iter_stop; iter++) {
+	LINKTABLE_FOR_EACH(iter, __jump_table) {
 		struct static_key *iterk;
 
 		/* rewrite NOPs */
@@ -539,8 +541,9 @@ early_initcall(jump_label_init_module);
  */
 int jump_label_text_reserved(void *start, void *end)
 {
-	int ret = __jump_label_text_reserved(__start___jump_table,
-			__stop___jump_table, start, end);
+	int ret = __jump_label_text_reserved(LINUX_SECTION_START(__jump_table),
+					     LINUX_SECTION_END(__jump_table),
+					     start, end);
 
 	if (ret)
 		return ret;
@@ -553,7 +556,7 @@ int jump_label_text_reserved(void *start, void *end)
 
 static void jump_label_update(struct static_key *key)
 {
-	struct jump_entry *stop = __stop___jump_table;
+	struct jump_entry *stop = LINUX_SECTION_END(__jump_table);
 	struct jump_entry *entry = static_key_entries(key);
 #ifdef CONFIG_MODULES
 	struct module *mod;
diff --git a/scripts/module-common.lds.S b/scripts/module-common.lds.S
index 73a2c7da0e55..be3bde1ea0ce 100644
--- a/scripts/module-common.lds.S
+++ b/scripts/module-common.lds.S
@@ -3,6 +3,10 @@
  * Archs are free to supply their own linker scripts.  ld will
  * combine them automatically.
  */
+
+#include <asm/section-core.h>
+#include <asm/tables.h>
+
 SECTIONS {
 	/DISCARD/ : { *(.discard) }
 
@@ -16,6 +20,7 @@ SECTIONS {
 	__kcrctab_unused	0 : { *(SORT(___kcrctab_unused+*)) }
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
+	__jump_table		0 : { *(SORT(SECTION_TBL(SECTION_DATA, __jump_table, *))) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
diff --git a/tools/objtool/special.c b/tools/objtool/special.c
index bff8abb3a4aa..6f7f519abacc 100644
--- a/tools/objtool/special.c
+++ b/tools/objtool/special.c
@@ -63,7 +63,7 @@ struct special_entry entries[] = {
 		.feature = ALT_FEATURE_OFFSET,
 	},
 	{
-		.sec = "__jump_table",
+		.sec = ".data.tbl.__jump_table.any",
 		.jump_or_nop = true,
 		.size = JUMP_ENTRY_SIZE,
 		.orig = JUMP_ORIG_OFFSET,
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 12/16] jump_label: port __jump_table to linker tables
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Move the __jump_table from the a custom section solution
to a generic solution, this avoiding extra vmlinux.lds.h
customizations.

This also demos the use of the .data (SECTION_DATA) linker
table and of the shared asm call push_section_tbl().

Built-in kernel functionality was tested with CONFIG_STATIC_KEYS_SELFTEST.
Moduler  kernel functionality was tested with CONFIG_TEST_STATIC_KEYS.
Both work as expected.

Since __jump_table sections are also supported per
module this also required expanding module-common.lds.S
to capture and fold all .data.tlb.__jump_table.* onto
the the section __jump_table -- in this case for modules
need to keep a reference in place, given the alternative
is to use DEFINE_LINKTABLE(struct jump_entry, __jump_table)
per module -- and later through macro hacks instantiate
the jump entries per module upon init. This is doable but
we'd loose out on the sorting of the table using the
linker, to sort we'd always still need to expand the
module common linker script. An alternative mechanism
is possible which would make these custom module sections
extensions dynamic without requiring manual changes, this
however is best done later through a separate evolution
once linker tables are in place.

A careful reviewer may note that some architectures use
"\n\t" to separate asm code, while others just use a new line.
Upon review last time it was deemed reasonable to for all
architectures to just use "\n", this is defined as ASM_CMD_SEP,
and if an architecture needs to override they can do so on their
architecture sections.h prior to including asm-generic/sections.h

v4:

o Some architectures allow linker scripts to follow including header
  files, some others do not, so if you need a helper on a linker script
  you need to explicitly include it. So for instance although
  scripts/module-common.lds.S includes <asm/tables.h> and this file
  includes <asm/section-core.h>, you still need to explicitly
  include it on the linker script. This issue is present on ARM.

o as per Josh Poimboeuf open code the section table name instead
  of including the kernel section headers, the simplicity and
  independence from the kernel is preferred.

v3:

o More elaborate tests performed
o first modular support use case, module tested was
  CONFIG_TEST_STATIC_KEYS (lib/test_static_keys.ko), this
  required us to extend module-common.lds.S
o use generic push_section_tbl_any() for all architectures
o Makes use of ASM_CMD_SEP to enable architectures to override later
  if needed
o guard tables.h inclusion and table definition with __KERNEL__

v2: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arm/include/asm/jump_label.h     |  6 ++++--
 arch/arm64/include/asm/jump_label.h   |  6 ++++--
 arch/mips/include/asm/jump_label.h    |  6 ++++--
 arch/powerpc/include/asm/jump_label.h |  8 +++++---
 arch/s390/include/asm/jump_label.h    |  6 ++++--
 arch/sparc/include/asm/jump_label.h   |  6 ++++--
 arch/x86/include/asm/jump_label.h     | 10 ++++++----
 include/asm-generic/vmlinux.lds.h     |  4 ----
 include/linux/jump_label.h            |  4 ++--
 kernel/jump_label.c                   | 17 ++++++++++-------
 scripts/module-common.lds.S           |  5 +++++
 tools/objtool/special.c               |  2 +-
 12 files changed, 49 insertions(+), 31 deletions(-)

diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h
index 34f7b6980d21..960135a7b88e 100644
--- a/arch/arm/include/asm/jump_label.h
+++ b/arch/arm/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_ARM_JUMP_LABEL_H
 #define _ASM_ARM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(nop) "\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
@@ -26,7 +28,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(b) " %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
diff --git a/arch/arm64/include/asm/jump_label.h b/arch/arm64/include/asm/jump_label.h
index 1b5e0e843c3a..aa52cd2607e3 100644
--- a/arch/arm64/include/asm/jump_label.h
+++ b/arch/arm64/include/asm/jump_label.h
@@ -19,6 +19,8 @@
 #ifndef __ASM_JUMP_LABEL_H
 #define __ASM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -29,7 +31,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm goto("1: nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
@@ -43,7 +45,7 @@ l_yes:
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm goto("1: b %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
diff --git a/arch/mips/include/asm/jump_label.h b/arch/mips/include/asm/jump_label.h
index e77672539e8e..78e70cb98592 100644
--- a/arch/mips/include/asm/jump_label.h
+++ b/arch/mips/include/asm/jump_label.h
@@ -8,6 +8,8 @@
 #ifndef _ASM_MIPS_JUMP_LABEL_H
 #define _ASM_MIPS_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -30,7 +32,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\t" NOP_INSN "\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -44,7 +46,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\tj %l[l_yes]\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
index 9a287e0ac8b1..a1225f66887e 100644
--- a/arch/powerpc/include/asm/jump_label.h
+++ b/arch/powerpc/include/asm/jump_label.h
@@ -10,6 +10,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
 
@@ -23,7 +25,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 "nop # arch_static_branch\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -37,7 +39,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes] # arch_static_branch_jump\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -62,7 +64,7 @@ struct jump_entry {
 #else
 #define ARCH_STATIC_BRANCH(LABEL, KEY)		\
 1098:	nop;					\
-	.pushsection __jump_table, "aw";	\
+	push_section_tbl_any(SECTION_DATA, __jump_table, aw); \
 	FTR_ENTRY_LONG 1098b, LABEL, KEY;	\
 	.popsection
 #endif
diff --git a/arch/s390/include/asm/jump_label.h b/arch/s390/include/asm/jump_label.h
index 9be198f5ee79..17f02aec4644 100644
--- a/arch/s390/include/asm/jump_label.h
+++ b/arch/s390/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_S390_JUMP_LABEL_H
 #define _ASM_S390_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -16,7 +18,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 0,"__stringify(JUMP_LABEL_NOP_OFFSET)"\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
@@ -30,7 +32,7 @@ label:
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 15, %l[label]\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
diff --git a/arch/sparc/include/asm/jump_label.h b/arch/sparc/include/asm/jump_label.h
index 62d0354d1727..dde1275233f7 100644
--- a/arch/sparc/include/asm/jump_label.h
+++ b/arch/sparc/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_SPARC_JUMP_LABEL_H
 #define _ASM_SPARC_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 	asm_volatile_goto("1:\n\t"
 		 "nop\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
@@ -28,7 +30,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes]\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h
index adc54c12cbd1..d25fafa3df4b 100644
--- a/arch/x86/include/asm/jump_label.h
+++ b/arch/x86/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_JUMP_LABEL_H
 #define _ASM_X86_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef HAVE_JUMP_LABEL
 /*
  * For better or for worse, if jump labels (the gcc extension) are missing,
@@ -34,7 +36,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:"
 		".byte " __stringify(STATIC_KEY_INIT_NOP) "\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -50,7 +52,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:"
 		".byte 0xe9\n\t .long %l[l_yes] - 2f\n\t"
 		"2:\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -85,7 +87,7 @@ struct jump_entry {
 	.else
 	.byte		STATIC_KEY_INIT_NOP
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key
 	.popsection
@@ -101,7 +103,7 @@ struct jump_entry {
 	.long		\target - .Lstatic_jump_after_\@
 .Lstatic_jump_after_\@:
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key + 1
 	.popsection
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 2413444c048d..140fbed4a817 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -212,10 +212,6 @@
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
 	/* implement dynamic printk debug */				\
-	. = ALIGN(8);                                                   \
-	VMLINUX_SYMBOL(__start___jump_table) = .;                       \
-	*(__jump_table)                                                 \
-	VMLINUX_SYMBOL(__stop___jump_table) = .;                        \
 	. = ALIGN(8);							\
 	VMLINUX_SYMBOL(__start___verbose) = .;                          \
 	*(__verbose)                                                    \
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index 1256f543b002..842a24892a91 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -115,6 +115,7 @@ enum jump_label_type {
 struct module;
 
 #ifdef HAVE_JUMP_LABEL
+#include <linux/tables.h>
 
 #define JUMP_TYPE_FALSE	0UL
 #define JUMP_TYPE_TRUE	1UL
@@ -130,8 +131,7 @@ static __always_inline bool static_key_true(struct static_key *key)
 	return !arch_static_branch(key, true);
 }
 
-extern struct jump_entry __start___jump_table[];
-extern struct jump_entry __stop___jump_table[];
+DECLARE_LINKTABLE(struct jump_entry, __jump_table);
 
 extern void jump_label_init(void);
 extern void jump_label_lock(void);
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 93ad6c1fb9b6..7582ca28e3b8 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -15,9 +15,12 @@
 #include <linux/static_key.h>
 #include <linux/jump_label_ratelimit.h>
 #include <linux/bug.h>
+#include <linux/tables.h>
 
 #ifdef HAVE_JUMP_LABEL
 
+DEFINE_LINKTABLE(struct jump_entry, __jump_table);
+
 /* mutex to protect coming/going of the the jump_label table */
 static DEFINE_MUTEX(jump_label_mutex);
 
@@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
 
 void __init jump_label_init(void)
 {
-	struct jump_entry *iter_start = __start___jump_table;
-	struct jump_entry *iter_stop = __stop___jump_table;
 	struct static_key *key = NULL;
 	struct jump_entry *iter;
 
@@ -292,9 +293,10 @@ void __init jump_label_init(void)
 		return;
 
 	jump_label_lock();
-	jump_label_sort_entries(iter_start, iter_stop);
+	jump_label_sort_entries(LINUX_SECTION_START(__jump_table),
+				LINUX_SECTION_END(__jump_table));
 
-	for (iter = iter_start; iter < iter_stop; iter++) {
+	LINKTABLE_FOR_EACH(iter, __jump_table) {
 		struct static_key *iterk;
 
 		/* rewrite NOPs */
@@ -539,8 +541,9 @@ early_initcall(jump_label_init_module);
  */
 int jump_label_text_reserved(void *start, void *end)
 {
-	int ret = __jump_label_text_reserved(__start___jump_table,
-			__stop___jump_table, start, end);
+	int ret = __jump_label_text_reserved(LINUX_SECTION_START(__jump_table),
+					     LINUX_SECTION_END(__jump_table),
+					     start, end);
 
 	if (ret)
 		return ret;
@@ -553,7 +556,7 @@ int jump_label_text_reserved(void *start, void *end)
 
 static void jump_label_update(struct static_key *key)
 {
-	struct jump_entry *stop = __stop___jump_table;
+	struct jump_entry *stop = LINUX_SECTION_END(__jump_table);
 	struct jump_entry *entry = static_key_entries(key);
 #ifdef CONFIG_MODULES
 	struct module *mod;
diff --git a/scripts/module-common.lds.S b/scripts/module-common.lds.S
index 73a2c7da0e55..be3bde1ea0ce 100644
--- a/scripts/module-common.lds.S
+++ b/scripts/module-common.lds.S
@@ -3,6 +3,10 @@
  * Archs are free to supply their own linker scripts.  ld will
  * combine them automatically.
  */
+
+#include <asm/section-core.h>
+#include <asm/tables.h>
+
 SECTIONS {
 	/DISCARD/ : { *(.discard) }
 
@@ -16,6 +20,7 @@ SECTIONS {
 	__kcrctab_unused	0 : { *(SORT(___kcrctab_unused+*)) }
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
+	__jump_table		0 : { *(SORT(SECTION_TBL(SECTION_DATA, __jump_table, *))) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
diff --git a/tools/objtool/special.c b/tools/objtool/special.c
index bff8abb3a4aa..6f7f519abacc 100644
--- a/tools/objtool/special.c
+++ b/tools/objtool/special.c
@@ -63,7 +63,7 @@ struct special_entry entries[] = {
 		.feature = ALT_FEATURE_OFFSET,
 	},
 	{
-		.sec = "__jump_table",
+		.sec = ".data.tbl.__jump_table.any",
 		.jump_or_nop = true,
 		.size = JUMP_ENTRY_SIZE,
 		.orig = JUMP_ORIG_OFFSET,
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 12/16] jump_label: port __jump_table to linker tables
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Move the __jump_table from the a custom section solution
to a generic solution, this avoiding extra vmlinux.lds.h
customizations.

This also demos the use of the .data (SECTION_DATA) linker
table and of the shared asm call push_section_tbl().

Built-in kernel functionality was tested with CONFIG_STATIC_KEYS_SELFTEST.
Moduler  kernel functionality was tested with CONFIG_TEST_STATIC_KEYS.
Both work as expected.

Since __jump_table sections are also supported per
module this also required expanding module-common.lds.S
to capture and fold all .data.tlb.__jump_table.* onto
the the section __jump_table -- in this case for modules
need to keep a reference in place, given the alternative
is to use DEFINE_LINKTABLE(struct jump_entry, __jump_table)
per module -- and later through macro hacks instantiate
the jump entries per module upon init. This is doable but
we'd loose out on the sorting of the table using the
linker, to sort we'd always still need to expand the
module common linker script. An alternative mechanism
is possible which would make these custom module sections
extensions dynamic without requiring manual changes, this
however is best done later through a separate evolution
once linker tables are in place.

A careful reviewer may note that some architectures use
"\n\t" to separate asm code, while others just use a new line.
Upon review last time it was deemed reasonable to for all
architectures to just use "\n", this is defined as ASM_CMD_SEP,
and if an architecture needs to override they can do so on their
architecture sections.h prior to including asm-generic/sections.h

v4:

o Some architectures allow linker scripts to follow including header
  files, some others do not, so if you need a helper on a linker script
  you need to explicitly include it. So for instance although
  scripts/module-common.lds.S includes <asm/tables.h> and this file
  includes <asm/section-core.h>, you still need to explicitly
  include it on the linker script. This issue is present on ARM.

o as per Josh Poimboeuf open code the section table name instead
  of including the kernel section headers, the simplicity and
  independence from the kernel is preferred.

v3:

o More elaborate tests performed
o first modular support use case, module tested was
  CONFIG_TEST_STATIC_KEYS (lib/test_static_keys.ko), this
  required us to extend module-common.lds.S
o use generic push_section_tbl_any() for all architectures
o Makes use of ASM_CMD_SEP to enable architectures to override later
  if needed
o guard tables.h inclusion and table definition with __KERNEL__

v2: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arm/include/asm/jump_label.h     |  6 ++++--
 arch/arm64/include/asm/jump_label.h   |  6 ++++--
 arch/mips/include/asm/jump_label.h    |  6 ++++--
 arch/powerpc/include/asm/jump_label.h |  8 +++++---
 arch/s390/include/asm/jump_label.h    |  6 ++++--
 arch/sparc/include/asm/jump_label.h   |  6 ++++--
 arch/x86/include/asm/jump_label.h     | 10 ++++++----
 include/asm-generic/vmlinux.lds.h     |  4 ----
 include/linux/jump_label.h            |  4 ++--
 kernel/jump_label.c                   | 17 ++++++++++-------
 scripts/module-common.lds.S           |  5 +++++
 tools/objtool/special.c               |  2 +-
 12 files changed, 49 insertions(+), 31 deletions(-)

diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h
index 34f7b6980d21..960135a7b88e 100644
--- a/arch/arm/include/asm/jump_label.h
+++ b/arch/arm/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_ARM_JUMP_LABEL_H
 #define _ASM_ARM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(nop) "\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
@@ -26,7 +28,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(b) " %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
diff --git a/arch/arm64/include/asm/jump_label.h b/arch/arm64/include/asm/jump_label.h
index 1b5e0e843c3a..aa52cd2607e3 100644
--- a/arch/arm64/include/asm/jump_label.h
+++ b/arch/arm64/include/asm/jump_label.h
@@ -19,6 +19,8 @@
 #ifndef __ASM_JUMP_LABEL_H
 #define __ASM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -29,7 +31,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm goto("1: nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
@@ -43,7 +45,7 @@ l_yes:
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm goto("1: b %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
diff --git a/arch/mips/include/asm/jump_label.h b/arch/mips/include/asm/jump_label.h
index e77672539e8e..78e70cb98592 100644
--- a/arch/mips/include/asm/jump_label.h
+++ b/arch/mips/include/asm/jump_label.h
@@ -8,6 +8,8 @@
 #ifndef _ASM_MIPS_JUMP_LABEL_H
 #define _ASM_MIPS_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -30,7 +32,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\t" NOP_INSN "\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -44,7 +46,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\tj %l[l_yes]\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
index 9a287e0ac8b1..a1225f66887e 100644
--- a/arch/powerpc/include/asm/jump_label.h
+++ b/arch/powerpc/include/asm/jump_label.h
@@ -10,6 +10,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
 
@@ -23,7 +25,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 "nop # arch_static_branch\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -37,7 +39,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes] # arch_static_branch_jump\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -62,7 +64,7 @@ struct jump_entry {
 #else
 #define ARCH_STATIC_BRANCH(LABEL, KEY)		\
 1098:	nop;					\
-	.pushsection __jump_table, "aw";	\
+	push_section_tbl_any(SECTION_DATA, __jump_table, aw); \
 	FTR_ENTRY_LONG 1098b, LABEL, KEY;	\
 	.popsection
 #endif
diff --git a/arch/s390/include/asm/jump_label.h b/arch/s390/include/asm/jump_label.h
index 9be198f5ee79..17f02aec4644 100644
--- a/arch/s390/include/asm/jump_label.h
+++ b/arch/s390/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_S390_JUMP_LABEL_H
 #define _ASM_S390_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -16,7 +18,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 0,"__stringify(JUMP_LABEL_NOP_OFFSET)"\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
@@ -30,7 +32,7 @@ label:
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 15, %l[label]\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
diff --git a/arch/sparc/include/asm/jump_label.h b/arch/sparc/include/asm/jump_label.h
index 62d0354d1727..dde1275233f7 100644
--- a/arch/sparc/include/asm/jump_label.h
+++ b/arch/sparc/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_SPARC_JUMP_LABEL_H
 #define _ASM_SPARC_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 	asm_volatile_goto("1:\n\t"
 		 "nop\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
@@ -28,7 +30,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes]\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h
index adc54c12cbd1..d25fafa3df4b 100644
--- a/arch/x86/include/asm/jump_label.h
+++ b/arch/x86/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_JUMP_LABEL_H
 #define _ASM_X86_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef HAVE_JUMP_LABEL
 /*
  * For better or for worse, if jump labels (the gcc extension) are missing,
@@ -34,7 +36,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:"
 		".byte " __stringify(STATIC_KEY_INIT_NOP) "\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -50,7 +52,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:"
 		".byte 0xe9\n\t .long %l[l_yes] - 2f\n\t"
 		"2:\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -85,7 +87,7 @@ struct jump_entry {
 	.else
 	.byte		STATIC_KEY_INIT_NOP
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key
 	.popsection
@@ -101,7 +103,7 @@ struct jump_entry {
 	.long		\target - .Lstatic_jump_after_\@
 .Lstatic_jump_after_\@:
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(SECTION_DATA, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key + 1
 	.popsection
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 2413444c048d..140fbed4a817 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -212,10 +212,6 @@
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
 	/* implement dynamic printk debug */				\
-	. = ALIGN(8);                                                   \
-	VMLINUX_SYMBOL(__start___jump_table) = .;                       \
-	*(__jump_table)                                                 \
-	VMLINUX_SYMBOL(__stop___jump_table) = .;                        \
 	. = ALIGN(8);							\
 	VMLINUX_SYMBOL(__start___verbose) = .;                          \
 	*(__verbose)                                                    \
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index 1256f543b002..842a24892a91 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -115,6 +115,7 @@ enum jump_label_type {
 struct module;
 
 #ifdef HAVE_JUMP_LABEL
+#include <linux/tables.h>
 
 #define JUMP_TYPE_FALSE	0UL
 #define JUMP_TYPE_TRUE	1UL
@@ -130,8 +131,7 @@ static __always_inline bool static_key_true(struct static_key *key)
 	return !arch_static_branch(key, true);
 }
 
-extern struct jump_entry __start___jump_table[];
-extern struct jump_entry __stop___jump_table[];
+DECLARE_LINKTABLE(struct jump_entry, __jump_table);
 
 extern void jump_label_init(void);
 extern void jump_label_lock(void);
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 93ad6c1fb9b6..7582ca28e3b8 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -15,9 +15,12 @@
 #include <linux/static_key.h>
 #include <linux/jump_label_ratelimit.h>
 #include <linux/bug.h>
+#include <linux/tables.h>
 
 #ifdef HAVE_JUMP_LABEL
 
+DEFINE_LINKTABLE(struct jump_entry, __jump_table);
+
 /* mutex to protect coming/going of the the jump_label table */
 static DEFINE_MUTEX(jump_label_mutex);
 
@@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
 
 void __init jump_label_init(void)
 {
-	struct jump_entry *iter_start = __start___jump_table;
-	struct jump_entry *iter_stop = __stop___jump_table;
 	struct static_key *key = NULL;
 	struct jump_entry *iter;
 
@@ -292,9 +293,10 @@ void __init jump_label_init(void)
 		return;
 
 	jump_label_lock();
-	jump_label_sort_entries(iter_start, iter_stop);
+	jump_label_sort_entries(LINUX_SECTION_START(__jump_table),
+				LINUX_SECTION_END(__jump_table));
 
-	for (iter = iter_start; iter < iter_stop; iter++) {
+	LINKTABLE_FOR_EACH(iter, __jump_table) {
 		struct static_key *iterk;
 
 		/* rewrite NOPs */
@@ -539,8 +541,9 @@ early_initcall(jump_label_init_module);
  */
 int jump_label_text_reserved(void *start, void *end)
 {
-	int ret = __jump_label_text_reserved(__start___jump_table,
-			__stop___jump_table, start, end);
+	int ret = __jump_label_text_reserved(LINUX_SECTION_START(__jump_table),
+					     LINUX_SECTION_END(__jump_table),
+					     start, end);
 
 	if (ret)
 		return ret;
@@ -553,7 +556,7 @@ int jump_label_text_reserved(void *start, void *end)
 
 static void jump_label_update(struct static_key *key)
 {
-	struct jump_entry *stop = __stop___jump_table;
+	struct jump_entry *stop = LINUX_SECTION_END(__jump_table);
 	struct jump_entry *entry = static_key_entries(key);
 #ifdef CONFIG_MODULES
 	struct module *mod;
diff --git a/scripts/module-common.lds.S b/scripts/module-common.lds.S
index 73a2c7da0e55..be3bde1ea0ce 100644
--- a/scripts/module-common.lds.S
+++ b/scripts/module-common.lds.S
@@ -3,6 +3,10 @@
  * Archs are free to supply their own linker scripts.  ld will
  * combine them automatically.
  */
+
+#include <asm/section-core.h>
+#include <asm/tables.h>
+
 SECTIONS {
 	/DISCARD/ : { *(.discard) }
 
@@ -16,6 +20,7 @@ SECTIONS {
 	__kcrctab_unused	0 : { *(SORT(___kcrctab_unused+*)) }
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
+	__jump_table		0 : { *(SORT(SECTION_TBL(SECTION_DATA, __jump_table, *))) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
diff --git a/tools/objtool/special.c b/tools/objtool/special.c
index bff8abb3a4aa..6f7f519abacc 100644
--- a/tools/objtool/special.c
+++ b/tools/objtool/special.c
@@ -63,7 +63,7 @@ struct special_entry entries[] = {
 		.feature = ALT_FEATURE_OFFSET,
 	},
 	{
-		.sec = "__jump_table",
+		.sec = ".data.tbl.__jump_table.any",
 		.jump_or_nop = true,
 		.size = JUMP_ENTRY_SIZE,
 		.orig = JUMP_ORIG_OFFSET,
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 13/16] dynamic_debug: port to use linker tables
  2016-08-19 21:33   ` mcgrof
  (?)
@ 2016-08-19 21:34     ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This removes the custom vmlinux.lds.h hacks and uses
the generalized solution for .data (SECTION_DATA)
entries.

This is much more potential for further fine tuning here
though in the future. For instance, linker tables enable
an extra postfix for order level annotations, this could
easily be used as the KBUILD_MODNAME and with a bit of
linker table changes we may be able to get a direct O(1)
count of the entries for that KBUILD_MODNAME: it would
just be a count on the number of entries for the given
order level. This should help make dynamic_debug_init()
cleaner and also reduce the amount of time it takes at
boot time. Instead of iterating over each print until we
have all for a KBUILD_MODNAME, we'd instead directly
operate on each KBUILD_MODNAME directly.

Tested dynamic debug with dyndbg query ana debugfs control
and it works as expected, for both built-in code and modules.

v4: fix compilation on blackfin
v3: added modular support
v2: introduced this patch into the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/asm-generic/vmlinux.lds.h |  5 -----
 include/linux/dynamic_debug.h     |  5 +++--
 lib/dynamic_debug.c               | 13 ++++++-------
 scripts/module-common.lds.S       |  1 +
 4 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 140fbed4a817..ba49b7ad7af2 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -211,11 +211,6 @@
 	*(.data.unlikely)						\
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
-	/* implement dynamic printk debug */				\
-	. = ALIGN(8);							\
-	VMLINUX_SYMBOL(__start___verbose) = .;                          \
-	*(__verbose)                                                    \
-	VMLINUX_SYMBOL(__stop___verbose) = .;				\
 	LIKELY_PROFILE()		       				\
 	BRANCH_PROFILE()						\
 	TRACE_PRINTKS()							\
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 546d68057e3b..a52618a77b09 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -4,6 +4,7 @@
 #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
 #include <linux/jump_label.h>
 #endif
+#include <linux/tables.h>
 
 /*
  * An instance of this structure is created in a special
@@ -50,6 +51,7 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
 				const char *modname);
 
 #if defined(CONFIG_DYNAMIC_DEBUG)
+DECLARE_LINKTABLE(struct _ddebug, __verbose);
 extern int ddebug_remove_module(const char *mod_name);
 extern __printf(2, 3)
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
@@ -71,8 +73,7 @@ void __dynamic_netdev_dbg(struct _ddebug *descriptor,
 			  const char *fmt, ...);
 
 #define DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, key, init)	\
-	static struct _ddebug  __aligned(8)			\
-	__attribute__((section("__verbose"))) name = {		\
+	static LINKTABLE(__verbose, SECTION_ORDER_ANY) name = {	\
 		.modname = KBUILD_MODNAME,			\
 		.function = __func__,				\
 		.filename = __FILE__,				\
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index da796e2dc4f5..f0060c84c654 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -37,8 +37,7 @@
 #include <linux/device.h>
 #include <linux/netdevice.h>
 
-extern struct _ddebug __start___verbose[];
-extern struct _ddebug __stop___verbose[];
+DEFINE_LINKTABLE(struct _ddebug, __verbose);
 
 struct ddebug_table {
 	struct list_head link;
@@ -978,14 +977,14 @@ static int __init dynamic_debug_init(void)
 	int n = 0, entries = 0, modct = 0;
 	int verbose_bytes = 0;
 
-	if (__start___verbose = __stop___verbose) {
-		pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
+	if (LINUX_SECTION_EMPTY(__verbose)) {
+		pr_warn("dynamic debug linker table empty on CONFIG_DYNAMIC_DEBUG build\n");
 		return 1;
 	}
-	iter = __start___verbose;
+	iter = LINUX_SECTION_START(__verbose);
 	modname = iter->modname;
 	iter_start = iter;
-	for (; iter < __stop___verbose; iter++) {
+	LINKTABLE_FOR_EACH(iter, __verbose) {
 		entries++;
 		verbose_bytes += strlen(iter->modname) + strlen(iter->function)
 			+ strlen(iter->filename) + strlen(iter->format);
@@ -1008,7 +1007,7 @@ static int __init dynamic_debug_init(void)
 	ddebug_init_success = 1;
 	vpr_info("%d modules, %d entries and %d bytes in ddebug tables, %d bytes in (readonly) verbose section\n",
 		 modct, entries, (int)(modct * sizeof(struct ddebug_table)),
-		 verbose_bytes + (int)(__stop___verbose - __start___verbose));
+		 verbose_bytes + (int)(LINUX_SECTION_SIZE(__verbose)));
 
 	/* apply ddebug_query boot param, dont unload tables on err */
 	if (ddebug_setup_string[0] != '\0') {
diff --git a/scripts/module-common.lds.S b/scripts/module-common.lds.S
index be3bde1ea0ce..be57ca0994dc 100644
--- a/scripts/module-common.lds.S
+++ b/scripts/module-common.lds.S
@@ -21,6 +21,7 @@ SECTIONS {
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
 	__jump_table		0 : { *(SORT(SECTION_TBL(SECTION_DATA, __jump_table, *))) }
+	__verbose		0 : { *(SORT(SECTION_TBL(SECTION_DATA, __verbose, *))) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 13/16] dynamic_debug: port to use linker tables
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This removes the custom vmlinux.lds.h hacks and uses
the generalized solution for .data (SECTION_DATA)
entries.

This is much more potential for further fine tuning here
though in the future. For instance, linker tables enable
an extra postfix for order level annotations, this could
easily be used as the KBUILD_MODNAME and with a bit of
linker table changes we may be able to get a direct O(1)
count of the entries for that KBUILD_MODNAME: it would
just be a count on the number of entries for the given
order level. This should help make dynamic_debug_init()
cleaner and also reduce the amount of time it takes at
boot time. Instead of iterating over each print until we
have all for a KBUILD_MODNAME, we'd instead directly
operate on each KBUILD_MODNAME directly.

Tested dynamic debug with dyndbg query ana debugfs control
and it works as expected, for both built-in code and modules.

v4: fix compilation on blackfin
v3: added modular support
v2: introduced this patch into the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/asm-generic/vmlinux.lds.h |  5 -----
 include/linux/dynamic_debug.h     |  5 +++--
 lib/dynamic_debug.c               | 13 ++++++-------
 scripts/module-common.lds.S       |  1 +
 4 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 140fbed4a817..ba49b7ad7af2 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -211,11 +211,6 @@
 	*(.data.unlikely)						\
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
-	/* implement dynamic printk debug */				\
-	. = ALIGN(8);							\
-	VMLINUX_SYMBOL(__start___verbose) = .;                          \
-	*(__verbose)                                                    \
-	VMLINUX_SYMBOL(__stop___verbose) = .;				\
 	LIKELY_PROFILE()		       				\
 	BRANCH_PROFILE()						\
 	TRACE_PRINTKS()							\
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 546d68057e3b..a52618a77b09 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -4,6 +4,7 @@
 #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
 #include <linux/jump_label.h>
 #endif
+#include <linux/tables.h>
 
 /*
  * An instance of this structure is created in a special
@@ -50,6 +51,7 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
 				const char *modname);
 
 #if defined(CONFIG_DYNAMIC_DEBUG)
+DECLARE_LINKTABLE(struct _ddebug, __verbose);
 extern int ddebug_remove_module(const char *mod_name);
 extern __printf(2, 3)
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
@@ -71,8 +73,7 @@ void __dynamic_netdev_dbg(struct _ddebug *descriptor,
 			  const char *fmt, ...);
 
 #define DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, key, init)	\
-	static struct _ddebug  __aligned(8)			\
-	__attribute__((section("__verbose"))) name = {		\
+	static LINKTABLE(__verbose, SECTION_ORDER_ANY) name = {	\
 		.modname = KBUILD_MODNAME,			\
 		.function = __func__,				\
 		.filename = __FILE__,				\
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index da796e2dc4f5..f0060c84c654 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -37,8 +37,7 @@
 #include <linux/device.h>
 #include <linux/netdevice.h>
 
-extern struct _ddebug __start___verbose[];
-extern struct _ddebug __stop___verbose[];
+DEFINE_LINKTABLE(struct _ddebug, __verbose);
 
 struct ddebug_table {
 	struct list_head link;
@@ -978,14 +977,14 @@ static int __init dynamic_debug_init(void)
 	int n = 0, entries = 0, modct = 0;
 	int verbose_bytes = 0;
 
-	if (__start___verbose == __stop___verbose) {
-		pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
+	if (LINUX_SECTION_EMPTY(__verbose)) {
+		pr_warn("dynamic debug linker table empty on CONFIG_DYNAMIC_DEBUG build\n");
 		return 1;
 	}
-	iter = __start___verbose;
+	iter = LINUX_SECTION_START(__verbose);
 	modname = iter->modname;
 	iter_start = iter;
-	for (; iter < __stop___verbose; iter++) {
+	LINKTABLE_FOR_EACH(iter, __verbose) {
 		entries++;
 		verbose_bytes += strlen(iter->modname) + strlen(iter->function)
 			+ strlen(iter->filename) + strlen(iter->format);
@@ -1008,7 +1007,7 @@ static int __init dynamic_debug_init(void)
 	ddebug_init_success = 1;
 	vpr_info("%d modules, %d entries and %d bytes in ddebug tables, %d bytes in (readonly) verbose section\n",
 		 modct, entries, (int)(modct * sizeof(struct ddebug_table)),
-		 verbose_bytes + (int)(__stop___verbose - __start___verbose));
+		 verbose_bytes + (int)(LINUX_SECTION_SIZE(__verbose)));
 
 	/* apply ddebug_query boot param, dont unload tables on err */
 	if (ddebug_setup_string[0] != '\0') {
diff --git a/scripts/module-common.lds.S b/scripts/module-common.lds.S
index be3bde1ea0ce..be57ca0994dc 100644
--- a/scripts/module-common.lds.S
+++ b/scripts/module-common.lds.S
@@ -21,6 +21,7 @@ SECTIONS {
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
 	__jump_table		0 : { *(SORT(SECTION_TBL(SECTION_DATA, __jump_table, *))) }
+	__verbose		0 : { *(SORT(SECTION_TBL(SECTION_DATA, __verbose, *))) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 13/16] dynamic_debug: port to use linker tables
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez, Barry Song, Mike Frysinger,
	Michael Matz, Guenter Roeck, Fengguang Wu

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This removes the custom vmlinux.lds.h hacks and uses
the generalized solution for .data (SECTION_DATA)
entries.

This is much more potential for further fine tuning here
though in the future. For instance, linker tables enable
an extra postfix for order level annotations, this could
easily be used as the KBUILD_MODNAME and with a bit of
linker table changes we may be able to get a direct O(1)
count of the entries for that KBUILD_MODNAME: it would
just be a count on the number of entries for the given
order level. This should help make dynamic_debug_init()
cleaner and also reduce the amount of time it takes at
boot time. Instead of iterating over each print until we
have all for a KBUILD_MODNAME, we'd instead directly
operate on each KBUILD_MODNAME directly.

Tested dynamic debug with dyndbg query ana debugfs control
and it works as expected, for both built-in code and modules.

v4: fix compilation on blackfin
v3: added modular support
v2: introduced this patch into the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/asm-generic/vmlinux.lds.h |  5 -----
 include/linux/dynamic_debug.h     |  5 +++--
 lib/dynamic_debug.c               | 13 ++++++-------
 scripts/module-common.lds.S       |  1 +
 4 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 140fbed4a817..ba49b7ad7af2 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -211,11 +211,6 @@
 	*(.data.unlikely)						\
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
-	/* implement dynamic printk debug */				\
-	. = ALIGN(8);							\
-	VMLINUX_SYMBOL(__start___verbose) = .;                          \
-	*(__verbose)                                                    \
-	VMLINUX_SYMBOL(__stop___verbose) = .;				\
 	LIKELY_PROFILE()		       				\
 	BRANCH_PROFILE()						\
 	TRACE_PRINTKS()							\
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 546d68057e3b..a52618a77b09 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -4,6 +4,7 @@
 #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
 #include <linux/jump_label.h>
 #endif
+#include <linux/tables.h>
 
 /*
  * An instance of this structure is created in a special
@@ -50,6 +51,7 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
 				const char *modname);
 
 #if defined(CONFIG_DYNAMIC_DEBUG)
+DECLARE_LINKTABLE(struct _ddebug, __verbose);
 extern int ddebug_remove_module(const char *mod_name);
 extern __printf(2, 3)
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
@@ -71,8 +73,7 @@ void __dynamic_netdev_dbg(struct _ddebug *descriptor,
 			  const char *fmt, ...);
 
 #define DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, key, init)	\
-	static struct _ddebug  __aligned(8)			\
-	__attribute__((section("__verbose"))) name = {		\
+	static LINKTABLE(__verbose, SECTION_ORDER_ANY) name = {	\
 		.modname = KBUILD_MODNAME,			\
 		.function = __func__,				\
 		.filename = __FILE__,				\
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index da796e2dc4f5..f0060c84c654 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -37,8 +37,7 @@
 #include <linux/device.h>
 #include <linux/netdevice.h>
 
-extern struct _ddebug __start___verbose[];
-extern struct _ddebug __stop___verbose[];
+DEFINE_LINKTABLE(struct _ddebug, __verbose);
 
 struct ddebug_table {
 	struct list_head link;
@@ -978,14 +977,14 @@ static int __init dynamic_debug_init(void)
 	int n = 0, entries = 0, modct = 0;
 	int verbose_bytes = 0;
 
-	if (__start___verbose == __stop___verbose) {
-		pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
+	if (LINUX_SECTION_EMPTY(__verbose)) {
+		pr_warn("dynamic debug linker table empty on CONFIG_DYNAMIC_DEBUG build\n");
 		return 1;
 	}
-	iter = __start___verbose;
+	iter = LINUX_SECTION_START(__verbose);
 	modname = iter->modname;
 	iter_start = iter;
-	for (; iter < __stop___verbose; iter++) {
+	LINKTABLE_FOR_EACH(iter, __verbose) {
 		entries++;
 		verbose_bytes += strlen(iter->modname) + strlen(iter->function)
 			+ strlen(iter->filename) + strlen(iter->format);
@@ -1008,7 +1007,7 @@ static int __init dynamic_debug_init(void)
 	ddebug_init_success = 1;
 	vpr_info("%d modules, %d entries and %d bytes in ddebug tables, %d bytes in (readonly) verbose section\n",
 		 modct, entries, (int)(modct * sizeof(struct ddebug_table)),
-		 verbose_bytes + (int)(__stop___verbose - __start___verbose));
+		 verbose_bytes + (int)(LINUX_SECTION_SIZE(__verbose)));
 
 	/* apply ddebug_query boot param, dont unload tables on err */
 	if (ddebug_setup_string[0] != '\0') {
diff --git a/scripts/module-common.lds.S b/scripts/module-common.lds.S
index be3bde1ea0ce..be57ca0994dc 100644
--- a/scripts/module-common.lds.S
+++ b/scripts/module-common.lds.S
@@ -21,6 +21,7 @@ SECTIONS {
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
 	__jump_table		0 : { *(SORT(SECTION_TBL(SECTION_DATA, __jump_table, *))) }
+	__verbose		0 : { *(SORT(SECTION_TBL(SECTION_DATA, __verbose, *))) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 14/16] kprobes: move kprobe declarations to asm-generic/kprobes.h
  2016-08-19 21:33   ` mcgrof
  (?)
@ 2016-08-19 21:34     ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Often all is needed is these small helpers, instead of compiler.h
or a full kprobes.h. This is important for asm helpers, in fact even
some asm/kprobes.h make use of these helpers... instead just keep a
generic asm file with helpers useful for asm code with the least amount
of clutter as possible.

Likewise we need now to also address what to do about this file for both
when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
for when architectures have CONFIG_HAVE_KPROBES but have disabled
CONFIG_KPROBES.

Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
this means most architecture code cannot include asm/kprobes.h safely.
Correct this and add guards for architectures missing them. Additionally
provide architectures that not have kprobes support with the default
asm-generic solution. This lets us force asm/kprobes.h on the header
include/linux/kprobes.h always, but most importantly we can now safely
include just asm/kprobes.h on architecture code without bringing
the full kitchen sink of header files.

Two architectures already provided a guard against CONFIG_KPROBES on
its kprobes.h: sh, arch. The rest of the architectures needed gaurds
added. We avoid including any not-needed headers on asm/kprobes.h
unless kprobes have been enabled.

In a subsequent atomic change we can try now to remove compiler.h from
include/linux/kprobes.h.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/alpha/include/asm/Kbuild      |  1 +
 arch/arc/include/asm/kprobes.h     |  6 ++++--
 arch/arm/include/asm/kprobes.h     |  4 ++++
 arch/arm/probes/decode.h           |  1 +
 arch/arm64/include/asm/kprobes.h   |  4 ++++
 arch/arm64/kernel/insn.c           |  1 +
 arch/avr32/include/asm/kprobes.h   |  4 ++++
 arch/blackfin/include/asm/Kbuild   |  1 +
 arch/c6x/include/asm/Kbuild        |  1 +
 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/kprobes.h    |  7 ++++++-
 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/kprobes.h    |  6 +++++-
 arch/mn10300/include/asm/kprobes.h |  4 ++++
 arch/nios2/include/asm/Kbuild      |  1 +
 arch/openrisc/include/asm/Kbuild   |  1 +
 arch/parisc/include/asm/Kbuild     |  1 +
 arch/powerpc/include/asm/kprobes.h |  6 ++++++
 arch/s390/include/asm/kprobes.h    |  4 ++++
 arch/score/include/asm/Kbuild      |  1 +
 arch/sh/include/asm/kprobes.h      |  2 ++
 arch/sparc/include/asm/kprobes.h   |  5 +++++
 arch/tile/include/asm/kprobes.h    |  6 +++++-
 arch/um/include/asm/Kbuild         |  1 +
 arch/unicore32/include/asm/Kbuild  |  1 +
 arch/x86/include/asm/kprobes.h     |  6 ++++++
 arch/xtensa/include/asm/Kbuild     |  1 +
 include/asm-generic/kprobes.h      | 25 +++++++++++++++++++++++++
 include/linux/compiler.h           |  8 --------
 include/linux/kprobes.h            | 19 +++----------------
 36 files changed, 107 insertions(+), 29 deletions(-)
 create mode 100644 include/asm-generic/kprobes.h

diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index f3bdc31d3c97..54d388fd026f 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += trace_clock.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/arc/include/asm/kprobes.h b/arch/arc/include/asm/kprobes.h
index 944dbedb38b5..00bdbe167615 100644
--- a/arch/arc/include/asm/kprobes.h
+++ b/arch/arc/include/asm/kprobes.h
@@ -9,6 +9,8 @@
 #ifndef _ARC_KPROBES_H
 #define _ARC_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
 #ifdef CONFIG_KPROBES
 
 typedef u16 kprobe_opcode_t;
@@ -55,6 +57,6 @@ void trap_is_kprobe(unsigned long address, struct pt_regs *regs);
 static void trap_is_kprobe(unsigned long address, struct pt_regs *regs)
 {
 }
-#endif
+#endif /* CONFIG_KPROBES */
 
-#endif
+#endif /* _ARC_KPROBES_H */
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index 3ea9be559726..59655459da59 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/notifier.h>
@@ -83,4 +86,5 @@ struct arch_optimized_insn {
 	 */
 };
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm/probes/decode.h b/arch/arm/probes/decode.h
index f9b08ba7fe73..548d622a3159 100644
--- a/arch/arm/probes/decode.h
+++ b/arch/arm/probes/decode.h
@@ -22,6 +22,7 @@
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <asm/probes.h>
+#include <asm/kprobes.h>
 
 void __init arm_probes_decode_init(void);
 
diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
index 1737aecfcc5e..6deb8d726041 100644
--- a/arch/arm64/include/asm/kprobes.h
+++ b/arch/arm64/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -57,4 +60,5 @@ int kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr);
 void kretprobe_trampoline(void);
 void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 63f9432d05e8..cc38f3241927 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -32,6 +32,7 @@
 #include <asm/fixmap.h>
 #include <asm/opcodes.h>
 #include <asm/insn.h>
+#include <asm/kprobes.h>
 
 #define AARCH64_INSN_SF_BIT	BIT(31)
 #define AARCH64_INSN_N_BIT	BIT(22)
diff --git a/arch/avr32/include/asm/kprobes.h b/arch/avr32/include/asm/kprobes.h
index 45f563ed73fd..09f39d8749ea 100644
--- a/arch/avr32/include/asm/kprobes.h
+++ b/arch/avr32/include/asm/kprobes.h
@@ -11,6 +11,9 @@
 #ifndef __ASM_AVR32_KPROBES_H
 #define __ASM_AVR32_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 
 typedef u16	kprobe_opcode_t;
@@ -46,4 +49,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif /* __ASM_AVR32_KPROBES_H */
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index b71893b1cd53..f56a68697353 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index cede2a950fbf..c54f7cc1f63e 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
+generic-y += kprobes.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 7062c1be7913..051d355feae3 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 4a59cbda5091..b58b9fc49383 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index d79968d93c12..cfca7de52b37 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -78,3 +78,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index d59ac1c1858b..d7cc35451f30 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/ia64/include/asm/kprobes.h b/arch/ia64/include/asm/kprobes.h
index d5505d6f2382..36999c55f3f2 100644
--- a/arch/ia64/include/asm/kprobes.h
+++ b/arch/ia64/include/asm/kprobes.h
@@ -23,6 +23,10 @@
  * 2005-Apr     Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
  *              <anil.s.keshavamurthy@intel.com> adapted from i386
  */
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -124,4 +128,5 @@ extern void invalidate_stacked_regs(void);
 extern void flush_register_stack(void);
 extern void arch_remove_kprobe(struct kprobe *p);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 24088f3c733c..198ad591ab41 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 65c0df17f70e..ae86bb91e13b 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -38,3 +38,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 2538224899fd..10f36ed301e1 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -59,3 +59,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index 01afb1b420f5..865ce3d96443 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/mips/include/asm/kprobes.h b/arch/mips/include/asm/kprobes.h
index daba1f9a4f79..291846d9ba83 100644
--- a/arch/mips/include/asm/kprobes.h
+++ b/arch/mips/include/asm/kprobes.h
@@ -22,6 +22,9 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/ptrace.h>
 #include <linux/types.h>
 
@@ -94,4 +97,5 @@ struct kprobe_ctlblk {
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/mn10300/include/asm/kprobes.h b/arch/mn10300/include/asm/kprobes.h
index c800b590183a..5729bb5b972a 100644
--- a/arch/mn10300/include/asm/kprobes.h
+++ b/arch/mn10300/include/asm/kprobes.h
@@ -21,6 +21,9 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 
@@ -47,4 +50,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 extern void arch_remove_kprobe(struct kprobe *p);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_KPROBES_H */
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index ee6220dac1e8..d6ce7edee7e0 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -66,3 +66,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index ceafe458e295..1bf89a67317c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -74,3 +74,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 99211477bfb2..982886ba812a 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h
index 2c9759bdb63b..e5d0dc5c6236 100644
--- a/arch/powerpc/include/asm/kprobes.h
+++ b/arch/powerpc/include/asm/kprobes.h
@@ -1,5 +1,9 @@
 #ifndef _ASM_POWERPC_KPROBES_H
 #define _ASM_POWERPC_KPROBES_H
+
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #ifdef __KERNEL__
 /*
  *  Kernel Probes (KProbes)
@@ -127,5 +131,7 @@ struct kprobe_ctlblk {
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 					unsigned long val, void *data);
 extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
+
 #endif /* __KERNEL__ */
+#endif /* CONFIG_KPROBES */
 #endif	/* _ASM_POWERPC_KPROBES_H */
diff --git a/arch/s390/include/asm/kprobes.h b/arch/s390/include/asm/kprobes.h
index 591e5a5279b0..dc12b0135007 100644
--- a/arch/s390/include/asm/kprobes.h
+++ b/arch/s390/include/asm/kprobes.h
@@ -27,6 +27,9 @@
  * 2005-Dec	Used as a template for s390 by Mike Grundy
  *		<grundym@us.ibm.com>
  */
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -91,4 +94,5 @@ int probe_is_insn_relative_long(u16 *insn);
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif	/* _ASM_S390_KPROBES_H */
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index 16ea15a3e432..6ac8a7f5c768 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -17,3 +17,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h
index 134f3980e44a..0b9a54016eeb 100644
--- a/arch/sh/include/asm/kprobes.h
+++ b/arch/sh/include/asm/kprobes.h
@@ -1,6 +1,8 @@
 #ifndef __ASM_SH_KPROBES_H
 #define __ASM_SH_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
 #ifdef CONFIG_KPROBES
 
 #include <linux/types.h>
diff --git a/arch/sparc/include/asm/kprobes.h b/arch/sparc/include/asm/kprobes.h
index a145d798e112..8c4cd15395f6 100644
--- a/arch/sparc/include/asm/kprobes.h
+++ b/arch/sparc/include/asm/kprobes.h
@@ -1,6 +1,9 @@
 #ifndef _SPARC64_KPROBES_H
 #define _SPARC64_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/percpu.h>
 
@@ -48,4 +51,6 @@ int kprobe_exceptions_notify(struct notifier_block *self,
 int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
 				      struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _SPARC64_KPROBES_H */
diff --git a/arch/tile/include/asm/kprobes.h b/arch/tile/include/asm/kprobes.h
index d8f9a83943b1..4a8b1cadca24 100644
--- a/arch/tile/include/asm/kprobes.h
+++ b/arch/tile/include/asm/kprobes.h
@@ -17,10 +17,13 @@
 #ifndef _ASM_TILE_KPROBES_H
 #define _ASM_TILE_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
-
 #include <arch/opcode.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
@@ -76,4 +79,5 @@ void arch_remove_kprobe(struct kprobe *);
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 			     unsigned long val, void *data);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_TILE_KPROBES_H */
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index eea5dd842992..f0314517090b 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -30,3 +30,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 5c31eafbf1fd..32321579011b 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -66,3 +66,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h
index d1d1e5094c28..95c480dc8570 100644
--- a/arch/x86/include/asm/kprobes.h
+++ b/arch/x86/include/asm/kprobes.h
@@ -21,6 +21,10 @@
  *
  * See arch/x86/kernel/kprobes.c for x86 kprobes history.
  */
+
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -116,4 +120,6 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 extern int kprobe_int3_handler(struct pt_regs *regs);
 extern int kprobe_debug_handler(struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_X86_KPROBES_H */
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index ae48f8fd9212..bf0e40100fda 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -34,3 +34,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
new file mode 100644
index 000000000000..57af9f21d148
--- /dev/null
+++ b/include/asm-generic/kprobes.h
@@ -0,0 +1,25 @@
+#ifndef _ASM_GENERIC_KPROBES_H
+#define _ASM_GENERIC_KPROBES_H
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#ifdef CONFIG_KPROBES
+/*
+ * Blacklist ganerating macro. Specify functions which is not probed
+ * by using this macro.
+ */
+# define __NOKPROBE_SYMBOL(fname)				\
+static unsigned long __used					\
+	__attribute__((__section__("_kprobe_blacklist")))	\
+	_kbl_addr_##fname = (unsigned long)fname;
+# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
+/* Use this to forbid a kprobes attach on very low level functions */
+# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define nokprobe_inline	__always_inline
+#else
+# define NOKPROBE_SYMBOL(fname)
+# define __kprobes
+# define nokprobe_inline	inline
+#endif
+#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
+
+#endif /* _ASM_GENERIC_KPROBES_H */
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 1eed7f5e137d..4736dc5741e4 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -542,12 +542,4 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 	(_________p1); \
 })
 
-/* Ignore/forbid kprobes attach on very low level functions marked by this attribute: */
-#ifdef CONFIG_KPROBES
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
-# define nokprobe_inline	__always_inline
-#else
-# define __kprobes
-# define nokprobe_inline	inline
-#endif
 #endif /* __LINUX_COMPILER_H */
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 8f6849084248..985ed79ef431 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -29,7 +29,7 @@
  *		<jkenisto@us.ibm.com>  and Prasanna S Panchamukhi
  *		<prasanna@in.ibm.com> added function-return probes.
  */
-#include <linux/compiler.h>	/* for __kprobes */
+#include <linux/compiler.h>
 #include <linux/linkage.h>
 #include <linux/list.h>
 #include <linux/notifier.h>
@@ -40,9 +40,9 @@
 #include <linux/rcupdate.h>
 #include <linux/mutex.h>
 #include <linux/ftrace.h>
+#include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
-#include <asm/kprobes.h>
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
@@ -51,6 +51,7 @@
 #define KPROBE_HIT_SSDONE	0x00000008
 
 #else /* CONFIG_KPROBES */
+#include <asm-generic/kprobes.h>
 typedef int kprobe_opcode_t;
 struct arch_specific_insn {
 	int dummy;
@@ -481,18 +482,4 @@ static inline int enable_jprobe(struct jprobe *jp)
 	return enable_kprobe(&jp->kp);
 }
 
-#ifdef CONFIG_KPROBES
-/*
- * Blacklist ganerating macro. Specify functions which is not probed
- * by using this macro.
- */
-#define __NOKPROBE_SYMBOL(fname)			\
-static unsigned long __used				\
-	__attribute__((section("_kprobe_blacklist")))	\
-	_kbl_addr_##fname = (unsigned long)fname;
-#define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
-#else
-#define NOKPROBE_SYMBOL(fname)
-#endif
-
 #endif /* _LINUX_KPROBES_H */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 14/16] kprobes: move kprobe declarations to asm-generic/kprobes.h
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Often all is needed is these small helpers, instead of compiler.h
or a full kprobes.h. This is important for asm helpers, in fact even
some asm/kprobes.h make use of these helpers... instead just keep a
generic asm file with helpers useful for asm code with the least amount
of clutter as possible.

Likewise we need now to also address what to do about this file for both
when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
for when architectures have CONFIG_HAVE_KPROBES but have disabled
CONFIG_KPROBES.

Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
this means most architecture code cannot include asm/kprobes.h safely.
Correct this and add guards for architectures missing them. Additionally
provide architectures that not have kprobes support with the default
asm-generic solution. This lets us force asm/kprobes.h on the header
include/linux/kprobes.h always, but most importantly we can now safely
include just asm/kprobes.h on architecture code without bringing
the full kitchen sink of header files.

Two architectures already provided a guard against CONFIG_KPROBES on
its kprobes.h: sh, arch. The rest of the architectures needed gaurds
added. We avoid including any not-needed headers on asm/kprobes.h
unless kprobes have been enabled.

In a subsequent atomic change we can try now to remove compiler.h from
include/linux/kprobes.h.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/alpha/include/asm/Kbuild      |  1 +
 arch/arc/include/asm/kprobes.h     |  6 ++++--
 arch/arm/include/asm/kprobes.h     |  4 ++++
 arch/arm/probes/decode.h           |  1 +
 arch/arm64/include/asm/kprobes.h   |  4 ++++
 arch/arm64/kernel/insn.c           |  1 +
 arch/avr32/include/asm/kprobes.h   |  4 ++++
 arch/blackfin/include/asm/Kbuild   |  1 +
 arch/c6x/include/asm/Kbuild        |  1 +
 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/kprobes.h    |  7 ++++++-
 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/kprobes.h    |  6 +++++-
 arch/mn10300/include/asm/kprobes.h |  4 ++++
 arch/nios2/include/asm/Kbuild      |  1 +
 arch/openrisc/include/asm/Kbuild   |  1 +
 arch/parisc/include/asm/Kbuild     |  1 +
 arch/powerpc/include/asm/kprobes.h |  6 ++++++
 arch/s390/include/asm/kprobes.h    |  4 ++++
 arch/score/include/asm/Kbuild      |  1 +
 arch/sh/include/asm/kprobes.h      |  2 ++
 arch/sparc/include/asm/kprobes.h   |  5 +++++
 arch/tile/include/asm/kprobes.h    |  6 +++++-
 arch/um/include/asm/Kbuild         |  1 +
 arch/unicore32/include/asm/Kbuild  |  1 +
 arch/x86/include/asm/kprobes.h     |  6 ++++++
 arch/xtensa/include/asm/Kbuild     |  1 +
 include/asm-generic/kprobes.h      | 25 +++++++++++++++++++++++++
 include/linux/compiler.h           |  8 --------
 include/linux/kprobes.h            | 19 +++----------------
 36 files changed, 107 insertions(+), 29 deletions(-)
 create mode 100644 include/asm-generic/kprobes.h

diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index f3bdc31d3c97..54d388fd026f 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += trace_clock.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/arc/include/asm/kprobes.h b/arch/arc/include/asm/kprobes.h
index 944dbedb38b5..00bdbe167615 100644
--- a/arch/arc/include/asm/kprobes.h
+++ b/arch/arc/include/asm/kprobes.h
@@ -9,6 +9,8 @@
 #ifndef _ARC_KPROBES_H
 #define _ARC_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
 #ifdef CONFIG_KPROBES
 
 typedef u16 kprobe_opcode_t;
@@ -55,6 +57,6 @@ void trap_is_kprobe(unsigned long address, struct pt_regs *regs);
 static void trap_is_kprobe(unsigned long address, struct pt_regs *regs)
 {
 }
-#endif
+#endif /* CONFIG_KPROBES */
 
-#endif
+#endif /* _ARC_KPROBES_H */
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index 3ea9be559726..59655459da59 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/notifier.h>
@@ -83,4 +86,5 @@ struct arch_optimized_insn {
 	 */
 };
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm/probes/decode.h b/arch/arm/probes/decode.h
index f9b08ba7fe73..548d622a3159 100644
--- a/arch/arm/probes/decode.h
+++ b/arch/arm/probes/decode.h
@@ -22,6 +22,7 @@
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <asm/probes.h>
+#include <asm/kprobes.h>
 
 void __init arm_probes_decode_init(void);
 
diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
index 1737aecfcc5e..6deb8d726041 100644
--- a/arch/arm64/include/asm/kprobes.h
+++ b/arch/arm64/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -57,4 +60,5 @@ int kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr);
 void kretprobe_trampoline(void);
 void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 63f9432d05e8..cc38f3241927 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -32,6 +32,7 @@
 #include <asm/fixmap.h>
 #include <asm/opcodes.h>
 #include <asm/insn.h>
+#include <asm/kprobes.h>
 
 #define AARCH64_INSN_SF_BIT	BIT(31)
 #define AARCH64_INSN_N_BIT	BIT(22)
diff --git a/arch/avr32/include/asm/kprobes.h b/arch/avr32/include/asm/kprobes.h
index 45f563ed73fd..09f39d8749ea 100644
--- a/arch/avr32/include/asm/kprobes.h
+++ b/arch/avr32/include/asm/kprobes.h
@@ -11,6 +11,9 @@
 #ifndef __ASM_AVR32_KPROBES_H
 #define __ASM_AVR32_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 
 typedef u16	kprobe_opcode_t;
@@ -46,4 +49,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif /* __ASM_AVR32_KPROBES_H */
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index b71893b1cd53..f56a68697353 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index cede2a950fbf..c54f7cc1f63e 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
+generic-y += kprobes.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 7062c1be7913..051d355feae3 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 4a59cbda5091..b58b9fc49383 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index d79968d93c12..cfca7de52b37 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -78,3 +78,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index d59ac1c1858b..d7cc35451f30 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/ia64/include/asm/kprobes.h b/arch/ia64/include/asm/kprobes.h
index d5505d6f2382..36999c55f3f2 100644
--- a/arch/ia64/include/asm/kprobes.h
+++ b/arch/ia64/include/asm/kprobes.h
@@ -23,6 +23,10 @@
  * 2005-Apr     Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
  *              <anil.s.keshavamurthy@intel.com> adapted from i386
  */
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -124,4 +128,5 @@ extern void invalidate_stacked_regs(void);
 extern void flush_register_stack(void);
 extern void arch_remove_kprobe(struct kprobe *p);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 24088f3c733c..198ad591ab41 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 65c0df17f70e..ae86bb91e13b 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -38,3 +38,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 2538224899fd..10f36ed301e1 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -59,3 +59,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index 01afb1b420f5..865ce3d96443 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/mips/include/asm/kprobes.h b/arch/mips/include/asm/kprobes.h
index daba1f9a4f79..291846d9ba83 100644
--- a/arch/mips/include/asm/kprobes.h
+++ b/arch/mips/include/asm/kprobes.h
@@ -22,6 +22,9 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/ptrace.h>
 #include <linux/types.h>
 
@@ -94,4 +97,5 @@ struct kprobe_ctlblk {
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/mn10300/include/asm/kprobes.h b/arch/mn10300/include/asm/kprobes.h
index c800b590183a..5729bb5b972a 100644
--- a/arch/mn10300/include/asm/kprobes.h
+++ b/arch/mn10300/include/asm/kprobes.h
@@ -21,6 +21,9 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 
@@ -47,4 +50,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 extern void arch_remove_kprobe(struct kprobe *p);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_KPROBES_H */
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index ee6220dac1e8..d6ce7edee7e0 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -66,3 +66,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index ceafe458e295..1bf89a67317c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -74,3 +74,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 99211477bfb2..982886ba812a 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h
index 2c9759bdb63b..e5d0dc5c6236 100644
--- a/arch/powerpc/include/asm/kprobes.h
+++ b/arch/powerpc/include/asm/kprobes.h
@@ -1,5 +1,9 @@
 #ifndef _ASM_POWERPC_KPROBES_H
 #define _ASM_POWERPC_KPROBES_H
+
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #ifdef __KERNEL__
 /*
  *  Kernel Probes (KProbes)
@@ -127,5 +131,7 @@ struct kprobe_ctlblk {
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 					unsigned long val, void *data);
 extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
+
 #endif /* __KERNEL__ */
+#endif /* CONFIG_KPROBES */
 #endif	/* _ASM_POWERPC_KPROBES_H */
diff --git a/arch/s390/include/asm/kprobes.h b/arch/s390/include/asm/kprobes.h
index 591e5a5279b0..dc12b0135007 100644
--- a/arch/s390/include/asm/kprobes.h
+++ b/arch/s390/include/asm/kprobes.h
@@ -27,6 +27,9 @@
  * 2005-Dec	Used as a template for s390 by Mike Grundy
  *		<grundym@us.ibm.com>
  */
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -91,4 +94,5 @@ int probe_is_insn_relative_long(u16 *insn);
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif	/* _ASM_S390_KPROBES_H */
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index 16ea15a3e432..6ac8a7f5c768 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -17,3 +17,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h
index 134f3980e44a..0b9a54016eeb 100644
--- a/arch/sh/include/asm/kprobes.h
+++ b/arch/sh/include/asm/kprobes.h
@@ -1,6 +1,8 @@
 #ifndef __ASM_SH_KPROBES_H
 #define __ASM_SH_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
 #ifdef CONFIG_KPROBES
 
 #include <linux/types.h>
diff --git a/arch/sparc/include/asm/kprobes.h b/arch/sparc/include/asm/kprobes.h
index a145d798e112..8c4cd15395f6 100644
--- a/arch/sparc/include/asm/kprobes.h
+++ b/arch/sparc/include/asm/kprobes.h
@@ -1,6 +1,9 @@
 #ifndef _SPARC64_KPROBES_H
 #define _SPARC64_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/percpu.h>
 
@@ -48,4 +51,6 @@ int kprobe_exceptions_notify(struct notifier_block *self,
 int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
 				      struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _SPARC64_KPROBES_H */
diff --git a/arch/tile/include/asm/kprobes.h b/arch/tile/include/asm/kprobes.h
index d8f9a83943b1..4a8b1cadca24 100644
--- a/arch/tile/include/asm/kprobes.h
+++ b/arch/tile/include/asm/kprobes.h
@@ -17,10 +17,13 @@
 #ifndef _ASM_TILE_KPROBES_H
 #define _ASM_TILE_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
-
 #include <arch/opcode.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
@@ -76,4 +79,5 @@ void arch_remove_kprobe(struct kprobe *);
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 			     unsigned long val, void *data);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_TILE_KPROBES_H */
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index eea5dd842992..f0314517090b 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -30,3 +30,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 5c31eafbf1fd..32321579011b 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -66,3 +66,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h
index d1d1e5094c28..95c480dc8570 100644
--- a/arch/x86/include/asm/kprobes.h
+++ b/arch/x86/include/asm/kprobes.h
@@ -21,6 +21,10 @@
  *
  * See arch/x86/kernel/kprobes.c for x86 kprobes history.
  */
+
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -116,4 +120,6 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 extern int kprobe_int3_handler(struct pt_regs *regs);
 extern int kprobe_debug_handler(struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_X86_KPROBES_H */
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index ae48f8fd9212..bf0e40100fda 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -34,3 +34,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
new file mode 100644
index 000000000000..57af9f21d148
--- /dev/null
+++ b/include/asm-generic/kprobes.h
@@ -0,0 +1,25 @@
+#ifndef _ASM_GENERIC_KPROBES_H
+#define _ASM_GENERIC_KPROBES_H
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#ifdef CONFIG_KPROBES
+/*
+ * Blacklist ganerating macro. Specify functions which is not probed
+ * by using this macro.
+ */
+# define __NOKPROBE_SYMBOL(fname)				\
+static unsigned long __used					\
+	__attribute__((__section__("_kprobe_blacklist")))	\
+	_kbl_addr_##fname = (unsigned long)fname;
+# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
+/* Use this to forbid a kprobes attach on very low level functions */
+# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define nokprobe_inline	__always_inline
+#else
+# define NOKPROBE_SYMBOL(fname)
+# define __kprobes
+# define nokprobe_inline	inline
+#endif
+#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
+
+#endif /* _ASM_GENERIC_KPROBES_H */
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 1eed7f5e137d..4736dc5741e4 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -542,12 +542,4 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 	(_________p1); \
 })
 
-/* Ignore/forbid kprobes attach on very low level functions marked by this attribute: */
-#ifdef CONFIG_KPROBES
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
-# define nokprobe_inline	__always_inline
-#else
-# define __kprobes
-# define nokprobe_inline	inline
-#endif
 #endif /* __LINUX_COMPILER_H */
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 8f6849084248..985ed79ef431 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -29,7 +29,7 @@
  *		<jkenisto@us.ibm.com>  and Prasanna S Panchamukhi
  *		<prasanna@in.ibm.com> added function-return probes.
  */
-#include <linux/compiler.h>	/* for __kprobes */
+#include <linux/compiler.h>
 #include <linux/linkage.h>
 #include <linux/list.h>
 #include <linux/notifier.h>
@@ -40,9 +40,9 @@
 #include <linux/rcupdate.h>
 #include <linux/mutex.h>
 #include <linux/ftrace.h>
+#include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
-#include <asm/kprobes.h>
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
@@ -51,6 +51,7 @@
 #define KPROBE_HIT_SSDONE	0x00000008
 
 #else /* CONFIG_KPROBES */
+#include <asm-generic/kprobes.h>
 typedef int kprobe_opcode_t;
 struct arch_specific_insn {
 	int dummy;
@@ -481,18 +482,4 @@ static inline int enable_jprobe(struct jprobe *jp)
 	return enable_kprobe(&jp->kp);
 }
 
-#ifdef CONFIG_KPROBES
-/*
- * Blacklist ganerating macro. Specify functions which is not probed
- * by using this macro.
- */
-#define __NOKPROBE_SYMBOL(fname)			\
-static unsigned long __used				\
-	__attribute__((section("_kprobe_blacklist")))	\
-	_kbl_addr_##fname = (unsigned long)fname;
-#define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
-#else
-#define NOKPROBE_SYMBOL(fname)
-#endif
-
 #endif /* _LINUX_KPROBES_H */
-- 
2.9.2

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 14/16] kprobes: move kprobe declarations to asm-generic/kprobes.h
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Often all is needed is these small helpers, instead of compiler.h
or a full kprobes.h. This is important for asm helpers, in fact even
some asm/kprobes.h make use of these helpers... instead just keep a
generic asm file with helpers useful for asm code with the least amount
of clutter as possible.

Likewise we need now to also address what to do about this file for both
when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
for when architectures have CONFIG_HAVE_KPROBES but have disabled
CONFIG_KPROBES.

Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
this means most architecture code cannot include asm/kprobes.h safely.
Correct this and add guards for architectures missing them. Additionally
provide architectures that not have kprobes support with the default
asm-generic solution. This lets us force asm/kprobes.h on the header
include/linux/kprobes.h always, but most importantly we can now safely
include just asm/kprobes.h on architecture code without bringing
the full kitchen sink of header files.

Two architectures already provided a guard against CONFIG_KPROBES on
its kprobes.h: sh, arch. The rest of the architectures needed gaurds
added. We avoid including any not-needed headers on asm/kprobes.h
unless kprobes have been enabled.

In a subsequent atomic change we can try now to remove compiler.h from
include/linux/kprobes.h.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/alpha/include/asm/Kbuild      |  1 +
 arch/arc/include/asm/kprobes.h     |  6 ++++--
 arch/arm/include/asm/kprobes.h     |  4 ++++
 arch/arm/probes/decode.h           |  1 +
 arch/arm64/include/asm/kprobes.h   |  4 ++++
 arch/arm64/kernel/insn.c           |  1 +
 arch/avr32/include/asm/kprobes.h   |  4 ++++
 arch/blackfin/include/asm/Kbuild   |  1 +
 arch/c6x/include/asm/Kbuild        |  1 +
 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/kprobes.h    |  7 ++++++-
 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/kprobes.h    |  6 +++++-
 arch/mn10300/include/asm/kprobes.h |  4 ++++
 arch/nios2/include/asm/Kbuild      |  1 +
 arch/openrisc/include/asm/Kbuild   |  1 +
 arch/parisc/include/asm/Kbuild     |  1 +
 arch/powerpc/include/asm/kprobes.h |  6 ++++++
 arch/s390/include/asm/kprobes.h    |  4 ++++
 arch/score/include/asm/Kbuild      |  1 +
 arch/sh/include/asm/kprobes.h      |  2 ++
 arch/sparc/include/asm/kprobes.h   |  5 +++++
 arch/tile/include/asm/kprobes.h    |  6 +++++-
 arch/um/include/asm/Kbuild         |  1 +
 arch/unicore32/include/asm/Kbuild  |  1 +
 arch/x86/include/asm/kprobes.h     |  6 ++++++
 arch/xtensa/include/asm/Kbuild     |  1 +
 include/asm-generic/kprobes.h      | 25 +++++++++++++++++++++++++
 include/linux/compiler.h           |  8 --------
 include/linux/kprobes.h            | 19 +++----------------
 36 files changed, 107 insertions(+), 29 deletions(-)
 create mode 100644 include/asm-generic/kprobes.h

diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index f3bdc31d3c97..54d388fd026f 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += trace_clock.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/arc/include/asm/kprobes.h b/arch/arc/include/asm/kprobes.h
index 944dbedb38b5..00bdbe167615 100644
--- a/arch/arc/include/asm/kprobes.h
+++ b/arch/arc/include/asm/kprobes.h
@@ -9,6 +9,8 @@
 #ifndef _ARC_KPROBES_H
 #define _ARC_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
 #ifdef CONFIG_KPROBES
 
 typedef u16 kprobe_opcode_t;
@@ -55,6 +57,6 @@ void trap_is_kprobe(unsigned long address, struct pt_regs *regs);
 static void trap_is_kprobe(unsigned long address, struct pt_regs *regs)
 {
 }
-#endif
+#endif /* CONFIG_KPROBES */
 
-#endif
+#endif /* _ARC_KPROBES_H */
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index 3ea9be559726..59655459da59 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/notifier.h>
@@ -83,4 +86,5 @@ struct arch_optimized_insn {
 	 */
 };
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm/probes/decode.h b/arch/arm/probes/decode.h
index f9b08ba7fe73..548d622a3159 100644
--- a/arch/arm/probes/decode.h
+++ b/arch/arm/probes/decode.h
@@ -22,6 +22,7 @@
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <asm/probes.h>
+#include <asm/kprobes.h>
 
 void __init arm_probes_decode_init(void);
 
diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
index 1737aecfcc5e..6deb8d726041 100644
--- a/arch/arm64/include/asm/kprobes.h
+++ b/arch/arm64/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -57,4 +60,5 @@ int kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr);
 void kretprobe_trampoline(void);
 void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 63f9432d05e8..cc38f3241927 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -32,6 +32,7 @@
 #include <asm/fixmap.h>
 #include <asm/opcodes.h>
 #include <asm/insn.h>
+#include <asm/kprobes.h>
 
 #define AARCH64_INSN_SF_BIT	BIT(31)
 #define AARCH64_INSN_N_BIT	BIT(22)
diff --git a/arch/avr32/include/asm/kprobes.h b/arch/avr32/include/asm/kprobes.h
index 45f563ed73fd..09f39d8749ea 100644
--- a/arch/avr32/include/asm/kprobes.h
+++ b/arch/avr32/include/asm/kprobes.h
@@ -11,6 +11,9 @@
 #ifndef __ASM_AVR32_KPROBES_H
 #define __ASM_AVR32_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 
 typedef u16	kprobe_opcode_t;
@@ -46,4 +49,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif /* __ASM_AVR32_KPROBES_H */
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index b71893b1cd53..f56a68697353 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index cede2a950fbf..c54f7cc1f63e 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
+generic-y += kprobes.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 7062c1be7913..051d355feae3 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 4a59cbda5091..b58b9fc49383 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index d79968d93c12..cfca7de52b37 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -78,3 +78,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index d59ac1c1858b..d7cc35451f30 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/ia64/include/asm/kprobes.h b/arch/ia64/include/asm/kprobes.h
index d5505d6f2382..36999c55f3f2 100644
--- a/arch/ia64/include/asm/kprobes.h
+++ b/arch/ia64/include/asm/kprobes.h
@@ -23,6 +23,10 @@
  * 2005-Apr     Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
  *              <anil.s.keshavamurthy@intel.com> adapted from i386
  */
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -124,4 +128,5 @@ extern void invalidate_stacked_regs(void);
 extern void flush_register_stack(void);
 extern void arch_remove_kprobe(struct kprobe *p);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 24088f3c733c..198ad591ab41 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 65c0df17f70e..ae86bb91e13b 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -38,3 +38,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 2538224899fd..10f36ed301e1 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -59,3 +59,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index 01afb1b420f5..865ce3d96443 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/mips/include/asm/kprobes.h b/arch/mips/include/asm/kprobes.h
index daba1f9a4f79..291846d9ba83 100644
--- a/arch/mips/include/asm/kprobes.h
+++ b/arch/mips/include/asm/kprobes.h
@@ -22,6 +22,9 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/ptrace.h>
 #include <linux/types.h>
 
@@ -94,4 +97,5 @@ struct kprobe_ctlblk {
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/mn10300/include/asm/kprobes.h b/arch/mn10300/include/asm/kprobes.h
index c800b590183a..5729bb5b972a 100644
--- a/arch/mn10300/include/asm/kprobes.h
+++ b/arch/mn10300/include/asm/kprobes.h
@@ -21,6 +21,9 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 
@@ -47,4 +50,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 extern void arch_remove_kprobe(struct kprobe *p);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_KPROBES_H */
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index ee6220dac1e8..d6ce7edee7e0 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -66,3 +66,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index ceafe458e295..1bf89a67317c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -74,3 +74,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 99211477bfb2..982886ba812a 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h
index 2c9759bdb63b..e5d0dc5c6236 100644
--- a/arch/powerpc/include/asm/kprobes.h
+++ b/arch/powerpc/include/asm/kprobes.h
@@ -1,5 +1,9 @@
 #ifndef _ASM_POWERPC_KPROBES_H
 #define _ASM_POWERPC_KPROBES_H
+
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #ifdef __KERNEL__
 /*
  *  Kernel Probes (KProbes)
@@ -127,5 +131,7 @@ struct kprobe_ctlblk {
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 					unsigned long val, void *data);
 extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
+
 #endif /* __KERNEL__ */
+#endif /* CONFIG_KPROBES */
 #endif	/* _ASM_POWERPC_KPROBES_H */
diff --git a/arch/s390/include/asm/kprobes.h b/arch/s390/include/asm/kprobes.h
index 591e5a5279b0..dc12b0135007 100644
--- a/arch/s390/include/asm/kprobes.h
+++ b/arch/s390/include/asm/kprobes.h
@@ -27,6 +27,9 @@
  * 2005-Dec	Used as a template for s390 by Mike Grundy
  *		<grundym@us.ibm.com>
  */
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -91,4 +94,5 @@ int probe_is_insn_relative_long(u16 *insn);
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif	/* _ASM_S390_KPROBES_H */
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index 16ea15a3e432..6ac8a7f5c768 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -17,3 +17,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h
index 134f3980e44a..0b9a54016eeb 100644
--- a/arch/sh/include/asm/kprobes.h
+++ b/arch/sh/include/asm/kprobes.h
@@ -1,6 +1,8 @@
 #ifndef __ASM_SH_KPROBES_H
 #define __ASM_SH_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
 #ifdef CONFIG_KPROBES
 
 #include <linux/types.h>
diff --git a/arch/sparc/include/asm/kprobes.h b/arch/sparc/include/asm/kprobes.h
index a145d798e112..8c4cd15395f6 100644
--- a/arch/sparc/include/asm/kprobes.h
+++ b/arch/sparc/include/asm/kprobes.h
@@ -1,6 +1,9 @@
 #ifndef _SPARC64_KPROBES_H
 #define _SPARC64_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/percpu.h>
 
@@ -48,4 +51,6 @@ int kprobe_exceptions_notify(struct notifier_block *self,
 int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
 				      struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _SPARC64_KPROBES_H */
diff --git a/arch/tile/include/asm/kprobes.h b/arch/tile/include/asm/kprobes.h
index d8f9a83943b1..4a8b1cadca24 100644
--- a/arch/tile/include/asm/kprobes.h
+++ b/arch/tile/include/asm/kprobes.h
@@ -17,10 +17,13 @@
 #ifndef _ASM_TILE_KPROBES_H
 #define _ASM_TILE_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
-
 #include <arch/opcode.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
@@ -76,4 +79,5 @@ void arch_remove_kprobe(struct kprobe *);
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 			     unsigned long val, void *data);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_TILE_KPROBES_H */
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index eea5dd842992..f0314517090b 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -30,3 +30,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 5c31eafbf1fd..32321579011b 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -66,3 +66,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h
index d1d1e5094c28..95c480dc8570 100644
--- a/arch/x86/include/asm/kprobes.h
+++ b/arch/x86/include/asm/kprobes.h
@@ -21,6 +21,10 @@
  *
  * See arch/x86/kernel/kprobes.c for x86 kprobes history.
  */
+
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -116,4 +120,6 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 extern int kprobe_int3_handler(struct pt_regs *regs);
 extern int kprobe_debug_handler(struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_X86_KPROBES_H */
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index ae48f8fd9212..bf0e40100fda 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -34,3 +34,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
new file mode 100644
index 000000000000..57af9f21d148
--- /dev/null
+++ b/include/asm-generic/kprobes.h
@@ -0,0 +1,25 @@
+#ifndef _ASM_GENERIC_KPROBES_H
+#define _ASM_GENERIC_KPROBES_H
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#ifdef CONFIG_KPROBES
+/*
+ * Blacklist ganerating macro. Specify functions which is not probed
+ * by using this macro.
+ */
+# define __NOKPROBE_SYMBOL(fname)				\
+static unsigned long __used					\
+	__attribute__((__section__("_kprobe_blacklist")))	\
+	_kbl_addr_##fname = (unsigned long)fname;
+# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
+/* Use this to forbid a kprobes attach on very low level functions */
+# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define nokprobe_inline	__always_inline
+#else
+# define NOKPROBE_SYMBOL(fname)
+# define __kprobes
+# define nokprobe_inline	inline
+#endif
+#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
+
+#endif /* _ASM_GENERIC_KPROBES_H */
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 1eed7f5e137d..4736dc5741e4 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -542,12 +542,4 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 	(_________p1); \
 })
 
-/* Ignore/forbid kprobes attach on very low level functions marked by this attribute: */
-#ifdef CONFIG_KPROBES
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
-# define nokprobe_inline	__always_inline
-#else
-# define __kprobes
-# define nokprobe_inline	inline
-#endif
 #endif /* __LINUX_COMPILER_H */
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 8f6849084248..985ed79ef431 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -29,7 +29,7 @@
  *		<jkenisto@us.ibm.com>  and Prasanna S Panchamukhi
  *		<prasanna@in.ibm.com> added function-return probes.
  */
-#include <linux/compiler.h>	/* for __kprobes */
+#include <linux/compiler.h>
 #include <linux/linkage.h>
 #include <linux/list.h>
 #include <linux/notifier.h>
@@ -40,9 +40,9 @@
 #include <linux/rcupdate.h>
 #include <linux/mutex.h>
 #include <linux/ftrace.h>
+#include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
-#include <asm/kprobes.h>
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
@@ -51,6 +51,7 @@
 #define KPROBE_HIT_SSDONE	0x00000008
 
 #else /* CONFIG_KPROBES */
+#include <asm-generic/kprobes.h>
 typedef int kprobe_opcode_t;
 struct arch_specific_insn {
 	int dummy;
@@ -481,18 +482,4 @@ static inline int enable_jprobe(struct jprobe *jp)
 	return enable_kprobe(&jp->kp);
 }
 
-#ifdef CONFIG_KPROBES
-/*
- * Blacklist ganerating macro. Specify functions which is not probed
- * by using this macro.
- */
-#define __NOKPROBE_SYMBOL(fname)			\
-static unsigned long __used				\
-	__attribute__((section("_kprobe_blacklist")))	\
-	_kbl_addr_##fname = (unsigned long)fname;
-#define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
-#else
-#define NOKPROBE_SYMBOL(fname)
-#endif
-
 #endif /* _LINUX_KPROBES_H */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 15/16] kprobes: port .kprobes.text to section range
  2016-08-19 21:33   ` mcgrof
  (?)
@ 2016-08-19 21:34     ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

kprobe makes use of two custom sections, each custom section
is folded into one of the standard Linux sections types as follows,
it currently relies on the linker script to fold the custom section
onto the respective Linux section:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist
range .text         .kprobes.text        __kprobes_text_start     __kprobes_text_end

This ports the .kprobes.text custom section to the standard
Linux ranges API allowing us remove all the custom kprobe section
declarations from the linker script.

Tested with CONFIG_KPROBES_SANITY_TEST, it passes with:

Kprobe smoke test: started
Kprobe smoke test: passed successfully

Then tested CONFIG_SAMPLE_KPROBES on do_fork, and the kprobe bites
and kicks as expected.

Also ran ./ftracetest with no issues:

$ sudo ./ftracetest
== Ftrace unit tests =[1] Basic trace file check      [PASS]
[2] Basic test for tracers      [PASS]
[3] Basic trace clock test      [PASS]
[4] Basic event tracing check   [PASS]
[5] event tracing - enable/disable with event level files       [PASS]
[6] event tracing - restricts events based on pid       [PASS]
[7] event tracing - enable/disable with subsystem level files   [PASS]
[8] event tracing - enable/disable with top level files [PASS]
[9] ftrace - function graph filters with stack tracer   [PASS]
[10] ftrace - function graph filters    [PASS]
[11] ftrace - function profiler with function tracing   [PASS]
[12] Test creation and deletion of trace instances while setting an event[PASS]
[13] Test creation and deletion of trace instances      [PASS]
[14] Kprobe dynamic event - adding and removing [PASS]
[15] Kprobe dynamic event - busy event check    [PASS]
[16] Kprobe dynamic event with arguments        [PASS]
[17] Kprobe dynamic event with function tracer  [PASS]
[18] Kretprobe dynamic event with arguments     [PASS]
[19] event trigger - test event enable/disable trigger  [PASS]
[20] event trigger - test trigger filter        [PASS]
[21] event trigger - test histogram modifiers   [PASS]
[22] event trigger - test histogram trigger     [PASS]
[23] event trigger - test multiple histogram triggers   [PASS]
[24] event trigger - test snapshot-trigger      [PASS]
[25] event trigger - test stacktrace-trigger    [PASS]
[26] event trigger - test traceon/off trigger   [PASS]

 # of passed:  26
 # of failed:  0
 # of unresolved:  0
 # of untested:  0
 # of unsupported:  0
 # of xfailed:  0
 # of undefined(test bug):  0

v4:

o arm64 build fixes with allmodconfig

o build fix suggested for avr32 with allnoconfig, otherwise we end up with:

arch/avr32/kernel/built-in.o: In function `save_full_context_ex':
(.ex.text+0x1c4): relocation truncated to fit: R_AVR32_16N_PCREL against
symbol `debug_trampoline' defined in .text.rng.kprobes.any section in
arch/avr32/kernel/built-in.o
arch/avr32/kernel/built-in.o: In function `debug_exit_work':
(.text.rng.kprobes.any+0xa8): relocation truncated to fit:
R_AVR32_16N_PCREL against `.ex.text'+3aa
make: *** [Makefile:953: vmlinux] Error 1

o open-code section use on scripts/ code -- folks to prefer the
  simplicity over dealing with having more tool code access kernel
  headers.

o NOPE: include #include <asm-generic/ranges.h> on compiler.h -- solves
  a few 0-day compilation issues

v3:

o after v2 arch/arm/kernel/vmlinux-xip.lds.S got kprobe support,
  this just removes the custom linker script reference to kprobes as
  that is no longer needed with linker tables.

o split kprobe linker table and kprobe section ranges use into
  two separate patches. This should make it easier to review and
  also demos both distinct use types, one a linker table another
  a simple section range.

v2: introduced this patch in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arc/kernel/vmlinux.lds.S        |  1 -
 arch/arm/kernel/entry-armv.S         |  3 ++-
 arch/arm/kernel/vmlinux-xip.lds.S    |  1 -
 arch/arm/kernel/vmlinux.lds.S        |  1 -
 arch/arm64/kernel/armv8_deprecated.c |  1 +
 arch/arm64/kernel/probes/kprobes.c   |  4 ++--
 arch/arm64/kernel/vmlinux.lds.S      |  1 -
 arch/avr32/kernel/entry-avr32b.S     | 13 +++++++++++--
 arch/avr32/kernel/vmlinux.lds.S      |  1 -
 arch/blackfin/kernel/vmlinux.lds.S   |  1 -
 arch/c6x/kernel/vmlinux.lds.S        |  1 -
 arch/hexagon/kernel/vmlinux.lds.S    |  1 -
 arch/ia64/kernel/jprobes.S           |  3 ++-
 arch/ia64/kernel/vmlinux.lds.S       |  1 -
 arch/ia64/lib/flush.S                |  6 +++---
 arch/metag/kernel/vmlinux.lds.S      |  1 -
 arch/microblaze/kernel/vmlinux.lds.S |  1 -
 arch/mips/kernel/vmlinux.lds.S       |  1 -
 arch/mn10300/kernel/vmlinux.lds.S    |  1 -
 arch/nios2/kernel/vmlinux.lds.S      |  1 -
 arch/openrisc/kernel/vmlinux.lds.S   |  1 -
 arch/parisc/kernel/vmlinux.lds.S     |  1 -
 arch/powerpc/include/asm/ppc_asm.h   |  7 ++++---
 arch/powerpc/kernel/vmlinux.lds.S    |  1 -
 arch/s390/kernel/entry.S             |  5 +++--
 arch/s390/kernel/kprobes.c           |  6 +++---
 arch/s390/kernel/mcount.S            |  3 ++-
 arch/s390/kernel/vmlinux.lds.S       |  1 -
 arch/score/kernel/vmlinux.lds.S      |  1 -
 arch/sh/kernel/vmlinux.lds.S         |  1 -
 arch/sparc/kernel/vmlinux.lds.S      |  1 -
 arch/sparc/mm/ultra.S                |  3 ++-
 arch/tile/kernel/vmlinux.lds.S       |  1 -
 arch/x86/kernel/kprobes/core.c       | 11 +++++------
 arch/x86/kernel/vmlinux.lds.S        |  1 -
 include/asm-generic/kprobes.h        |  3 ++-
 include/asm-generic/sections.h       |  2 --
 include/asm-generic/vmlinux.lds.h    |  6 ------
 include/linux/kprobes.h              |  3 +++
 kernel/kprobes.c                     |  6 ++++--
 scripts/mod/modpost.c                |  2 +-
 scripts/recordmcount.c               |  2 +-
 scripts/recordmcount.pl              |  2 +-
 43 files changed, 52 insertions(+), 62 deletions(-)

diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S
index 894e696bddaa..52f23df2b9b6 100644
--- a/arch/arc/kernel/vmlinux.lds.S
+++ b/arch/arc/kernel/vmlinux.lds.S
@@ -98,7 +98,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 9f157e7c51e7..566823b904bd 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -34,6 +34,7 @@
 #include "entry-header.S"
 #include <asm/entry-macro-multi.S>
 #include <asm/probes.h>
+#include <asm/ranges.h>
 
 /*
  * Interrupt handling.
@@ -83,7 +84,7 @@
 	.endm
 
 #ifdef CONFIG_KPROBES
-	.section	.kprobes.text,"ax",%progbits
+	set_section_rng_type(SECTION_TEXT, kprobes, ax, %progbits)
 #else
 	.text
 #endif
diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S
index cba1ec899a69..3aea8834e3d2 100644
--- a/arch/arm/kernel/vmlinux-xip.lds.S
+++ b/arch/arm/kernel/vmlinux-xip.lds.S
@@ -99,7 +99,6 @@ SECTIONS
 			TEXT_TEXT
 			SCHED_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index d24e5dd2aa7a..e88b77d01f0b 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -113,7 +113,6 @@ SECTIONS
 			SCHED_TEXT
 			LOCK_TEXT
 			HYPERVISOR_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index 42ffdb54e162..200c5bfb8d16 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -23,6 +23,7 @@
 #include <asm/traps.h>
 #include <asm/uaccess.h>
 #include <asm/cpufeature.h>
+#include <asm/kprobes.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace-events-emulation.h"
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index c6b0f40620d8..04398745582c 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/stop_machine.h>
 #include <linux/stringify.h>
+#include <linux/ranges.h>
 #include <asm/traps.h>
 #include <asm/ptrace.h>
 #include <asm/cacheflush.h>
@@ -546,8 +547,7 @@ bool arch_within_kprobe_blacklist(unsigned long addr)
 	extern char __idmap_text_start[], __idmap_text_end[];
 	extern char __hyp_idmap_text_start[], __hyp_idmap_text_end[];
 
-	if ((addr >= (unsigned long)__kprobes_text_start &&
-	    addr < (unsigned long)__kprobes_text_end) ||
+	if (SECTION_ADDR_IN_RANGE(kprobes, addr) ||
 	    (addr >= (unsigned long)__entry_text_start &&
 	    addr < (unsigned long)__entry_text_end) ||
 	    (addr >= (unsigned long)__idmap_text_start &&
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 659963d40bb4..cfd8fc58290b 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -123,7 +123,6 @@ SECTIONS
 			TEXT_TEXT
 			SCHED_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			HYPERVISOR_TEXT
 			IDMAP_TEXT
 			HIBERNATE_TEXT
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index 7301f4806bbe..74d82358fae9 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -23,6 +23,7 @@
 #include <asm/sysreg.h>
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
+#include <asm/ranges.h>
 
 #ifdef CONFIG_PREEMPT
 # define preempt_stop		mask_interrupts
@@ -605,7 +606,11 @@ fault_exit_work:
 	brcc	fault_resume_user
 	rjmp	enter_monitor_mode
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(SECTION_TEXT, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	handle_debug, @function
 handle_debug:
 	sub	sp, 4		/* r12_orig */
@@ -826,7 +831,11 @@ irq_level\level:
 	IRQ_LEVEL 2
 	IRQ_LEVEL 3
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(SECTION_TEXT, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	enter_monitor_mode, @function
 enter_monitor_mode:
 	/*
diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S
index a4589176bed5..bf4f3f1f9dbb 100644
--- a/arch/avr32/kernel/vmlinux.lds.S
+++ b/arch/avr32/kernel/vmlinux.lds.S
@@ -49,7 +49,6 @@ SECTIONS
 		_stext = .;
 		*(.ex.text)
 		*(.irq.text)
-		KPROBES_TEXT
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index d920b959ff3a..8f7ca475c549 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -36,7 +36,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 #ifdef CONFIG_ROMKERNEL
 		__sinittext = .;
 		INIT_TEXT
diff --git a/arch/c6x/kernel/vmlinux.lds.S b/arch/c6x/kernel/vmlinux.lds.S
index 50bc10f97bcb..e7aae42f632e 100644
--- a/arch/c6x/kernel/vmlinux.lds.S
+++ b/arch/c6x/kernel/vmlinux.lds.S
@@ -73,7 +73,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S
index 5f268c1071b3..a358b699ec64 100644
--- a/arch/hexagon/kernel/vmlinux.lds.S
+++ b/arch/hexagon/kernel/vmlinux.lds.S
@@ -51,7 +51,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 	}
 	_etext = .;
diff --git a/arch/ia64/kernel/jprobes.S b/arch/ia64/kernel/jprobes.S
index f69389c7be1d..32f497978541 100644
--- a/arch/ia64/kernel/jprobes.S
+++ b/arch/ia64/kernel/jprobes.S
@@ -46,11 +46,12 @@
  */
 #include <asm/asmmacro.h>
 #include <asm/break.h>
+#include <asm/ranges.h>
 
 	/*
 	 * void jprobe_break(void)
 	 */
-	.section .kprobes.text, "ax"
+	set_section_rng(SECTION_TEXT, kprobes, ax)
 ENTRY(jprobe_break)
 	break.m __IA64_BREAK_JPROBE
 END(jprobe_break)
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index dc506b05ffbd..884f36d38989 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -47,7 +47,6 @@ SECTIONS {
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.gnu.linkonce.t*)
 	}
 
diff --git a/arch/ia64/lib/flush.S b/arch/ia64/lib/flush.S
index 9a5a2f9fad13..0b658993ca72 100644
--- a/arch/ia64/lib/flush.S
+++ b/arch/ia64/lib/flush.S
@@ -9,7 +9,7 @@
 
 #include <asm/asmmacro.h>
 #include <asm/export.h>
-
+#include <asm/ranges.h>
 
 	/*
 	 * flush_icache_range(start,end)
@@ -21,7 +21,7 @@
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(SECTION_TEXT, kprobes, ax)
 GLOBAL_ENTRY(flush_icache_range)
 
 	.prologue
@@ -74,7 +74,7 @@ EXPORT_SYMBOL_GPL(flush_icache_range)
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(SECTION_TEXT, kprobes, ax)
 GLOBAL_ENTRY(clflush_cache_range)
 
 	.prologue
diff --git a/arch/metag/kernel/vmlinux.lds.S b/arch/metag/kernel/vmlinux.lds.S
index 150ace92c7ad..bee7031d6b65 100644
--- a/arch/metag/kernel/vmlinux.lds.S
+++ b/arch/metag/kernel/vmlinux.lds.S
@@ -22,7 +22,6 @@ SECTIONS
 	TEXT_TEXT
 	SCHED_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	IRQENTRY_TEXT
 	SOFTIRQENTRY_TEXT
 	*(.text.*)
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
index 0a47f0410554..2da85501a97a 100644
--- a/arch/microblaze/kernel/vmlinux.lds.S
+++ b/arch/microblaze/kernel/vmlinux.lds.S
@@ -34,7 +34,6 @@ SECTIONS {
 		EXIT_CALL
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		. = ALIGN (4) ;
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index a82c178d0bb9..a4c1c9889bdf 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -56,7 +56,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.*)
diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S
index 13c4814c29f8..ead5efc01802 100644
--- a/arch/mn10300/kernel/vmlinux.lds.S
+++ b/arch/mn10300/kernel/vmlinux.lds.S
@@ -31,7 +31,6 @@ SECTIONS
 	TEXT_TEXT
 	SCHED_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0xcb
diff --git a/arch/nios2/kernel/vmlinux.lds.S b/arch/nios2/kernel/vmlinux.lds.S
index e23e89539967..51647b5c45db 100644
--- a/arch/nios2/kernel/vmlinux.lds.S
+++ b/arch/nios2/kernel/vmlinux.lds.S
@@ -40,7 +40,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 	} =0
 	_etext = .;
 
diff --git a/arch/openrisc/kernel/vmlinux.lds.S b/arch/openrisc/kernel/vmlinux.lds.S
index d936de4c07ca..1e09dd42d7fa 100644
--- a/arch/openrisc/kernel/vmlinux.lds.S
+++ b/arch/openrisc/kernel/vmlinux.lds.S
@@ -48,7 +48,6 @@ SECTIONS
 	  TEXT_TEXT
 	  SCHED_TEXT
 	  LOCK_TEXT
-	  KPROBES_TEXT
 	  IRQENTRY_TEXT
 	  SOFTIRQENTRY_TEXT
 	  *(.fixup)
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index f3ead0b6ce46..c48399848674 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -70,7 +70,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.do_softirq)
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index d5d5b5e348f2..2ded7061e090 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,6 +9,7 @@
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
 #include <asm/firmware.h>
+#include <asm/ranges.h>
 
 #ifndef __ASSEMBLY__
 #error __FILE__ should only be used in assembler files
@@ -218,7 +219,7 @@ name: \
 	.localentry name,.-name
 
 #define _KPROBE(name) \
-	.section ".kprobes.text","a"; \
+	set_section_rng(SECTION_TEXT, kprobes, a); \
 	.align 2 ; \
 	.type name,@function; \
 	.globl name; \
@@ -248,7 +249,7 @@ GLUE(.,name):
 #define _GLOBAL_TOC(name) _GLOBAL(name)
 
 #define _KPROBE(name) \
-	.section ".kprobes.text","a"; \
+	set_section_rng(SECTION_TEXT, kprobes, a); \
 	.align 2 ; \
 	.globl name; \
 	.globl GLUE(.,name); \
@@ -280,7 +281,7 @@ n:
 #define _GLOBAL_TOC(name) _GLOBAL(name)
 
 #define _KPROBE(n)	\
-	.section ".kprobes.text","a";	\
+	set_section_rng(SECTION_TEXT, kprobes, a); \
 	.globl	n;	\
 n:
 
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index b5fba689fca6..544856210081 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -53,7 +53,6 @@ SECTIONS
 		*(.text .fixup __ftr_alt_* .ref.text)
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 49a30737adde..6dd5a868db51 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -24,6 +24,7 @@
 #include <asm/setup.h>
 #include <asm/nmi.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
 __PT_R0      =	__PT_GPRS
 __PT_R1      =	__PT_GPRS + 8
@@ -163,7 +164,7 @@ _PIF_WORK	= (_PIF_PER_TRAP)
 		tm	off+\addr, \mask
 	.endm
 
-	.section .kprobes.text, "ax"
+	set_section_rng(SECTION_TEXT, kprobes, ax)
 .Ldummy:
 	/*
 	 * This nop exists only in order to avoid that __switch_to starts at
@@ -981,7 +982,7 @@ ENTRY(restart_int_handler)
 	brc	2,2b
 3:	j	3b
 
-	.section .kprobes.text, "ax"
+	set_section_rng(SECTION_TEXT, kprobes, ax)
 
 #ifdef CONFIG_CHECK_STACK
 /*
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index dd6306c51bd6..3882fa617532 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -287,9 +287,9 @@ static void kprobe_reenter_check(struct kprobe_ctlblk *kcb, struct kprobe *p)
 	case KPROBE_REENTER:
 	default:
 		/*
-		 * A kprobe on the code path to single step an instruction
-		 * is a BUG. The code path resides in the .kprobes.text
-		 * section and is executed with interrupts disabled.
+		 * A kprobe on the code path to single step an instruction is a
+		 * BUG. The code path resides in the kprobes section range and
+		 * is executed with interrupts disabled.
 		 */
 		printk(KERN_EMERG "Invalid kprobe detected at %p.\n", p->addr);
 		dump_kprobe(p);
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S
index 9a17e4475d27..e766ba4f60ca 100644
--- a/arch/s390/kernel/mcount.S
+++ b/arch/s390/kernel/mcount.S
@@ -10,8 +10,9 @@
 #include <asm/ftrace.h>
 #include <asm/ptrace.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
-	.section .kprobes.text, "ax"
+	set_section_rng(SECTION_TEXT, kprobes, ax)
 
 ENTRY(ftrace_stub)
 	br	%r14
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 429bfd111961..33b0baf2233c 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -36,7 +36,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/score/kernel/vmlinux.lds.S b/arch/score/kernel/vmlinux.lds.S
index 7274b5c4287e..36ebcb3b1215 100644
--- a/arch/score/kernel/vmlinux.lds.S
+++ b/arch/score/kernel/vmlinux.lds.S
@@ -41,7 +41,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.text.*)
 		*(.fixup)
 		. = ALIGN (4) ;
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 235a4101999f..d8ae0a60cdf2 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -37,7 +37,6 @@ SECTIONS
 		EXTRA_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index d79b3b734245..017eb4d7ccca 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -50,7 +50,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.gnu.warning)
diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S
index b4f4733abc6e..194c16d0dcb4 100644
--- a/arch/sparc/mm/ultra.S
+++ b/arch/sparc/mm/ultra.S
@@ -16,6 +16,7 @@
 #include <asm/cacheflush.h>
 #include <asm/hypervisor.h>
 #include <asm/cpudata.h>
+#include <asm/ranges.h>
 
 	/* Basically, most of the Spitfire vs. Cheetah madness
 	 * has to do with the fact that Cheetah does not support
@@ -148,7 +149,7 @@ __spitfire_flush_tlb_mm_slow:
 /*
  * The following code flushes one page_size worth.
  */
-	.section .kprobes.text, "ax"
+	set_section_rng(SECTION_TEXT, kprobes, ax)
 	.align		32
 	.globl		__flush_icache_page
 __flush_icache_page:	/* %o0 = phys_page */
diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S
index 9d449caf8910..c222cea90b7a 100644
--- a/arch/tile/kernel/vmlinux.lds.S
+++ b/arch/tile/kernel/vmlinux.lds.S
@@ -43,7 +43,6 @@ SECTIONS
     HEAD_TEXT
     SCHED_TEXT
     LOCK_TEXT
-    KPROBES_TEXT
     IRQENTRY_TEXT
     SOFTIRQENTRY_TEXT
     __fix_text_end = .;   /* tile-cpack won't rearrange before this */
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index 7847e5c0e0b5..5a08b2e7196d 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -579,9 +579,9 @@ static int reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
 	case KPROBE_REENTER:
 		/* A probe has been hit in the codepath leading up to, or just
 		 * after, single-stepping of a probed instruction. This entire
-		 * codepath should strictly reside in .kprobes.text section.
-		 * Raise a BUG or we'll continue in an endless reentering loop
-		 * and eventually a stack overflow.
+		 * codepath should strictly reside in the kprobes section
+		 * range. Raise a BUG or we'll continue in an endless
+		 * reentering loop and eventually a stack overflow.
 		 */
 		printk(KERN_WARNING "Unrecoverable kprobe detected at %p.\n",
 		       p->addr);
@@ -1128,10 +1128,9 @@ NOKPROBE_SYMBOL(longjmp_break_handler);
 
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
-	return  (addr >= (unsigned long)__kprobes_text_start &&
-		 addr < (unsigned long)__kprobes_text_end) ||
+	return  (SECTION_ADDR_IN_RANGE(kprobes, addr) ||
 		(addr >= (unsigned long)__entry_text_start &&
-		 addr < (unsigned long)__entry_text_end);
+		 addr < (unsigned long)__entry_text_end));
 }
 
 int __init arch_init_kprobes(void)
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 9297a002d8e5..8a5dfa38fde3 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -98,7 +98,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		ENTRY_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 57af9f21d148..7b986f4b7ccd 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,6 +3,7 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
@@ -13,7 +14,7 @@ static unsigned long __used					\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define __kprobes	__LINUX_RANGE(SECTION_TEXT, kprobes)
 # define nokprobe_inline	__always_inline
 #else
 # define NOKPROBE_SYMBOL(fname)
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 298252df3c81..742b9d903461 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -24,7 +24,6 @@
  * Following global variables are optional and may be unavailable on some
  * architectures and/or kernel configurations.
  *	_text, _data
- *	__kprobes_text_start, __kprobes_text_end
  *	__entry_text_start, __entry_text_end
  *	__ctors_start, __ctors_end
  */
@@ -35,7 +34,6 @@ extern char __init_begin[], __init_end[];
 extern char _sinittext[], _einittext[];
 extern char _end[];
 extern char __per_cpu_load[], __per_cpu_start[], __per_cpu_end[];
-extern char __kprobes_text_start[], __kprobes_text_end[];
 extern char __entry_text_start[], __entry_text_end[];
 extern char __start_rodata[], __end_rodata[];
 
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index ba49b7ad7af2..f2444d82d02a 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -449,12 +449,6 @@
 		*(.spinlock.text)					\
 		VMLINUX_SYMBOL(__lock_text_end) = .;
 
-#define KPROBES_TEXT							\
-		ALIGN_FUNCTION();					\
-		VMLINUX_SYMBOL(__kprobes_text_start) = .;		\
-		*(.kprobes.text)					\
-		VMLINUX_SYMBOL(__kprobes_text_end) = .;
-
 #define ENTRY_TEXT							\
 		ALIGN_FUNCTION();					\
 		VMLINUX_SYMBOL(__entry_text_start) = .;			\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 985ed79ef431..445cc6fe7afa 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -43,6 +43,9 @@
 #include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
+#include <linux/ranges.h>
+
+DECLARE_SECTION_RANGE(kprobes);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index d10ab6b9b5e0..387605682622 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1328,8 +1328,7 @@ out:
 bool __weak arch_within_kprobe_blacklist(unsigned long addr)
 {
 	/* The __kprobes marked functions and entry code must not be probed */
-	return addr >= (unsigned long)__kprobes_text_start &&
-	       addr < (unsigned long)__kprobes_text_end;
+	return SECTION_ADDR_IN_RANGE(kprobes, addr);
 }
 
 bool within_kprobe_blacklist(unsigned long addr)
@@ -2129,6 +2128,9 @@ static struct notifier_block kprobe_module_nb = {
 extern unsigned long __start_kprobe_blacklist[];
 extern unsigned long __stop_kprobe_blacklist[];
 
+/* Actual kprobes section range */
+DEFINE_SECTION_RANGE(kprobes, SECTION_TEXT);
+
 static int __init init_kprobes(void)
 {
 	int i, err = 0;
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 48958d3cec9e..1a50a83304d3 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -888,7 +888,7 @@ static void check_section(const char *modname, struct elf_info *elf,
 
 #define DATA_SECTIONS ".data", ".data.rel"
 #define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \
-		".kprobes.text"
+		".text.rng.kprobes.any"
 #define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
 		".fixup", ".entry.text", ".exception.text", ".text.*", \
 		".coldtext"
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 42396a74405d..7f66cce79612 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -363,7 +363,7 @@ is_mcounted_section_name(char const *const txtname)
 		strcmp(".sched.text",    txtname) = 0 ||
 		strcmp(".spinlock.text", txtname) = 0 ||
 		strcmp(".irqentry.text", txtname) = 0 ||
-		strcmp(".kprobes.text", txtname) = 0 ||
+		strcmp(".text.rng.kprobes.any", txtname) = 0 ||
 		strcmp(".text.unlikely", txtname) = 0;
 }
 
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 96e2486a6fc4..f663a7c5d6ab 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -134,7 +134,7 @@ my %text_sections = (
      ".sched.text" => 1,
      ".spinlock.text" => 1,
      ".irqentry.text" => 1,
-     ".kprobes.text" => 1,
+     ".text.rng.kprobes.any" => 1,
      ".text.unlikely" => 1,
 );
 
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 15/16] kprobes: port .kprobes.text to section range
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

kprobe makes use of two custom sections, each custom section
is folded into one of the standard Linux sections types as follows,
it currently relies on the linker script to fold the custom section
onto the respective Linux section:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist
range .text         .kprobes.text        __kprobes_text_start     __kprobes_text_end

This ports the .kprobes.text custom section to the standard
Linux ranges API allowing us remove all the custom kprobe section
declarations from the linker script.

Tested with CONFIG_KPROBES_SANITY_TEST, it passes with:

Kprobe smoke test: started
Kprobe smoke test: passed successfully

Then tested CONFIG_SAMPLE_KPROBES on do_fork, and the kprobe bites
and kicks as expected.

Also ran ./ftracetest with no issues:

$ sudo ./ftracetest
=== Ftrace unit tests ===
[1] Basic trace file check      [PASS]
[2] Basic test for tracers      [PASS]
[3] Basic trace clock test      [PASS]
[4] Basic event tracing check   [PASS]
[5] event tracing - enable/disable with event level files       [PASS]
[6] event tracing - restricts events based on pid       [PASS]
[7] event tracing - enable/disable with subsystem level files   [PASS]
[8] event tracing - enable/disable with top level files [PASS]
[9] ftrace - function graph filters with stack tracer   [PASS]
[10] ftrace - function graph filters    [PASS]
[11] ftrace - function profiler with function tracing   [PASS]
[12] Test creation and deletion of trace instances while setting an event[PASS]
[13] Test creation and deletion of trace instances      [PASS]
[14] Kprobe dynamic event - adding and removing [PASS]
[15] Kprobe dynamic event - busy event check    [PASS]
[16] Kprobe dynamic event with arguments        [PASS]
[17] Kprobe dynamic event with function tracer  [PASS]
[18] Kretprobe dynamic event with arguments     [PASS]
[19] event trigger - test event enable/disable trigger  [PASS]
[20] event trigger - test trigger filter        [PASS]
[21] event trigger - test histogram modifiers   [PASS]
[22] event trigger - test histogram trigger     [PASS]
[23] event trigger - test multiple histogram triggers   [PASS]
[24] event trigger - test snapshot-trigger      [PASS]
[25] event trigger - test stacktrace-trigger    [PASS]
[26] event trigger - test traceon/off trigger   [PASS]

 # of passed:  26
 # of failed:  0
 # of unresolved:  0
 # of untested:  0
 # of unsupported:  0
 # of xfailed:  0
 # of undefined(test bug):  0

v4:

o arm64 build fixes with allmodconfig

o build fix suggested for avr32 with allnoconfig, otherwise we end up with:

arch/avr32/kernel/built-in.o: In function `save_full_context_ex':
(.ex.text+0x1c4): relocation truncated to fit: R_AVR32_16N_PCREL against
symbol `debug_trampoline' defined in .text.rng.kprobes.any section in
arch/avr32/kernel/built-in.o
arch/avr32/kernel/built-in.o: In function `debug_exit_work':
(.text.rng.kprobes.any+0xa8): relocation truncated to fit:
R_AVR32_16N_PCREL against `.ex.text'+3aa
make: *** [Makefile:953: vmlinux] Error 1

o open-code section use on scripts/ code -- folks to prefer the
  simplicity over dealing with having more tool code access kernel
  headers.

o NOPE: include #include <asm-generic/ranges.h> on compiler.h -- solves
  a few 0-day compilation issues

v3:

o after v2 arch/arm/kernel/vmlinux-xip.lds.S got kprobe support,
  this just removes the custom linker script reference to kprobes as
  that is no longer needed with linker tables.

o split kprobe linker table and kprobe section ranges use into
  two separate patches. This should make it easier to review and
  also demos both distinct use types, one a linker table another
  a simple section range.

v2: introduced this patch in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arc/kernel/vmlinux.lds.S        |  1 -
 arch/arm/kernel/entry-armv.S         |  3 ++-
 arch/arm/kernel/vmlinux-xip.lds.S    |  1 -
 arch/arm/kernel/vmlinux.lds.S        |  1 -
 arch/arm64/kernel/armv8_deprecated.c |  1 +
 arch/arm64/kernel/probes/kprobes.c   |  4 ++--
 arch/arm64/kernel/vmlinux.lds.S      |  1 -
 arch/avr32/kernel/entry-avr32b.S     | 13 +++++++++++--
 arch/avr32/kernel/vmlinux.lds.S      |  1 -
 arch/blackfin/kernel/vmlinux.lds.S   |  1 -
 arch/c6x/kernel/vmlinux.lds.S        |  1 -
 arch/hexagon/kernel/vmlinux.lds.S    |  1 -
 arch/ia64/kernel/jprobes.S           |  3 ++-
 arch/ia64/kernel/vmlinux.lds.S       |  1 -
 arch/ia64/lib/flush.S                |  6 +++---
 arch/metag/kernel/vmlinux.lds.S      |  1 -
 arch/microblaze/kernel/vmlinux.lds.S |  1 -
 arch/mips/kernel/vmlinux.lds.S       |  1 -
 arch/mn10300/kernel/vmlinux.lds.S    |  1 -
 arch/nios2/kernel/vmlinux.lds.S      |  1 -
 arch/openrisc/kernel/vmlinux.lds.S   |  1 -
 arch/parisc/kernel/vmlinux.lds.S     |  1 -
 arch/powerpc/include/asm/ppc_asm.h   |  7 ++++---
 arch/powerpc/kernel/vmlinux.lds.S    |  1 -
 arch/s390/kernel/entry.S             |  5 +++--
 arch/s390/kernel/kprobes.c           |  6 +++---
 arch/s390/kernel/mcount.S            |  3 ++-
 arch/s390/kernel/vmlinux.lds.S       |  1 -
 arch/score/kernel/vmlinux.lds.S      |  1 -
 arch/sh/kernel/vmlinux.lds.S         |  1 -
 arch/sparc/kernel/vmlinux.lds.S      |  1 -
 arch/sparc/mm/ultra.S                |  3 ++-
 arch/tile/kernel/vmlinux.lds.S       |  1 -
 arch/x86/kernel/kprobes/core.c       | 11 +++++------
 arch/x86/kernel/vmlinux.lds.S        |  1 -
 include/asm-generic/kprobes.h        |  3 ++-
 include/asm-generic/sections.h       |  2 --
 include/asm-generic/vmlinux.lds.h    |  6 ------
 include/linux/kprobes.h              |  3 +++
 kernel/kprobes.c                     |  6 ++++--
 scripts/mod/modpost.c                |  2 +-
 scripts/recordmcount.c               |  2 +-
 scripts/recordmcount.pl              |  2 +-
 43 files changed, 52 insertions(+), 62 deletions(-)

diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S
index 894e696bddaa..52f23df2b9b6 100644
--- a/arch/arc/kernel/vmlinux.lds.S
+++ b/arch/arc/kernel/vmlinux.lds.S
@@ -98,7 +98,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 9f157e7c51e7..566823b904bd 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -34,6 +34,7 @@
 #include "entry-header.S"
 #include <asm/entry-macro-multi.S>
 #include <asm/probes.h>
+#include <asm/ranges.h>
 
 /*
  * Interrupt handling.
@@ -83,7 +84,7 @@
 	.endm
 
 #ifdef CONFIG_KPROBES
-	.section	.kprobes.text,"ax",%progbits
+	set_section_rng_type(SECTION_TEXT, kprobes, ax, %progbits)
 #else
 	.text
 #endif
diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S
index cba1ec899a69..3aea8834e3d2 100644
--- a/arch/arm/kernel/vmlinux-xip.lds.S
+++ b/arch/arm/kernel/vmlinux-xip.lds.S
@@ -99,7 +99,6 @@ SECTIONS
 			TEXT_TEXT
 			SCHED_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index d24e5dd2aa7a..e88b77d01f0b 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -113,7 +113,6 @@ SECTIONS
 			SCHED_TEXT
 			LOCK_TEXT
 			HYPERVISOR_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index 42ffdb54e162..200c5bfb8d16 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -23,6 +23,7 @@
 #include <asm/traps.h>
 #include <asm/uaccess.h>
 #include <asm/cpufeature.h>
+#include <asm/kprobes.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace-events-emulation.h"
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index c6b0f40620d8..04398745582c 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/stop_machine.h>
 #include <linux/stringify.h>
+#include <linux/ranges.h>
 #include <asm/traps.h>
 #include <asm/ptrace.h>
 #include <asm/cacheflush.h>
@@ -546,8 +547,7 @@ bool arch_within_kprobe_blacklist(unsigned long addr)
 	extern char __idmap_text_start[], __idmap_text_end[];
 	extern char __hyp_idmap_text_start[], __hyp_idmap_text_end[];
 
-	if ((addr >= (unsigned long)__kprobes_text_start &&
-	    addr < (unsigned long)__kprobes_text_end) ||
+	if (SECTION_ADDR_IN_RANGE(kprobes, addr) ||
 	    (addr >= (unsigned long)__entry_text_start &&
 	    addr < (unsigned long)__entry_text_end) ||
 	    (addr >= (unsigned long)__idmap_text_start &&
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 659963d40bb4..cfd8fc58290b 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -123,7 +123,6 @@ SECTIONS
 			TEXT_TEXT
 			SCHED_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			HYPERVISOR_TEXT
 			IDMAP_TEXT
 			HIBERNATE_TEXT
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index 7301f4806bbe..74d82358fae9 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -23,6 +23,7 @@
 #include <asm/sysreg.h>
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
+#include <asm/ranges.h>
 
 #ifdef CONFIG_PREEMPT
 # define preempt_stop		mask_interrupts
@@ -605,7 +606,11 @@ fault_exit_work:
 	brcc	fault_resume_user
 	rjmp	enter_monitor_mode
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(SECTION_TEXT, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	handle_debug, @function
 handle_debug:
 	sub	sp, 4		/* r12_orig */
@@ -826,7 +831,11 @@ irq_level\level:
 	IRQ_LEVEL 2
 	IRQ_LEVEL 3
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(SECTION_TEXT, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	enter_monitor_mode, @function
 enter_monitor_mode:
 	/*
diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S
index a4589176bed5..bf4f3f1f9dbb 100644
--- a/arch/avr32/kernel/vmlinux.lds.S
+++ b/arch/avr32/kernel/vmlinux.lds.S
@@ -49,7 +49,6 @@ SECTIONS
 		_stext = .;
 		*(.ex.text)
 		*(.irq.text)
-		KPROBES_TEXT
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index d920b959ff3a..8f7ca475c549 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -36,7 +36,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 #ifdef CONFIG_ROMKERNEL
 		__sinittext = .;
 		INIT_TEXT
diff --git a/arch/c6x/kernel/vmlinux.lds.S b/arch/c6x/kernel/vmlinux.lds.S
index 50bc10f97bcb..e7aae42f632e 100644
--- a/arch/c6x/kernel/vmlinux.lds.S
+++ b/arch/c6x/kernel/vmlinux.lds.S
@@ -73,7 +73,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S
index 5f268c1071b3..a358b699ec64 100644
--- a/arch/hexagon/kernel/vmlinux.lds.S
+++ b/arch/hexagon/kernel/vmlinux.lds.S
@@ -51,7 +51,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 	}
 	_etext = .;
diff --git a/arch/ia64/kernel/jprobes.S b/arch/ia64/kernel/jprobes.S
index f69389c7be1d..32f497978541 100644
--- a/arch/ia64/kernel/jprobes.S
+++ b/arch/ia64/kernel/jprobes.S
@@ -46,11 +46,12 @@
  */
 #include <asm/asmmacro.h>
 #include <asm/break.h>
+#include <asm/ranges.h>
 
 	/*
 	 * void jprobe_break(void)
 	 */
-	.section .kprobes.text, "ax"
+	set_section_rng(SECTION_TEXT, kprobes, ax)
 ENTRY(jprobe_break)
 	break.m __IA64_BREAK_JPROBE
 END(jprobe_break)
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index dc506b05ffbd..884f36d38989 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -47,7 +47,6 @@ SECTIONS {
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.gnu.linkonce.t*)
 	}
 
diff --git a/arch/ia64/lib/flush.S b/arch/ia64/lib/flush.S
index 9a5a2f9fad13..0b658993ca72 100644
--- a/arch/ia64/lib/flush.S
+++ b/arch/ia64/lib/flush.S
@@ -9,7 +9,7 @@
 
 #include <asm/asmmacro.h>
 #include <asm/export.h>
-
+#include <asm/ranges.h>
 
 	/*
 	 * flush_icache_range(start,end)
@@ -21,7 +21,7 @@
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(SECTION_TEXT, kprobes, ax)
 GLOBAL_ENTRY(flush_icache_range)
 
 	.prologue
@@ -74,7 +74,7 @@ EXPORT_SYMBOL_GPL(flush_icache_range)
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(SECTION_TEXT, kprobes, ax)
 GLOBAL_ENTRY(clflush_cache_range)
 
 	.prologue
diff --git a/arch/metag/kernel/vmlinux.lds.S b/arch/metag/kernel/vmlinux.lds.S
index 150ace92c7ad..bee7031d6b65 100644
--- a/arch/metag/kernel/vmlinux.lds.S
+++ b/arch/metag/kernel/vmlinux.lds.S
@@ -22,7 +22,6 @@ SECTIONS
 	TEXT_TEXT
 	SCHED_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	IRQENTRY_TEXT
 	SOFTIRQENTRY_TEXT
 	*(.text.*)
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
index 0a47f0410554..2da85501a97a 100644
--- a/arch/microblaze/kernel/vmlinux.lds.S
+++ b/arch/microblaze/kernel/vmlinux.lds.S
@@ -34,7 +34,6 @@ SECTIONS {
 		EXIT_CALL
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		. = ALIGN (4) ;
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index a82c178d0bb9..a4c1c9889bdf 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -56,7 +56,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.*)
diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S
index 13c4814c29f8..ead5efc01802 100644
--- a/arch/mn10300/kernel/vmlinux.lds.S
+++ b/arch/mn10300/kernel/vmlinux.lds.S
@@ -31,7 +31,6 @@ SECTIONS
 	TEXT_TEXT
 	SCHED_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0xcb
diff --git a/arch/nios2/kernel/vmlinux.lds.S b/arch/nios2/kernel/vmlinux.lds.S
index e23e89539967..51647b5c45db 100644
--- a/arch/nios2/kernel/vmlinux.lds.S
+++ b/arch/nios2/kernel/vmlinux.lds.S
@@ -40,7 +40,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 	} =0
 	_etext = .;
 
diff --git a/arch/openrisc/kernel/vmlinux.lds.S b/arch/openrisc/kernel/vmlinux.lds.S
index d936de4c07ca..1e09dd42d7fa 100644
--- a/arch/openrisc/kernel/vmlinux.lds.S
+++ b/arch/openrisc/kernel/vmlinux.lds.S
@@ -48,7 +48,6 @@ SECTIONS
 	  TEXT_TEXT
 	  SCHED_TEXT
 	  LOCK_TEXT
-	  KPROBES_TEXT
 	  IRQENTRY_TEXT
 	  SOFTIRQENTRY_TEXT
 	  *(.fixup)
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index f3ead0b6ce46..c48399848674 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -70,7 +70,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.do_softirq)
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index d5d5b5e348f2..2ded7061e090 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,6 +9,7 @@
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
 #include <asm/firmware.h>
+#include <asm/ranges.h>
 
 #ifndef __ASSEMBLY__
 #error __FILE__ should only be used in assembler files
@@ -218,7 +219,7 @@ name: \
 	.localentry name,.-name
 
 #define _KPROBE(name) \
-	.section ".kprobes.text","a"; \
+	set_section_rng(SECTION_TEXT, kprobes, a); \
 	.align 2 ; \
 	.type name,@function; \
 	.globl name; \
@@ -248,7 +249,7 @@ GLUE(.,name):
 #define _GLOBAL_TOC(name) _GLOBAL(name)
 
 #define _KPROBE(name) \
-	.section ".kprobes.text","a"; \
+	set_section_rng(SECTION_TEXT, kprobes, a); \
 	.align 2 ; \
 	.globl name; \
 	.globl GLUE(.,name); \
@@ -280,7 +281,7 @@ n:
 #define _GLOBAL_TOC(name) _GLOBAL(name)
 
 #define _KPROBE(n)	\
-	.section ".kprobes.text","a";	\
+	set_section_rng(SECTION_TEXT, kprobes, a); \
 	.globl	n;	\
 n:
 
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index b5fba689fca6..544856210081 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -53,7 +53,6 @@ SECTIONS
 		*(.text .fixup __ftr_alt_* .ref.text)
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 49a30737adde..6dd5a868db51 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -24,6 +24,7 @@
 #include <asm/setup.h>
 #include <asm/nmi.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
 __PT_R0      =	__PT_GPRS
 __PT_R1      =	__PT_GPRS + 8
@@ -163,7 +164,7 @@ _PIF_WORK	= (_PIF_PER_TRAP)
 		tm	off+\addr, \mask
 	.endm
 
-	.section .kprobes.text, "ax"
+	set_section_rng(SECTION_TEXT, kprobes, ax)
 .Ldummy:
 	/*
 	 * This nop exists only in order to avoid that __switch_to starts at
@@ -981,7 +982,7 @@ ENTRY(restart_int_handler)
 	brc	2,2b
 3:	j	3b
 
-	.section .kprobes.text, "ax"
+	set_section_rng(SECTION_TEXT, kprobes, ax)
 
 #ifdef CONFIG_CHECK_STACK
 /*
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index dd6306c51bd6..3882fa617532 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -287,9 +287,9 @@ static void kprobe_reenter_check(struct kprobe_ctlblk *kcb, struct kprobe *p)
 	case KPROBE_REENTER:
 	default:
 		/*
-		 * A kprobe on the code path to single step an instruction
-		 * is a BUG. The code path resides in the .kprobes.text
-		 * section and is executed with interrupts disabled.
+		 * A kprobe on the code path to single step an instruction is a
+		 * BUG. The code path resides in the kprobes section range and
+		 * is executed with interrupts disabled.
 		 */
 		printk(KERN_EMERG "Invalid kprobe detected at %p.\n", p->addr);
 		dump_kprobe(p);
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S
index 9a17e4475d27..e766ba4f60ca 100644
--- a/arch/s390/kernel/mcount.S
+++ b/arch/s390/kernel/mcount.S
@@ -10,8 +10,9 @@
 #include <asm/ftrace.h>
 #include <asm/ptrace.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
-	.section .kprobes.text, "ax"
+	set_section_rng(SECTION_TEXT, kprobes, ax)
 
 ENTRY(ftrace_stub)
 	br	%r14
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 429bfd111961..33b0baf2233c 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -36,7 +36,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/score/kernel/vmlinux.lds.S b/arch/score/kernel/vmlinux.lds.S
index 7274b5c4287e..36ebcb3b1215 100644
--- a/arch/score/kernel/vmlinux.lds.S
+++ b/arch/score/kernel/vmlinux.lds.S
@@ -41,7 +41,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.text.*)
 		*(.fixup)
 		. = ALIGN (4) ;
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 235a4101999f..d8ae0a60cdf2 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -37,7 +37,6 @@ SECTIONS
 		EXTRA_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index d79b3b734245..017eb4d7ccca 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -50,7 +50,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.gnu.warning)
diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S
index b4f4733abc6e..194c16d0dcb4 100644
--- a/arch/sparc/mm/ultra.S
+++ b/arch/sparc/mm/ultra.S
@@ -16,6 +16,7 @@
 #include <asm/cacheflush.h>
 #include <asm/hypervisor.h>
 #include <asm/cpudata.h>
+#include <asm/ranges.h>
 
 	/* Basically, most of the Spitfire vs. Cheetah madness
 	 * has to do with the fact that Cheetah does not support
@@ -148,7 +149,7 @@ __spitfire_flush_tlb_mm_slow:
 /*
  * The following code flushes one page_size worth.
  */
-	.section .kprobes.text, "ax"
+	set_section_rng(SECTION_TEXT, kprobes, ax)
 	.align		32
 	.globl		__flush_icache_page
 __flush_icache_page:	/* %o0 = phys_page */
diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S
index 9d449caf8910..c222cea90b7a 100644
--- a/arch/tile/kernel/vmlinux.lds.S
+++ b/arch/tile/kernel/vmlinux.lds.S
@@ -43,7 +43,6 @@ SECTIONS
     HEAD_TEXT
     SCHED_TEXT
     LOCK_TEXT
-    KPROBES_TEXT
     IRQENTRY_TEXT
     SOFTIRQENTRY_TEXT
     __fix_text_end = .;   /* tile-cpack won't rearrange before this */
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index 7847e5c0e0b5..5a08b2e7196d 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -579,9 +579,9 @@ static int reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
 	case KPROBE_REENTER:
 		/* A probe has been hit in the codepath leading up to, or just
 		 * after, single-stepping of a probed instruction. This entire
-		 * codepath should strictly reside in .kprobes.text section.
-		 * Raise a BUG or we'll continue in an endless reentering loop
-		 * and eventually a stack overflow.
+		 * codepath should strictly reside in the kprobes section
+		 * range. Raise a BUG or we'll continue in an endless
+		 * reentering loop and eventually a stack overflow.
 		 */
 		printk(KERN_WARNING "Unrecoverable kprobe detected at %p.\n",
 		       p->addr);
@@ -1128,10 +1128,9 @@ NOKPROBE_SYMBOL(longjmp_break_handler);
 
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
-	return  (addr >= (unsigned long)__kprobes_text_start &&
-		 addr < (unsigned long)__kprobes_text_end) ||
+	return  (SECTION_ADDR_IN_RANGE(kprobes, addr) ||
 		(addr >= (unsigned long)__entry_text_start &&
-		 addr < (unsigned long)__entry_text_end);
+		 addr < (unsigned long)__entry_text_end));
 }
 
 int __init arch_init_kprobes(void)
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 9297a002d8e5..8a5dfa38fde3 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -98,7 +98,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		ENTRY_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 57af9f21d148..7b986f4b7ccd 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,6 +3,7 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
@@ -13,7 +14,7 @@ static unsigned long __used					\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define __kprobes	__LINUX_RANGE(SECTION_TEXT, kprobes)
 # define nokprobe_inline	__always_inline
 #else
 # define NOKPROBE_SYMBOL(fname)
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 298252df3c81..742b9d903461 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -24,7 +24,6 @@
  * Following global variables are optional and may be unavailable on some
  * architectures and/or kernel configurations.
  *	_text, _data
- *	__kprobes_text_start, __kprobes_text_end
  *	__entry_text_start, __entry_text_end
  *	__ctors_start, __ctors_end
  */
@@ -35,7 +34,6 @@ extern char __init_begin[], __init_end[];
 extern char _sinittext[], _einittext[];
 extern char _end[];
 extern char __per_cpu_load[], __per_cpu_start[], __per_cpu_end[];
-extern char __kprobes_text_start[], __kprobes_text_end[];
 extern char __entry_text_start[], __entry_text_end[];
 extern char __start_rodata[], __end_rodata[];
 
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index ba49b7ad7af2..f2444d82d02a 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -449,12 +449,6 @@
 		*(.spinlock.text)					\
 		VMLINUX_SYMBOL(__lock_text_end) = .;
 
-#define KPROBES_TEXT							\
-		ALIGN_FUNCTION();					\
-		VMLINUX_SYMBOL(__kprobes_text_start) = .;		\
-		*(.kprobes.text)					\
-		VMLINUX_SYMBOL(__kprobes_text_end) = .;
-
 #define ENTRY_TEXT							\
 		ALIGN_FUNCTION();					\
 		VMLINUX_SYMBOL(__entry_text_start) = .;			\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 985ed79ef431..445cc6fe7afa 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -43,6 +43,9 @@
 #include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
+#include <linux/ranges.h>
+
+DECLARE_SECTION_RANGE(kprobes);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index d10ab6b9b5e0..387605682622 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1328,8 +1328,7 @@ out:
 bool __weak arch_within_kprobe_blacklist(unsigned long addr)
 {
 	/* The __kprobes marked functions and entry code must not be probed */
-	return addr >= (unsigned long)__kprobes_text_start &&
-	       addr < (unsigned long)__kprobes_text_end;
+	return SECTION_ADDR_IN_RANGE(kprobes, addr);
 }
 
 bool within_kprobe_blacklist(unsigned long addr)
@@ -2129,6 +2128,9 @@ static struct notifier_block kprobe_module_nb = {
 extern unsigned long __start_kprobe_blacklist[];
 extern unsigned long __stop_kprobe_blacklist[];
 
+/* Actual kprobes section range */
+DEFINE_SECTION_RANGE(kprobes, SECTION_TEXT);
+
 static int __init init_kprobes(void)
 {
 	int i, err = 0;
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 48958d3cec9e..1a50a83304d3 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -888,7 +888,7 @@ static void check_section(const char *modname, struct elf_info *elf,
 
 #define DATA_SECTIONS ".data", ".data.rel"
 #define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \
-		".kprobes.text"
+		".text.rng.kprobes.any"
 #define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
 		".fixup", ".entry.text", ".exception.text", ".text.*", \
 		".coldtext"
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 42396a74405d..7f66cce79612 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -363,7 +363,7 @@ is_mcounted_section_name(char const *const txtname)
 		strcmp(".sched.text",    txtname) == 0 ||
 		strcmp(".spinlock.text", txtname) == 0 ||
 		strcmp(".irqentry.text", txtname) == 0 ||
-		strcmp(".kprobes.text", txtname) == 0 ||
+		strcmp(".text.rng.kprobes.any", txtname) == 0 ||
 		strcmp(".text.unlikely", txtname) == 0;
 }
 
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 96e2486a6fc4..f663a7c5d6ab 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -134,7 +134,7 @@ my %text_sections = (
      ".sched.text" => 1,
      ".spinlock.text" => 1,
      ".irqentry.text" => 1,
-     ".kprobes.text" => 1,
+     ".text.rng.kprobes.any" => 1,
      ".text.unlikely" => 1,
 );
 
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 15/16] kprobes: port .kprobes.text to section range
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

kprobe makes use of two custom sections, each custom section
is folded into one of the standard Linux sections types as follows,
it currently relies on the linker script to fold the custom section
onto the respective Linux section:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist
range .text         .kprobes.text        __kprobes_text_start     __kprobes_text_end

This ports the .kprobes.text custom section to the standard
Linux ranges API allowing us remove all the custom kprobe section
declarations from the linker script.

Tested with CONFIG_KPROBES_SANITY_TEST, it passes with:

Kprobe smoke test: started
Kprobe smoke test: passed successfully

Then tested CONFIG_SAMPLE_KPROBES on do_fork, and the kprobe bites
and kicks as expected.

Also ran ./ftracetest with no issues:

$ sudo ./ftracetest
=== Ftrace unit tests ===
[1] Basic trace file check      [PASS]
[2] Basic test for tracers      [PASS]
[3] Basic trace clock test      [PASS]
[4] Basic event tracing check   [PASS]
[5] event tracing - enable/disable with event level files       [PASS]
[6] event tracing - restricts events based on pid       [PASS]
[7] event tracing - enable/disable with subsystem level files   [PASS]
[8] event tracing - enable/disable with top level files [PASS]
[9] ftrace - function graph filters with stack tracer   [PASS]
[10] ftrace - function graph filters    [PASS]
[11] ftrace - function profiler with function tracing   [PASS]
[12] Test creation and deletion of trace instances while setting an event[PASS]
[13] Test creation and deletion of trace instances      [PASS]
[14] Kprobe dynamic event - adding and removing [PASS]
[15] Kprobe dynamic event - busy event check    [PASS]
[16] Kprobe dynamic event with arguments        [PASS]
[17] Kprobe dynamic event with function tracer  [PASS]
[18] Kretprobe dynamic event with arguments     [PASS]
[19] event trigger - test event enable/disable trigger  [PASS]
[20] event trigger - test trigger filter        [PASS]
[21] event trigger - test histogram modifiers   [PASS]
[22] event trigger - test histogram trigger     [PASS]
[23] event trigger - test multiple histogram triggers   [PASS]
[24] event trigger - test snapshot-trigger      [PASS]
[25] event trigger - test stacktrace-trigger    [PASS]
[26] event trigger - test traceon/off trigger   [PASS]

 # of passed:  26
 # of failed:  0
 # of unresolved:  0
 # of untested:  0
 # of unsupported:  0
 # of xfailed:  0
 # of undefined(test bug):  0

v4:

o arm64 build fixes with allmodconfig

o build fix suggested for avr32 with allnoconfig, otherwise we end up with:

arch/avr32/kernel/built-in.o: In function `save_full_context_ex':
(.ex.text+0x1c4): relocation truncated to fit: R_AVR32_16N_PCREL against
symbol `debug_trampoline' defined in .text.rng.kprobes.any section in
arch/avr32/kernel/built-in.o
arch/avr32/kernel/built-in.o: In function `debug_exit_work':
(.text.rng.kprobes.any+0xa8): relocation truncated to fit:
R_AVR32_16N_PCREL against `.ex.text'+3aa
make: *** [Makefile:953: vmlinux] Error 1

o open-code section use on scripts/ code -- folks to prefer the
  simplicity over dealing with having more tool code access kernel
  headers.

o NOPE: include #include <asm-generic/ranges.h> on compiler.h -- solves
  a few 0-day compilation issues

v3:

o after v2 arch/arm/kernel/vmlinux-xip.lds.S got kprobe support,
  this just removes the custom linker script reference to kprobes as
  that is no longer needed with linker tables.

o split kprobe linker table and kprobe section ranges use into
  two separate patches. This should make it easier to review and
  also demos both distinct use types, one a linker table another
  a simple section range.

v2: introduced this patch in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arc/kernel/vmlinux.lds.S        |  1 -
 arch/arm/kernel/entry-armv.S         |  3 ++-
 arch/arm/kernel/vmlinux-xip.lds.S    |  1 -
 arch/arm/kernel/vmlinux.lds.S        |  1 -
 arch/arm64/kernel/armv8_deprecated.c |  1 +
 arch/arm64/kernel/probes/kprobes.c   |  4 ++--
 arch/arm64/kernel/vmlinux.lds.S      |  1 -
 arch/avr32/kernel/entry-avr32b.S     | 13 +++++++++++--
 arch/avr32/kernel/vmlinux.lds.S      |  1 -
 arch/blackfin/kernel/vmlinux.lds.S   |  1 -
 arch/c6x/kernel/vmlinux.lds.S        |  1 -
 arch/hexagon/kernel/vmlinux.lds.S    |  1 -
 arch/ia64/kernel/jprobes.S           |  3 ++-
 arch/ia64/kernel/vmlinux.lds.S       |  1 -
 arch/ia64/lib/flush.S                |  6 +++---
 arch/metag/kernel/vmlinux.lds.S      |  1 -
 arch/microblaze/kernel/vmlinux.lds.S |  1 -
 arch/mips/kernel/vmlinux.lds.S       |  1 -
 arch/mn10300/kernel/vmlinux.lds.S    |  1 -
 arch/nios2/kernel/vmlinux.lds.S      |  1 -
 arch/openrisc/kernel/vmlinux.lds.S   |  1 -
 arch/parisc/kernel/vmlinux.lds.S     |  1 -
 arch/powerpc/include/asm/ppc_asm.h   |  7 ++++---
 arch/powerpc/kernel/vmlinux.lds.S    |  1 -
 arch/s390/kernel/entry.S             |  5 +++--
 arch/s390/kernel/kprobes.c           |  6 +++---
 arch/s390/kernel/mcount.S            |  3 ++-
 arch/s390/kernel/vmlinux.lds.S       |  1 -
 arch/score/kernel/vmlinux.lds.S      |  1 -
 arch/sh/kernel/vmlinux.lds.S         |  1 -
 arch/sparc/kernel/vmlinux.lds.S      |  1 -
 arch/sparc/mm/ultra.S                |  3 ++-
 arch/tile/kernel/vmlinux.lds.S       |  1 -
 arch/x86/kernel/kprobes/core.c       | 11 +++++------
 arch/x86/kernel/vmlinux.lds.S        |  1 -
 include/asm-generic/kprobes.h        |  3 ++-
 include/asm-generic/sections.h       |  2 --
 include/asm-generic/vmlinux.lds.h    |  6 ------
 include/linux/kprobes.h              |  3 +++
 kernel/kprobes.c                     |  6 ++++--
 scripts/mod/modpost.c                |  2 +-
 scripts/recordmcount.c               |  2 +-
 scripts/recordmcount.pl              |  2 +-
 43 files changed, 52 insertions(+), 62 deletions(-)

diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S
index 894e696bddaa..52f23df2b9b6 100644
--- a/arch/arc/kernel/vmlinux.lds.S
+++ b/arch/arc/kernel/vmlinux.lds.S
@@ -98,7 +98,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 9f157e7c51e7..566823b904bd 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -34,6 +34,7 @@
 #include "entry-header.S"
 #include <asm/entry-macro-multi.S>
 #include <asm/probes.h>
+#include <asm/ranges.h>
 
 /*
  * Interrupt handling.
@@ -83,7 +84,7 @@
 	.endm
 
 #ifdef CONFIG_KPROBES
-	.section	.kprobes.text,"ax",%progbits
+	set_section_rng_type(SECTION_TEXT, kprobes, ax, %progbits)
 #else
 	.text
 #endif
diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S
index cba1ec899a69..3aea8834e3d2 100644
--- a/arch/arm/kernel/vmlinux-xip.lds.S
+++ b/arch/arm/kernel/vmlinux-xip.lds.S
@@ -99,7 +99,6 @@ SECTIONS
 			TEXT_TEXT
 			SCHED_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index d24e5dd2aa7a..e88b77d01f0b 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -113,7 +113,6 @@ SECTIONS
 			SCHED_TEXT
 			LOCK_TEXT
 			HYPERVISOR_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index 42ffdb54e162..200c5bfb8d16 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -23,6 +23,7 @@
 #include <asm/traps.h>
 #include <asm/uaccess.h>
 #include <asm/cpufeature.h>
+#include <asm/kprobes.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace-events-emulation.h"
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index c6b0f40620d8..04398745582c 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/stop_machine.h>
 #include <linux/stringify.h>
+#include <linux/ranges.h>
 #include <asm/traps.h>
 #include <asm/ptrace.h>
 #include <asm/cacheflush.h>
@@ -546,8 +547,7 @@ bool arch_within_kprobe_blacklist(unsigned long addr)
 	extern char __idmap_text_start[], __idmap_text_end[];
 	extern char __hyp_idmap_text_start[], __hyp_idmap_text_end[];
 
-	if ((addr >= (unsigned long)__kprobes_text_start &&
-	    addr < (unsigned long)__kprobes_text_end) ||
+	if (SECTION_ADDR_IN_RANGE(kprobes, addr) ||
 	    (addr >= (unsigned long)__entry_text_start &&
 	    addr < (unsigned long)__entry_text_end) ||
 	    (addr >= (unsigned long)__idmap_text_start &&
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 659963d40bb4..cfd8fc58290b 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -123,7 +123,6 @@ SECTIONS
 			TEXT_TEXT
 			SCHED_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			HYPERVISOR_TEXT
 			IDMAP_TEXT
 			HIBERNATE_TEXT
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index 7301f4806bbe..74d82358fae9 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -23,6 +23,7 @@
 #include <asm/sysreg.h>
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
+#include <asm/ranges.h>
 
 #ifdef CONFIG_PREEMPT
 # define preempt_stop		mask_interrupts
@@ -605,7 +606,11 @@ fault_exit_work:
 	brcc	fault_resume_user
 	rjmp	enter_monitor_mode
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(SECTION_TEXT, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	handle_debug, @function
 handle_debug:
 	sub	sp, 4		/* r12_orig */
@@ -826,7 +831,11 @@ irq_level\level:
 	IRQ_LEVEL 2
 	IRQ_LEVEL 3
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(SECTION_TEXT, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	enter_monitor_mode, @function
 enter_monitor_mode:
 	/*
diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S
index a4589176bed5..bf4f3f1f9dbb 100644
--- a/arch/avr32/kernel/vmlinux.lds.S
+++ b/arch/avr32/kernel/vmlinux.lds.S
@@ -49,7 +49,6 @@ SECTIONS
 		_stext = .;
 		*(.ex.text)
 		*(.irq.text)
-		KPROBES_TEXT
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index d920b959ff3a..8f7ca475c549 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -36,7 +36,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 #ifdef CONFIG_ROMKERNEL
 		__sinittext = .;
 		INIT_TEXT
diff --git a/arch/c6x/kernel/vmlinux.lds.S b/arch/c6x/kernel/vmlinux.lds.S
index 50bc10f97bcb..e7aae42f632e 100644
--- a/arch/c6x/kernel/vmlinux.lds.S
+++ b/arch/c6x/kernel/vmlinux.lds.S
@@ -73,7 +73,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S
index 5f268c1071b3..a358b699ec64 100644
--- a/arch/hexagon/kernel/vmlinux.lds.S
+++ b/arch/hexagon/kernel/vmlinux.lds.S
@@ -51,7 +51,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 	}
 	_etext = .;
diff --git a/arch/ia64/kernel/jprobes.S b/arch/ia64/kernel/jprobes.S
index f69389c7be1d..32f497978541 100644
--- a/arch/ia64/kernel/jprobes.S
+++ b/arch/ia64/kernel/jprobes.S
@@ -46,11 +46,12 @@
  */
 #include <asm/asmmacro.h>
 #include <asm/break.h>
+#include <asm/ranges.h>
 
 	/*
 	 * void jprobe_break(void)
 	 */
-	.section .kprobes.text, "ax"
+	set_section_rng(SECTION_TEXT, kprobes, ax)
 ENTRY(jprobe_break)
 	break.m __IA64_BREAK_JPROBE
 END(jprobe_break)
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index dc506b05ffbd..884f36d38989 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -47,7 +47,6 @@ SECTIONS {
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.gnu.linkonce.t*)
 	}
 
diff --git a/arch/ia64/lib/flush.S b/arch/ia64/lib/flush.S
index 9a5a2f9fad13..0b658993ca72 100644
--- a/arch/ia64/lib/flush.S
+++ b/arch/ia64/lib/flush.S
@@ -9,7 +9,7 @@
 
 #include <asm/asmmacro.h>
 #include <asm/export.h>
-
+#include <asm/ranges.h>
 
 	/*
 	 * flush_icache_range(start,end)
@@ -21,7 +21,7 @@
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(SECTION_TEXT, kprobes, ax)
 GLOBAL_ENTRY(flush_icache_range)
 
 	.prologue
@@ -74,7 +74,7 @@ EXPORT_SYMBOL_GPL(flush_icache_range)
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(SECTION_TEXT, kprobes, ax)
 GLOBAL_ENTRY(clflush_cache_range)
 
 	.prologue
diff --git a/arch/metag/kernel/vmlinux.lds.S b/arch/metag/kernel/vmlinux.lds.S
index 150ace92c7ad..bee7031d6b65 100644
--- a/arch/metag/kernel/vmlinux.lds.S
+++ b/arch/metag/kernel/vmlinux.lds.S
@@ -22,7 +22,6 @@ SECTIONS
 	TEXT_TEXT
 	SCHED_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	IRQENTRY_TEXT
 	SOFTIRQENTRY_TEXT
 	*(.text.*)
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
index 0a47f0410554..2da85501a97a 100644
--- a/arch/microblaze/kernel/vmlinux.lds.S
+++ b/arch/microblaze/kernel/vmlinux.lds.S
@@ -34,7 +34,6 @@ SECTIONS {
 		EXIT_CALL
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		. = ALIGN (4) ;
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index a82c178d0bb9..a4c1c9889bdf 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -56,7 +56,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.*)
diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S
index 13c4814c29f8..ead5efc01802 100644
--- a/arch/mn10300/kernel/vmlinux.lds.S
+++ b/arch/mn10300/kernel/vmlinux.lds.S
@@ -31,7 +31,6 @@ SECTIONS
 	TEXT_TEXT
 	SCHED_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0xcb
diff --git a/arch/nios2/kernel/vmlinux.lds.S b/arch/nios2/kernel/vmlinux.lds.S
index e23e89539967..51647b5c45db 100644
--- a/arch/nios2/kernel/vmlinux.lds.S
+++ b/arch/nios2/kernel/vmlinux.lds.S
@@ -40,7 +40,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 	} =0
 	_etext = .;
 
diff --git a/arch/openrisc/kernel/vmlinux.lds.S b/arch/openrisc/kernel/vmlinux.lds.S
index d936de4c07ca..1e09dd42d7fa 100644
--- a/arch/openrisc/kernel/vmlinux.lds.S
+++ b/arch/openrisc/kernel/vmlinux.lds.S
@@ -48,7 +48,6 @@ SECTIONS
 	  TEXT_TEXT
 	  SCHED_TEXT
 	  LOCK_TEXT
-	  KPROBES_TEXT
 	  IRQENTRY_TEXT
 	  SOFTIRQENTRY_TEXT
 	  *(.fixup)
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index f3ead0b6ce46..c48399848674 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -70,7 +70,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.do_softirq)
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index d5d5b5e348f2..2ded7061e090 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,6 +9,7 @@
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
 #include <asm/firmware.h>
+#include <asm/ranges.h>
 
 #ifndef __ASSEMBLY__
 #error __FILE__ should only be used in assembler files
@@ -218,7 +219,7 @@ name: \
 	.localentry name,.-name
 
 #define _KPROBE(name) \
-	.section ".kprobes.text","a"; \
+	set_section_rng(SECTION_TEXT, kprobes, a); \
 	.align 2 ; \
 	.type name,@function; \
 	.globl name; \
@@ -248,7 +249,7 @@ GLUE(.,name):
 #define _GLOBAL_TOC(name) _GLOBAL(name)
 
 #define _KPROBE(name) \
-	.section ".kprobes.text","a"; \
+	set_section_rng(SECTION_TEXT, kprobes, a); \
 	.align 2 ; \
 	.globl name; \
 	.globl GLUE(.,name); \
@@ -280,7 +281,7 @@ n:
 #define _GLOBAL_TOC(name) _GLOBAL(name)
 
 #define _KPROBE(n)	\
-	.section ".kprobes.text","a";	\
+	set_section_rng(SECTION_TEXT, kprobes, a); \
 	.globl	n;	\
 n:
 
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index b5fba689fca6..544856210081 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -53,7 +53,6 @@ SECTIONS
 		*(.text .fixup __ftr_alt_* .ref.text)
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 49a30737adde..6dd5a868db51 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -24,6 +24,7 @@
 #include <asm/setup.h>
 #include <asm/nmi.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
 __PT_R0      =	__PT_GPRS
 __PT_R1      =	__PT_GPRS + 8
@@ -163,7 +164,7 @@ _PIF_WORK	= (_PIF_PER_TRAP)
 		tm	off+\addr, \mask
 	.endm
 
-	.section .kprobes.text, "ax"
+	set_section_rng(SECTION_TEXT, kprobes, ax)
 .Ldummy:
 	/*
 	 * This nop exists only in order to avoid that __switch_to starts at
@@ -981,7 +982,7 @@ ENTRY(restart_int_handler)
 	brc	2,2b
 3:	j	3b
 
-	.section .kprobes.text, "ax"
+	set_section_rng(SECTION_TEXT, kprobes, ax)
 
 #ifdef CONFIG_CHECK_STACK
 /*
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index dd6306c51bd6..3882fa617532 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -287,9 +287,9 @@ static void kprobe_reenter_check(struct kprobe_ctlblk *kcb, struct kprobe *p)
 	case KPROBE_REENTER:
 	default:
 		/*
-		 * A kprobe on the code path to single step an instruction
-		 * is a BUG. The code path resides in the .kprobes.text
-		 * section and is executed with interrupts disabled.
+		 * A kprobe on the code path to single step an instruction is a
+		 * BUG. The code path resides in the kprobes section range and
+		 * is executed with interrupts disabled.
 		 */
 		printk(KERN_EMERG "Invalid kprobe detected at %p.\n", p->addr);
 		dump_kprobe(p);
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S
index 9a17e4475d27..e766ba4f60ca 100644
--- a/arch/s390/kernel/mcount.S
+++ b/arch/s390/kernel/mcount.S
@@ -10,8 +10,9 @@
 #include <asm/ftrace.h>
 #include <asm/ptrace.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
-	.section .kprobes.text, "ax"
+	set_section_rng(SECTION_TEXT, kprobes, ax)
 
 ENTRY(ftrace_stub)
 	br	%r14
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 429bfd111961..33b0baf2233c 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -36,7 +36,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/score/kernel/vmlinux.lds.S b/arch/score/kernel/vmlinux.lds.S
index 7274b5c4287e..36ebcb3b1215 100644
--- a/arch/score/kernel/vmlinux.lds.S
+++ b/arch/score/kernel/vmlinux.lds.S
@@ -41,7 +41,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.text.*)
 		*(.fixup)
 		. = ALIGN (4) ;
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 235a4101999f..d8ae0a60cdf2 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -37,7 +37,6 @@ SECTIONS
 		EXTRA_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index d79b3b734245..017eb4d7ccca 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -50,7 +50,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.gnu.warning)
diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S
index b4f4733abc6e..194c16d0dcb4 100644
--- a/arch/sparc/mm/ultra.S
+++ b/arch/sparc/mm/ultra.S
@@ -16,6 +16,7 @@
 #include <asm/cacheflush.h>
 #include <asm/hypervisor.h>
 #include <asm/cpudata.h>
+#include <asm/ranges.h>
 
 	/* Basically, most of the Spitfire vs. Cheetah madness
 	 * has to do with the fact that Cheetah does not support
@@ -148,7 +149,7 @@ __spitfire_flush_tlb_mm_slow:
 /*
  * The following code flushes one page_size worth.
  */
-	.section .kprobes.text, "ax"
+	set_section_rng(SECTION_TEXT, kprobes, ax)
 	.align		32
 	.globl		__flush_icache_page
 __flush_icache_page:	/* %o0 = phys_page */
diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S
index 9d449caf8910..c222cea90b7a 100644
--- a/arch/tile/kernel/vmlinux.lds.S
+++ b/arch/tile/kernel/vmlinux.lds.S
@@ -43,7 +43,6 @@ SECTIONS
     HEAD_TEXT
     SCHED_TEXT
     LOCK_TEXT
-    KPROBES_TEXT
     IRQENTRY_TEXT
     SOFTIRQENTRY_TEXT
     __fix_text_end = .;   /* tile-cpack won't rearrange before this */
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index 7847e5c0e0b5..5a08b2e7196d 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -579,9 +579,9 @@ static int reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
 	case KPROBE_REENTER:
 		/* A probe has been hit in the codepath leading up to, or just
 		 * after, single-stepping of a probed instruction. This entire
-		 * codepath should strictly reside in .kprobes.text section.
-		 * Raise a BUG or we'll continue in an endless reentering loop
-		 * and eventually a stack overflow.
+		 * codepath should strictly reside in the kprobes section
+		 * range. Raise a BUG or we'll continue in an endless
+		 * reentering loop and eventually a stack overflow.
 		 */
 		printk(KERN_WARNING "Unrecoverable kprobe detected at %p.\n",
 		       p->addr);
@@ -1128,10 +1128,9 @@ NOKPROBE_SYMBOL(longjmp_break_handler);
 
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
-	return  (addr >= (unsigned long)__kprobes_text_start &&
-		 addr < (unsigned long)__kprobes_text_end) ||
+	return  (SECTION_ADDR_IN_RANGE(kprobes, addr) ||
 		(addr >= (unsigned long)__entry_text_start &&
-		 addr < (unsigned long)__entry_text_end);
+		 addr < (unsigned long)__entry_text_end));
 }
 
 int __init arch_init_kprobes(void)
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 9297a002d8e5..8a5dfa38fde3 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -98,7 +98,6 @@ SECTIONS
 		TEXT_TEXT
 		SCHED_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		ENTRY_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 57af9f21d148..7b986f4b7ccd 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,6 +3,7 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
@@ -13,7 +14,7 @@ static unsigned long __used					\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define __kprobes	__LINUX_RANGE(SECTION_TEXT, kprobes)
 # define nokprobe_inline	__always_inline
 #else
 # define NOKPROBE_SYMBOL(fname)
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 298252df3c81..742b9d903461 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -24,7 +24,6 @@
  * Following global variables are optional and may be unavailable on some
  * architectures and/or kernel configurations.
  *	_text, _data
- *	__kprobes_text_start, __kprobes_text_end
  *	__entry_text_start, __entry_text_end
  *	__ctors_start, __ctors_end
  */
@@ -35,7 +34,6 @@ extern char __init_begin[], __init_end[];
 extern char _sinittext[], _einittext[];
 extern char _end[];
 extern char __per_cpu_load[], __per_cpu_start[], __per_cpu_end[];
-extern char __kprobes_text_start[], __kprobes_text_end[];
 extern char __entry_text_start[], __entry_text_end[];
 extern char __start_rodata[], __end_rodata[];
 
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index ba49b7ad7af2..f2444d82d02a 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -449,12 +449,6 @@
 		*(.spinlock.text)					\
 		VMLINUX_SYMBOL(__lock_text_end) = .;
 
-#define KPROBES_TEXT							\
-		ALIGN_FUNCTION();					\
-		VMLINUX_SYMBOL(__kprobes_text_start) = .;		\
-		*(.kprobes.text)					\
-		VMLINUX_SYMBOL(__kprobes_text_end) = .;
-
 #define ENTRY_TEXT							\
 		ALIGN_FUNCTION();					\
 		VMLINUX_SYMBOL(__entry_text_start) = .;			\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 985ed79ef431..445cc6fe7afa 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -43,6 +43,9 @@
 #include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
+#include <linux/ranges.h>
+
+DECLARE_SECTION_RANGE(kprobes);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index d10ab6b9b5e0..387605682622 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1328,8 +1328,7 @@ out:
 bool __weak arch_within_kprobe_blacklist(unsigned long addr)
 {
 	/* The __kprobes marked functions and entry code must not be probed */
-	return addr >= (unsigned long)__kprobes_text_start &&
-	       addr < (unsigned long)__kprobes_text_end;
+	return SECTION_ADDR_IN_RANGE(kprobes, addr);
 }
 
 bool within_kprobe_blacklist(unsigned long addr)
@@ -2129,6 +2128,9 @@ static struct notifier_block kprobe_module_nb = {
 extern unsigned long __start_kprobe_blacklist[];
 extern unsigned long __stop_kprobe_blacklist[];
 
+/* Actual kprobes section range */
+DEFINE_SECTION_RANGE(kprobes, SECTION_TEXT);
+
 static int __init init_kprobes(void)
 {
 	int i, err = 0;
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 48958d3cec9e..1a50a83304d3 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -888,7 +888,7 @@ static void check_section(const char *modname, struct elf_info *elf,
 
 #define DATA_SECTIONS ".data", ".data.rel"
 #define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \
-		".kprobes.text"
+		".text.rng.kprobes.any"
 #define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
 		".fixup", ".entry.text", ".exception.text", ".text.*", \
 		".coldtext"
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 42396a74405d..7f66cce79612 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -363,7 +363,7 @@ is_mcounted_section_name(char const *const txtname)
 		strcmp(".sched.text",    txtname) == 0 ||
 		strcmp(".spinlock.text", txtname) == 0 ||
 		strcmp(".irqentry.text", txtname) == 0 ||
-		strcmp(".kprobes.text", txtname) == 0 ||
+		strcmp(".text.rng.kprobes.any", txtname) == 0 ||
 		strcmp(".text.unlikely", txtname) == 0;
 }
 
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 96e2486a6fc4..f663a7c5d6ab 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -134,7 +134,7 @@ my %text_sections = (
      ".sched.text" => 1,
      ".spinlock.text" => 1,
      ".irqentry.text" => 1,
-     ".kprobes.text" => 1,
+     ".text.rng.kprobes.any" => 1,
      ".text.unlikely" => 1,
 );
 
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 16/16] kprobes: port blacklist kprobes to linker table
  2016-08-19 21:33   ` mcgrof
  (?)
@ 2016-08-19 21:34     ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

kprobe makes use of two sections, the one dealing with the actual
kprobes was recently ported using the standard section range API.
The blacklist functionality of kprobes is still using a custom
section and declaring its custom section using the linker script
as follows:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist

This ports the _kprobe_blacklist custom section to the standard
Linux linker table API allowing us remove all the custom blacklist
kprobe section declarations from the linker script.

This has been tested by trying to register a kprobe on a blacklisted
symbol (these are declared with NOKPROBE_SYMBOL()), and confirms that
this fails to work as expected. This was tested with:

 # insmod samples/kprobes/kprobe_example.ko symbol="get_kprobe"

This fails to load as expected with:

insmod: ERROR: could not insert module samples/kprobes/kprobe_example.ko: Invalid parameters

v3: this patch was introduced in this series

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/asm-generic/kprobes.h     |  4 ++--
 include/asm-generic/vmlinux.lds.h | 10 ----------
 include/linux/kprobes.h           |  2 ++
 kernel/kprobes.c                  | 11 ++++-------
 4 files changed, 8 insertions(+), 19 deletions(-)

diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 7b986f4b7ccd..23a49a4c7a38 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,14 +3,14 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <linux/tables.h>
 #include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
  */
 # define __NOKPROBE_SYMBOL(fname)				\
-static unsigned long __used					\
-	__attribute__((__section__("_kprobe_blacklist")))	\
+static LINKTABLE_INIT_DATA(_kprobe_blacklist, all)		\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index f2444d82d02a..47ef04de9958 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -114,15 +114,6 @@
 #define BRANCH_PROFILE()
 #endif
 
-#ifdef CONFIG_KPROBES
-#define KPROBE_BLACKLIST()	. = ALIGN(8);				      \
-				VMLINUX_SYMBOL(__start_kprobe_blacklist) = .; \
-				*(_kprobe_blacklist)			      \
-				VMLINUX_SYMBOL(__stop_kprobe_blacklist) = .;
-#else
-#define KPROBE_BLACKLIST()
-#endif
-
 #ifdef CONFIG_EVENT_TRACING
 #define FTRACE_EVENTS()	. = ALIGN(8);					\
 			VMLINUX_SYMBOL(__start_ftrace_events) = .;	\
@@ -525,7 +516,6 @@
 	*(SECTION_INIT_RODATA)						\
 	FTRACE_EVENTS()							\
 	TRACE_SYSCALLS()						\
-	KPROBE_BLACKLIST()						\
 	MEM_DISCARD(init.rodata)					\
 	CLK_OF_TABLES()							\
 	RESERVEDMEM_OF_TABLES()						\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 445cc6fe7afa..2707820cbb56 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -44,8 +44,10 @@
 
 #ifdef CONFIG_KPROBES
 #include <linux/ranges.h>
+#include <linux/tables.h>
 
 DECLARE_SECTION_RANGE(kprobes);
+DECLARE_LINKTABLE(unsigned long, _kprobe_blacklist);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 387605682622..4801aa3b4adf 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -2053,14 +2053,13 @@ NOKPROBE_SYMBOL(dump_kprobe);
  * since a kprobe need not necessarily be at the beginning
  * of a function.
  */
-static int __init populate_kprobe_blacklist(unsigned long *start,
-					     unsigned long *end)
+static int __init populate_kprobe_blacklist(void)
 {
 	unsigned long *iter;
 	struct kprobe_blacklist_entry *ent;
 	unsigned long entry, offset = 0, size = 0;
 
-	for (iter = start; iter < end; iter++) {
+	LINKTABLE_FOR_EACH(iter, _kprobe_blacklist) {
 		entry = arch_deref_entry_point((void *)*iter);
 
 		if (!kernel_text_address(entry) ||
@@ -2125,8 +2124,7 @@ static struct notifier_block kprobe_module_nb = {
 };
 
 /* Markers of _kprobe_blacklist section */
-extern unsigned long __start_kprobe_blacklist[];
-extern unsigned long __stop_kprobe_blacklist[];
+DEFINE_LINKTABLE_INIT_DATA(unsigned long, _kprobe_blacklist);
 
 /* Actual kprobes section range */
 DEFINE_SECTION_RANGE(kprobes, SECTION_TEXT);
@@ -2143,8 +2141,7 @@ static int __init init_kprobes(void)
 		raw_spin_lock_init(&(kretprobe_table_locks[i].lock));
 	}
 
-	err = populate_kprobe_blacklist(__start_kprobe_blacklist,
-					__stop_kprobe_blacklist);
+	err = populate_kprobe_blacklist();
 	if (err) {
 		pr_err("kprobes: failed to populate blacklist: %d\n", err);
 		pr_err("Please take care of using kprobes.\n");
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 16/16] kprobes: port blacklist kprobes to linker table
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

kprobe makes use of two sections, the one dealing with the actual
kprobes was recently ported using the standard section range API.
The blacklist functionality of kprobes is still using a custom
section and declaring its custom section using the linker script
as follows:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist

This ports the _kprobe_blacklist custom section to the standard
Linux linker table API allowing us remove all the custom blacklist
kprobe section declarations from the linker script.

This has been tested by trying to register a kprobe on a blacklisted
symbol (these are declared with NOKPROBE_SYMBOL()), and confirms that
this fails to work as expected. This was tested with:

 # insmod samples/kprobes/kprobe_example.ko symbol="get_kprobe"

This fails to load as expected with:

insmod: ERROR: could not insert module samples/kprobes/kprobe_example.ko: Invalid parameters

v3: this patch was introduced in this series

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/asm-generic/kprobes.h     |  4 ++--
 include/asm-generic/vmlinux.lds.h | 10 ----------
 include/linux/kprobes.h           |  2 ++
 kernel/kprobes.c                  | 11 ++++-------
 4 files changed, 8 insertions(+), 19 deletions(-)

diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 7b986f4b7ccd..23a49a4c7a38 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,14 +3,14 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <linux/tables.h>
 #include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
  */
 # define __NOKPROBE_SYMBOL(fname)				\
-static unsigned long __used					\
-	__attribute__((__section__("_kprobe_blacklist")))	\
+static LINKTABLE_INIT_DATA(_kprobe_blacklist, all)		\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index f2444d82d02a..47ef04de9958 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -114,15 +114,6 @@
 #define BRANCH_PROFILE()
 #endif
 
-#ifdef CONFIG_KPROBES
-#define KPROBE_BLACKLIST()	. = ALIGN(8);				      \
-				VMLINUX_SYMBOL(__start_kprobe_blacklist) = .; \
-				*(_kprobe_blacklist)			      \
-				VMLINUX_SYMBOL(__stop_kprobe_blacklist) = .;
-#else
-#define KPROBE_BLACKLIST()
-#endif
-
 #ifdef CONFIG_EVENT_TRACING
 #define FTRACE_EVENTS()	. = ALIGN(8);					\
 			VMLINUX_SYMBOL(__start_ftrace_events) = .;	\
@@ -525,7 +516,6 @@
 	*(SECTION_INIT_RODATA)						\
 	FTRACE_EVENTS()							\
 	TRACE_SYSCALLS()						\
-	KPROBE_BLACKLIST()						\
 	MEM_DISCARD(init.rodata)					\
 	CLK_OF_TABLES()							\
 	RESERVEDMEM_OF_TABLES()						\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 445cc6fe7afa..2707820cbb56 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -44,8 +44,10 @@
 
 #ifdef CONFIG_KPROBES
 #include <linux/ranges.h>
+#include <linux/tables.h>
 
 DECLARE_SECTION_RANGE(kprobes);
+DECLARE_LINKTABLE(unsigned long, _kprobe_blacklist);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 387605682622..4801aa3b4adf 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -2053,14 +2053,13 @@ NOKPROBE_SYMBOL(dump_kprobe);
  * since a kprobe need not necessarily be at the beginning
  * of a function.
  */
-static int __init populate_kprobe_blacklist(unsigned long *start,
-					     unsigned long *end)
+static int __init populate_kprobe_blacklist(void)
 {
 	unsigned long *iter;
 	struct kprobe_blacklist_entry *ent;
 	unsigned long entry, offset = 0, size = 0;
 
-	for (iter = start; iter < end; iter++) {
+	LINKTABLE_FOR_EACH(iter, _kprobe_blacklist) {
 		entry = arch_deref_entry_point((void *)*iter);
 
 		if (!kernel_text_address(entry) ||
@@ -2125,8 +2124,7 @@ static struct notifier_block kprobe_module_nb = {
 };
 
 /* Markers of _kprobe_blacklist section */
-extern unsigned long __start_kprobe_blacklist[];
-extern unsigned long __stop_kprobe_blacklist[];
+DEFINE_LINKTABLE_INIT_DATA(unsigned long, _kprobe_blacklist);
 
 /* Actual kprobes section range */
 DEFINE_SECTION_RANGE(kprobes, SECTION_TEXT);
@@ -2143,8 +2141,7 @@ static int __init init_kprobes(void)
 		raw_spin_lock_init(&(kretprobe_table_locks[i].lock));
 	}
 
-	err = populate_kprobe_blacklist(__start_kprobe_blacklist,
-					__stop_kprobe_blacklist);
+	err = populate_kprobe_blacklist();
 	if (err) {
 		pr_err("kprobes: failed to populate blacklist: %d\n", err);
 		pr_err("Please take care of using kprobes.\n");
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 16/16] kprobes: port blacklist kprobes to linker table
@ 2016-08-19 21:34     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:34 UTC (permalink / raw)
  To: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

kprobe makes use of two sections, the one dealing with the actual
kprobes was recently ported using the standard section range API.
The blacklist functionality of kprobes is still using a custom
section and declaring its custom section using the linker script
as follows:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist

This ports the _kprobe_blacklist custom section to the standard
Linux linker table API allowing us remove all the custom blacklist
kprobe section declarations from the linker script.

This has been tested by trying to register a kprobe on a blacklisted
symbol (these are declared with NOKPROBE_SYMBOL()), and confirms that
this fails to work as expected. This was tested with:

 # insmod samples/kprobes/kprobe_example.ko symbol="get_kprobe"

This fails to load as expected with:

insmod: ERROR: could not insert module samples/kprobes/kprobe_example.ko: Invalid parameters

v3: this patch was introduced in this series

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/asm-generic/kprobes.h     |  4 ++--
 include/asm-generic/vmlinux.lds.h | 10 ----------
 include/linux/kprobes.h           |  2 ++
 kernel/kprobes.c                  | 11 ++++-------
 4 files changed, 8 insertions(+), 19 deletions(-)

diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 7b986f4b7ccd..23a49a4c7a38 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,14 +3,14 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <linux/tables.h>
 #include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
  */
 # define __NOKPROBE_SYMBOL(fname)				\
-static unsigned long __used					\
-	__attribute__((__section__("_kprobe_blacklist")))	\
+static LINKTABLE_INIT_DATA(_kprobe_blacklist, all)		\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index f2444d82d02a..47ef04de9958 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -114,15 +114,6 @@
 #define BRANCH_PROFILE()
 #endif
 
-#ifdef CONFIG_KPROBES
-#define KPROBE_BLACKLIST()	. = ALIGN(8);				      \
-				VMLINUX_SYMBOL(__start_kprobe_blacklist) = .; \
-				*(_kprobe_blacklist)			      \
-				VMLINUX_SYMBOL(__stop_kprobe_blacklist) = .;
-#else
-#define KPROBE_BLACKLIST()
-#endif
-
 #ifdef CONFIG_EVENT_TRACING
 #define FTRACE_EVENTS()	. = ALIGN(8);					\
 			VMLINUX_SYMBOL(__start_ftrace_events) = .;	\
@@ -525,7 +516,6 @@
 	*(SECTION_INIT_RODATA)						\
 	FTRACE_EVENTS()							\
 	TRACE_SYSCALLS()						\
-	KPROBE_BLACKLIST()						\
 	MEM_DISCARD(init.rodata)					\
 	CLK_OF_TABLES()							\
 	RESERVEDMEM_OF_TABLES()						\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 445cc6fe7afa..2707820cbb56 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -44,8 +44,10 @@
 
 #ifdef CONFIG_KPROBES
 #include <linux/ranges.h>
+#include <linux/tables.h>
 
 DECLARE_SECTION_RANGE(kprobes);
+DECLARE_LINKTABLE(unsigned long, _kprobe_blacklist);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 387605682622..4801aa3b4adf 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -2053,14 +2053,13 @@ NOKPROBE_SYMBOL(dump_kprobe);
  * since a kprobe need not necessarily be at the beginning
  * of a function.
  */
-static int __init populate_kprobe_blacklist(unsigned long *start,
-					     unsigned long *end)
+static int __init populate_kprobe_blacklist(void)
 {
 	unsigned long *iter;
 	struct kprobe_blacklist_entry *ent;
 	unsigned long entry, offset = 0, size = 0;
 
-	for (iter = start; iter < end; iter++) {
+	LINKTABLE_FOR_EACH(iter, _kprobe_blacklist) {
 		entry = arch_deref_entry_point((void *)*iter);
 
 		if (!kernel_text_address(entry) ||
@@ -2125,8 +2124,7 @@ static struct notifier_block kprobe_module_nb = {
 };
 
 /* Markers of _kprobe_blacklist section */
-extern unsigned long __start_kprobe_blacklist[];
-extern unsigned long __stop_kprobe_blacklist[];
+DEFINE_LINKTABLE_INIT_DATA(unsigned long, _kprobe_blacklist);
 
 /* Actual kprobes section range */
 DEFINE_SECTION_RANGE(kprobes, SECTION_TEXT);
@@ -2143,8 +2141,7 @@ static int __init init_kprobes(void)
 		raw_spin_lock_init(&(kretprobe_table_locks[i].lock));
 	}
 
-	err = populate_kprobe_blacklist(__start_kprobe_blacklist,
-					__stop_kprobe_blacklist);
+	err = populate_kprobe_blacklist();
 	if (err) {
 		pr_err("kprobes: failed to populate blacklist: %d\n", err);
 		pr_err("Please take care of using kprobes.\n");
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v1 0/7] tools: add linker table userspace sandbox
  2016-08-19 21:33   ` mcgrof
  (?)
@ 2016-08-19 21:41     ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

The original v3 series for linker tables made reference only to
an external repository userspace sandbox application, however
Boris noted it'd be difficult ot keep this in sync with the
kernel so advised to consider integrate with the kernel. I've
taken steps in this direction.

A bit of prepping is done to help make use of the tools/include
and tools/arch/$(ARCH)/include/asm directories. For now the tool
only supports x86_64, however quite a bit of work was done to
help make it work with a cross compiler, and try to make as
architecture agnostic as possible. Adding suppor for another 
architecture should not require much work, mosty just generating
a userspace custom linker script, modifying it for linker tables,
section ranges, and finally testing this with its toolchain.

This is being submitted separately than the patches which adds
linker table support into the kernel. This should be considered
only if that gets merged.

If you'd like this in git-form, you can get it on the 20160819-linker-table-v4  
branch of my linux-next tree on kernel.org, this also includes the series of    
that introduces linker tables into the kernel:
                                                                                
https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h 160819-linker-table-v4

Please let me know if there are any issue or questions.

Luis R. Rodriguez (7):
  tools: add a userspace tools bug.h
  tools: add a basic tools printk.h
  tools: add init.h for tools
  tools: add __used and enable to override
  tools: expand export.h with VMLINUX_SYMBOL()
  tools: add __section() to compiler.h
  tools: add userspace linker table sandbox

 Documentation/sections/linker-tables.rst           |   4 +-
 MAINTAINERS                                        |   1 +
 include/linux/tables.h                             |   5 +-
 tools/Makefile                                     |   3 +-
 .../arch/x86/include/generated/asm/section-core.h  |   1 +
 tools/arch/x86/include/generated/ranges.h          |   1 +
 tools/arch/x86/include/generated/tables.h          |   1 +
 tools/include/asm-generic/bug.h                    |  24 +
 tools/include/asm-generic/ranges.h                 | 103 ++++
 tools/include/asm-generic/section-core.h           | 341 +++++++++++
 tools/include/asm-generic/tables.h                 |  50 ++
 tools/include/linux/bug.h                          |   6 +
 tools/include/linux/compiler.h                     |   8 +
 tools/include/linux/export.h                       |  22 +
 tools/include/linux/init.h                         |   9 +
 tools/include/linux/kernel.h                       |   3 +
 tools/include/linux/printk.h                       |  14 +
 tools/include/linux/ranges.h                       | 128 ++++
 tools/include/linux/sections.h                     | 111 ++++
 tools/include/linux/string.h                       |   1 +
 tools/include/linux/tables.h                       | 664 +++++++++++++++++++++
 tools/linker-tables/.gitignore                     |   2 +
 tools/linker-tables/Makefile                       | 184 ++++++
 tools/linker-tables/README                         | 114 ++++
 tools/linker-tables/arch/x86/include/asm/asm.h     |  17 +
 tools/linker-tables/arch/x86/include/asm/boot.h    |   1 +
 .../linker-tables/arch/x86/include/asm/bootparam.h |  32 +
 tools/linker-tables/arch/x86/include/asm/kprobes.h |   7 +
 .../linker-tables/arch/x86/include/asm/ps_const.h  |  21 +
 tools/linker-tables/arch/x86/include/asm/ranges.h  |   6 +
 .../arch/x86/include/asm/section-core.h            |   1 +
 tools/linker-tables/arch/x86/include/asm/setup.h   |   6 +
 tools/linker-tables/arch/x86/include/asm/tables.h  |   6 +
 tools/linker-tables/arch/x86/include/asm/x86.h     |   4 +
 .../arch/x86/include/asm/x86_init_fn.h             | 169 ++++++
 tools/linker-tables/arch/x86/kernel/alpha.c        |   9 +
 tools/linker-tables/arch/x86/kernel/alternative.c  |  31 +
 tools/linker-tables/arch/x86/kernel/beta.c         |   9 +
 tools/linker-tables/arch/x86/kernel/head64.c       |  58 ++
 tools/linker-tables/arch/x86/kernel/init.c         |  42 ++
 tools/linker-tables/arch/x86/kernel/kasan.c        |  10 +
 tools/linker-tables/arch/x86/kernel/kprobes.c      |  51 ++
 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S  | 273 +++++++++
 tools/linker-tables/arch/x86/mm/init.c             |  10 +
 tools/linker-tables/arch/x86/xen/init.c            |  13 +
 tools/linker-tables/drivers/acme.c                 |  32 +
 tools/linker-tables/drivers/synth/common.c         |  16 +
 tools/linker-tables/drivers/synth/common.h         |   2 +
 tools/linker-tables/drivers/synth/main.c           |  35 ++
 tools/linker-tables/drivers/synth/or.S             |  39 ++
 tools/linker-tables/drivers/synth/synth.h          |   2 +
 tools/linker-tables/drivers/xen-driver.c           |  11 +
 .../include/asm-generic/arch_init_fn.h             |  50 ++
 tools/linker-tables/include/asm-generic/kprobes.h  |  26 +
 tools/linker-tables/include/linux/bitops.h         |   6 +
 tools/linker-tables/include/linux/init.h           |  40 ++
 tools/linker-tables/include/linux/kasan.h          |   5 +
 tools/linker-tables/include/linux/kprobes.h        |  11 +
 tools/linker-tables/include/linux/module.h         |  14 +
 tools/linker-tables/include/linux/mutex.h          |  17 +
 tools/linker-tables/include/linux/pci.h            |   7 +
 tools/linker-tables/include/linux/ps_const.h       |  46 ++
 tools/linker-tables/include/linux/sched.h          |   9 +
 tools/linker-tables/include/linux/spinlock.h       |  13 +
 tools/linker-tables/include/linux/start_kernel.h   |   1 +
 tools/linker-tables/include/linux/types.h          |  13 +
 tools/linker-tables/include/linux/workqueue.h      |  51 ++
 tools/linker-tables/include/xen/xen.h              |   4 +
 tools/linker-tables/kernel/locking/mutex.c         |  28 +
 tools/linker-tables/kernel/locking/spinlock.c      |  26 +
 tools/linker-tables/kernel/main.c                  |  32 +
 tools/linker-tables/kernel/workqueue.c             |  43 ++
 tools/linker-tables/lib/string.c                   |  26 +
 tools/linker-tables/main.c                         |  20 +
 tools/linker-tables/pci-quirks.c                   |  13 +
 tools/linker-tables/pci.c                          |  29 +
 76 files changed, 3238 insertions(+), 5 deletions(-)
 create mode 100644 tools/arch/x86/include/generated/asm/section-core.h
 create mode 100644 tools/arch/x86/include/generated/ranges.h
 create mode 100644 tools/arch/x86/include/generated/tables.h
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/asm-generic/ranges.h
 create mode 100644 tools/include/asm-generic/section-core.h
 create mode 100644 tools/include/asm-generic/tables.h
 create mode 100644 tools/include/linux/bug.h
 create mode 100644 tools/include/linux/init.h
 create mode 100644 tools/include/linux/printk.h
 create mode 100644 tools/include/linux/ranges.h
 create mode 100644 tools/include/linux/sections.h
 create mode 100644 tools/include/linux/tables.h
 create mode 100644 tools/linker-tables/.gitignore
 create mode 100644 tools/linker-tables/Makefile
 create mode 100644 tools/linker-tables/README
 create mode 100644 tools/linker-tables/arch/x86/include/asm/asm.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/boot.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/bootparam.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/kprobes.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ps_const.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ranges.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/section-core.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/setup.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/tables.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
 create mode 100644 tools/linker-tables/arch/x86/kernel/alpha.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/alternative.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/beta.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/head64.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/init.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kasan.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kprobes.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
 create mode 100644 tools/linker-tables/arch/x86/mm/init.c
 create mode 100644 tools/linker-tables/arch/x86/xen/init.c
 create mode 100644 tools/linker-tables/drivers/acme.c
 create mode 100644 tools/linker-tables/drivers/synth/common.c
 create mode 100644 tools/linker-tables/drivers/synth/common.h
 create mode 100644 tools/linker-tables/drivers/synth/main.c
 create mode 100644 tools/linker-tables/drivers/synth/or.S
 create mode 100644 tools/linker-tables/drivers/synth/synth.h
 create mode 100644 tools/linker-tables/drivers/xen-driver.c
 create mode 100644 tools/linker-tables/include/asm-generic/arch_init_fn.h
 create mode 100644 tools/linker-tables/include/asm-generic/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/bitops.h
 create mode 100644 tools/linker-tables/include/linux/init.h
 create mode 100644 tools/linker-tables/include/linux/kasan.h
 create mode 100644 tools/linker-tables/include/linux/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/module.h
 create mode 100644 tools/linker-tables/include/linux/mutex.h
 create mode 100644 tools/linker-tables/include/linux/pci.h
 create mode 100644 tools/linker-tables/include/linux/ps_const.h
 create mode 100644 tools/linker-tables/include/linux/sched.h
 create mode 100644 tools/linker-tables/include/linux/spinlock.h
 create mode 100644 tools/linker-tables/include/linux/start_kernel.h
 create mode 100644 tools/linker-tables/include/linux/types.h
 create mode 100644 tools/linker-tables/include/linux/workqueue.h
 create mode 100644 tools/linker-tables/include/xen/xen.h
 create mode 100644 tools/linker-tables/kernel/locking/mutex.c
 create mode 100644 tools/linker-tables/kernel/locking/spinlock.c
 create mode 100644 tools/linker-tables/kernel/main.c
 create mode 100644 tools/linker-tables/kernel/workqueue.c
 create mode 100644 tools/linker-tables/lib/string.c
 create mode 100644 tools/linker-tables/main.c
 create mode 100644 tools/linker-tables/pci-quirks.c
 create mode 100644 tools/linker-tables/pci.c

-- 
2.9.2


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v1 0/7] tools: add linker table userspace sandbox
@ 2016-08-19 21:41     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

The original v3 series for linker tables made reference only to
an external repository userspace sandbox application, however
Boris noted it'd be difficult ot keep this in sync with the
kernel so advised to consider integrate with the kernel. I've
taken steps in this direction.

A bit of prepping is done to help make use of the tools/include
and tools/arch/$(ARCH)/include/asm directories. For now the tool
only supports x86_64, however quite a bit of work was done to
help make it work with a cross compiler, and try to make as
architecture agnostic as possible. Adding suppor for another 
architecture should not require much work, mosty just generating
a userspace custom linker script, modifying it for linker tables,
section ranges, and finally testing this with its toolchain.

This is being submitted separately than the patches which adds
linker table support into the kernel. This should be considered
only if that gets merged.

If you'd like this in git-form, you can get it on the 20160819-linker-table-v4  
branch of my linux-next tree on kernel.org, this also includes the series of    
that introduces linker tables into the kernel:
                                                                                
https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h=20160819-linker-table-v4

Please let me know if there are any issue or questions.

Luis R. Rodriguez (7):
  tools: add a userspace tools bug.h
  tools: add a basic tools printk.h
  tools: add init.h for tools
  tools: add __used and enable to override
  tools: expand export.h with VMLINUX_SYMBOL()
  tools: add __section() to compiler.h
  tools: add userspace linker table sandbox

 Documentation/sections/linker-tables.rst           |   4 +-
 MAINTAINERS                                        |   1 +
 include/linux/tables.h                             |   5 +-
 tools/Makefile                                     |   3 +-
 .../arch/x86/include/generated/asm/section-core.h  |   1 +
 tools/arch/x86/include/generated/ranges.h          |   1 +
 tools/arch/x86/include/generated/tables.h          |   1 +
 tools/include/asm-generic/bug.h                    |  24 +
 tools/include/asm-generic/ranges.h                 | 103 ++++
 tools/include/asm-generic/section-core.h           | 341 +++++++++++
 tools/include/asm-generic/tables.h                 |  50 ++
 tools/include/linux/bug.h                          |   6 +
 tools/include/linux/compiler.h                     |   8 +
 tools/include/linux/export.h                       |  22 +
 tools/include/linux/init.h                         |   9 +
 tools/include/linux/kernel.h                       |   3 +
 tools/include/linux/printk.h                       |  14 +
 tools/include/linux/ranges.h                       | 128 ++++
 tools/include/linux/sections.h                     | 111 ++++
 tools/include/linux/string.h                       |   1 +
 tools/include/linux/tables.h                       | 664 +++++++++++++++++++++
 tools/linker-tables/.gitignore                     |   2 +
 tools/linker-tables/Makefile                       | 184 ++++++
 tools/linker-tables/README                         | 114 ++++
 tools/linker-tables/arch/x86/include/asm/asm.h     |  17 +
 tools/linker-tables/arch/x86/include/asm/boot.h    |   1 +
 .../linker-tables/arch/x86/include/asm/bootparam.h |  32 +
 tools/linker-tables/arch/x86/include/asm/kprobes.h |   7 +
 .../linker-tables/arch/x86/include/asm/ps_const.h  |  21 +
 tools/linker-tables/arch/x86/include/asm/ranges.h  |   6 +
 .../arch/x86/include/asm/section-core.h            |   1 +
 tools/linker-tables/arch/x86/include/asm/setup.h   |   6 +
 tools/linker-tables/arch/x86/include/asm/tables.h  |   6 +
 tools/linker-tables/arch/x86/include/asm/x86.h     |   4 +
 .../arch/x86/include/asm/x86_init_fn.h             | 169 ++++++
 tools/linker-tables/arch/x86/kernel/alpha.c        |   9 +
 tools/linker-tables/arch/x86/kernel/alternative.c  |  31 +
 tools/linker-tables/arch/x86/kernel/beta.c         |   9 +
 tools/linker-tables/arch/x86/kernel/head64.c       |  58 ++
 tools/linker-tables/arch/x86/kernel/init.c         |  42 ++
 tools/linker-tables/arch/x86/kernel/kasan.c        |  10 +
 tools/linker-tables/arch/x86/kernel/kprobes.c      |  51 ++
 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S  | 273 +++++++++
 tools/linker-tables/arch/x86/mm/init.c             |  10 +
 tools/linker-tables/arch/x86/xen/init.c            |  13 +
 tools/linker-tables/drivers/acme.c                 |  32 +
 tools/linker-tables/drivers/synth/common.c         |  16 +
 tools/linker-tables/drivers/synth/common.h         |   2 +
 tools/linker-tables/drivers/synth/main.c           |  35 ++
 tools/linker-tables/drivers/synth/or.S             |  39 ++
 tools/linker-tables/drivers/synth/synth.h          |   2 +
 tools/linker-tables/drivers/xen-driver.c           |  11 +
 .../include/asm-generic/arch_init_fn.h             |  50 ++
 tools/linker-tables/include/asm-generic/kprobes.h  |  26 +
 tools/linker-tables/include/linux/bitops.h         |   6 +
 tools/linker-tables/include/linux/init.h           |  40 ++
 tools/linker-tables/include/linux/kasan.h          |   5 +
 tools/linker-tables/include/linux/kprobes.h        |  11 +
 tools/linker-tables/include/linux/module.h         |  14 +
 tools/linker-tables/include/linux/mutex.h          |  17 +
 tools/linker-tables/include/linux/pci.h            |   7 +
 tools/linker-tables/include/linux/ps_const.h       |  46 ++
 tools/linker-tables/include/linux/sched.h          |   9 +
 tools/linker-tables/include/linux/spinlock.h       |  13 +
 tools/linker-tables/include/linux/start_kernel.h   |   1 +
 tools/linker-tables/include/linux/types.h          |  13 +
 tools/linker-tables/include/linux/workqueue.h      |  51 ++
 tools/linker-tables/include/xen/xen.h              |   4 +
 tools/linker-tables/kernel/locking/mutex.c         |  28 +
 tools/linker-tables/kernel/locking/spinlock.c      |  26 +
 tools/linker-tables/kernel/main.c                  |  32 +
 tools/linker-tables/kernel/workqueue.c             |  43 ++
 tools/linker-tables/lib/string.c                   |  26 +
 tools/linker-tables/main.c                         |  20 +
 tools/linker-tables/pci-quirks.c                   |  13 +
 tools/linker-tables/pci.c                          |  29 +
 76 files changed, 3238 insertions(+), 5 deletions(-)
 create mode 100644 tools/arch/x86/include/generated/asm/section-core.h
 create mode 100644 tools/arch/x86/include/generated/ranges.h
 create mode 100644 tools/arch/x86/include/generated/tables.h
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/asm-generic/ranges.h
 create mode 100644 tools/include/asm-generic/section-core.h
 create mode 100644 tools/include/asm-generic/tables.h
 create mode 100644 tools/include/linux/bug.h
 create mode 100644 tools/include/linux/init.h
 create mode 100644 tools/include/linux/printk.h
 create mode 100644 tools/include/linux/ranges.h
 create mode 100644 tools/include/linux/sections.h
 create mode 100644 tools/include/linux/tables.h
 create mode 100644 tools/linker-tables/.gitignore
 create mode 100644 tools/linker-tables/Makefile
 create mode 100644 tools/linker-tables/README
 create mode 100644 tools/linker-tables/arch/x86/include/asm/asm.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/boot.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/bootparam.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/kprobes.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ps_const.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ranges.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/section-core.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/setup.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/tables.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
 create mode 100644 tools/linker-tables/arch/x86/kernel/alpha.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/alternative.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/beta.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/head64.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/init.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kasan.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kprobes.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
 create mode 100644 tools/linker-tables/arch/x86/mm/init.c
 create mode 100644 tools/linker-tables/arch/x86/xen/init.c
 create mode 100644 tools/linker-tables/drivers/acme.c
 create mode 100644 tools/linker-tables/drivers/synth/common.c
 create mode 100644 tools/linker-tables/drivers/synth/common.h
 create mode 100644 tools/linker-tables/drivers/synth/main.c
 create mode 100644 tools/linker-tables/drivers/synth/or.S
 create mode 100644 tools/linker-tables/drivers/synth/synth.h
 create mode 100644 tools/linker-tables/drivers/xen-driver.c
 create mode 100644 tools/linker-tables/include/asm-generic/arch_init_fn.h
 create mode 100644 tools/linker-tables/include/asm-generic/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/bitops.h
 create mode 100644 tools/linker-tables/include/linux/init.h
 create mode 100644 tools/linker-tables/include/linux/kasan.h
 create mode 100644 tools/linker-tables/include/linux/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/module.h
 create mode 100644 tools/linker-tables/include/linux/mutex.h
 create mode 100644 tools/linker-tables/include/linux/pci.h
 create mode 100644 tools/linker-tables/include/linux/ps_const.h
 create mode 100644 tools/linker-tables/include/linux/sched.h
 create mode 100644 tools/linker-tables/include/linux/spinlock.h
 create mode 100644 tools/linker-tables/include/linux/start_kernel.h
 create mode 100644 tools/linker-tables/include/linux/types.h
 create mode 100644 tools/linker-tables/include/linux/workqueue.h
 create mode 100644 tools/linker-tables/include/xen/xen.h
 create mode 100644 tools/linker-tables/kernel/locking/mutex.c
 create mode 100644 tools/linker-tables/kernel/locking/spinlock.c
 create mode 100644 tools/linker-tables/kernel/main.c
 create mode 100644 tools/linker-tables/kernel/workqueue.c
 create mode 100644 tools/linker-tables/lib/string.c
 create mode 100644 tools/linker-tables/main.c
 create mode 100644 tools/linker-tables/pci-quirks.c
 create mode 100644 tools/linker-tables/pci.c

-- 
2.9.2


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v1 0/7] tools: add linker table userspace sandbox
@ 2016-08-19 21:41     ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, jolsa,
	msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

The original v3 series for linker tables made reference only to
an external repository userspace sandbox application, however
Boris noted it'd be difficult ot keep this in sync with the
kernel so advised to consider integrate with the kernel. I've
taken steps in this direction.

A bit of prepping is done to help make use of the tools/include
and tools/arch/$(ARCH)/include/asm directories. For now the tool
only supports x86_64, however quite a bit of work was done to
help make it work with a cross compiler, and try to make as
architecture agnostic as possible. Adding suppor for another 
architecture should not require much work, mosty just generating
a userspace custom linker script, modifying it for linker tables,
section ranges, and finally testing this with its toolchain.

This is being submitted separately than the patches which adds
linker table support into the kernel. This should be considered
only if that gets merged.

If you'd like this in git-form, you can get it on the 20160819-linker-table-v4  
branch of my linux-next tree on kernel.org, this also includes the series of    
that introduces linker tables into the kernel:
                                                                                
https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h=20160819-linker-table-v4

Please let me know if there are any issue or questions.

Luis R. Rodriguez (7):
  tools: add a userspace tools bug.h
  tools: add a basic tools printk.h
  tools: add init.h for tools
  tools: add __used and enable to override
  tools: expand export.h with VMLINUX_SYMBOL()
  tools: add __section() to compiler.h
  tools: add userspace linker table sandbox

 Documentation/sections/linker-tables.rst           |   4 +-
 MAINTAINERS                                        |   1 +
 include/linux/tables.h                             |   5 +-
 tools/Makefile                                     |   3 +-
 .../arch/x86/include/generated/asm/section-core.h  |   1 +
 tools/arch/x86/include/generated/ranges.h          |   1 +
 tools/arch/x86/include/generated/tables.h          |   1 +
 tools/include/asm-generic/bug.h                    |  24 +
 tools/include/asm-generic/ranges.h                 | 103 ++++
 tools/include/asm-generic/section-core.h           | 341 +++++++++++
 tools/include/asm-generic/tables.h                 |  50 ++
 tools/include/linux/bug.h                          |   6 +
 tools/include/linux/compiler.h                     |   8 +
 tools/include/linux/export.h                       |  22 +
 tools/include/linux/init.h                         |   9 +
 tools/include/linux/kernel.h                       |   3 +
 tools/include/linux/printk.h                       |  14 +
 tools/include/linux/ranges.h                       | 128 ++++
 tools/include/linux/sections.h                     | 111 ++++
 tools/include/linux/string.h                       |   1 +
 tools/include/linux/tables.h                       | 664 +++++++++++++++++++++
 tools/linker-tables/.gitignore                     |   2 +
 tools/linker-tables/Makefile                       | 184 ++++++
 tools/linker-tables/README                         | 114 ++++
 tools/linker-tables/arch/x86/include/asm/asm.h     |  17 +
 tools/linker-tables/arch/x86/include/asm/boot.h    |   1 +
 .../linker-tables/arch/x86/include/asm/bootparam.h |  32 +
 tools/linker-tables/arch/x86/include/asm/kprobes.h |   7 +
 .../linker-tables/arch/x86/include/asm/ps_const.h  |  21 +
 tools/linker-tables/arch/x86/include/asm/ranges.h  |   6 +
 .../arch/x86/include/asm/section-core.h            |   1 +
 tools/linker-tables/arch/x86/include/asm/setup.h   |   6 +
 tools/linker-tables/arch/x86/include/asm/tables.h  |   6 +
 tools/linker-tables/arch/x86/include/asm/x86.h     |   4 +
 .../arch/x86/include/asm/x86_init_fn.h             | 169 ++++++
 tools/linker-tables/arch/x86/kernel/alpha.c        |   9 +
 tools/linker-tables/arch/x86/kernel/alternative.c  |  31 +
 tools/linker-tables/arch/x86/kernel/beta.c         |   9 +
 tools/linker-tables/arch/x86/kernel/head64.c       |  58 ++
 tools/linker-tables/arch/x86/kernel/init.c         |  42 ++
 tools/linker-tables/arch/x86/kernel/kasan.c        |  10 +
 tools/linker-tables/arch/x86/kernel/kprobes.c      |  51 ++
 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S  | 273 +++++++++
 tools/linker-tables/arch/x86/mm/init.c             |  10 +
 tools/linker-tables/arch/x86/xen/init.c            |  13 +
 tools/linker-tables/drivers/acme.c                 |  32 +
 tools/linker-tables/drivers/synth/common.c         |  16 +
 tools/linker-tables/drivers/synth/common.h         |   2 +
 tools/linker-tables/drivers/synth/main.c           |  35 ++
 tools/linker-tables/drivers/synth/or.S             |  39 ++
 tools/linker-tables/drivers/synth/synth.h          |   2 +
 tools/linker-tables/drivers/xen-driver.c           |  11 +
 .../include/asm-generic/arch_init_fn.h             |  50 ++
 tools/linker-tables/include/asm-generic/kprobes.h  |  26 +
 tools/linker-tables/include/linux/bitops.h         |   6 +
 tools/linker-tables/include/linux/init.h           |  40 ++
 tools/linker-tables/include/linux/kasan.h          |   5 +
 tools/linker-tables/include/linux/kprobes.h        |  11 +
 tools/linker-tables/include/linux/module.h         |  14 +
 tools/linker-tables/include/linux/mutex.h          |  17 +
 tools/linker-tables/include/linux/pci.h            |   7 +
 tools/linker-tables/include/linux/ps_const.h       |  46 ++
 tools/linker-tables/include/linux/sched.h          |   9 +
 tools/linker-tables/include/linux/spinlock.h       |  13 +
 tools/linker-tables/include/linux/start_kernel.h   |   1 +
 tools/linker-tables/include/linux/types.h          |  13 +
 tools/linker-tables/include/linux/workqueue.h      |  51 ++
 tools/linker-tables/include/xen/xen.h              |   4 +
 tools/linker-tables/kernel/locking/mutex.c         |  28 +
 tools/linker-tables/kernel/locking/spinlock.c      |  26 +
 tools/linker-tables/kernel/main.c                  |  32 +
 tools/linker-tables/kernel/workqueue.c             |  43 ++
 tools/linker-tables/lib/string.c                   |  26 +
 tools/linker-tables/main.c                         |  20 +
 tools/linker-tables/pci-quirks.c                   |  13 +
 tools/linker-tables/pci.c                          |  29 +
 76 files changed, 3238 insertions(+), 5 deletions(-)
 create mode 100644 tools/arch/x86/include/generated/asm/section-core.h
 create mode 100644 tools/arch/x86/include/generated/ranges.h
 create mode 100644 tools/arch/x86/include/generated/tables.h
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/asm-generic/ranges.h
 create mode 100644 tools/include/asm-generic/section-core.h
 create mode 100644 tools/include/asm-generic/tables.h
 create mode 100644 tools/include/linux/bug.h
 create mode 100644 tools/include/linux/init.h
 create mode 100644 tools/include/linux/printk.h
 create mode 100644 tools/include/linux/ranges.h
 create mode 100644 tools/include/linux/sections.h
 create mode 100644 tools/include/linux/tables.h
 create mode 100644 tools/linker-tables/.gitignore
 create mode 100644 tools/linker-tables/Makefile
 create mode 100644 tools/linker-tables/README
 create mode 100644 tools/linker-tables/arch/x86/include/asm/asm.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/boot.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/bootparam.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/kprobes.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ps_const.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ranges.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/section-core.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/setup.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/tables.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
 create mode 100644 tools/linker-tables/arch/x86/kernel/alpha.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/alternative.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/beta.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/head64.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/init.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kasan.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kprobes.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
 create mode 100644 tools/linker-tables/arch/x86/mm/init.c
 create mode 100644 tools/linker-tables/arch/x86/xen/init.c
 create mode 100644 tools/linker-tables/drivers/acme.c
 create mode 100644 tools/linker-tables/drivers/synth/common.c
 create mode 100644 tools/linker-tables/drivers/synth/common.h
 create mode 100644 tools/linker-tables/drivers/synth/main.c
 create mode 100644 tools/linker-tables/drivers/synth/or.S
 create mode 100644 tools/linker-tables/drivers/synth/synth.h
 create mode 100644 tools/linker-tables/drivers/xen-driver.c
 create mode 100644 tools/linker-tables/include/asm-generic/arch_init_fn.h
 create mode 100644 tools/linker-tables/include/asm-generic/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/bitops.h
 create mode 100644 tools/linker-tables/include/linux/init.h
 create mode 100644 tools/linker-tables/include/linux/kasan.h
 create mode 100644 tools/linker-tables/include/linux/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/module.h
 create mode 100644 tools/linker-tables/include/linux/mutex.h
 create mode 100644 tools/linker-tables/include/linux/pci.h
 create mode 100644 tools/linker-tables/include/linux/ps_const.h
 create mode 100644 tools/linker-tables/include/linux/sched.h
 create mode 100644 tools/linker-tables/include/linux/spinlock.h
 create mode 100644 tools/linker-tables/include/linux/start_kernel.h
 create mode 100644 tools/linker-tables/include/linux/types.h
 create mode 100644 tools/linker-tables/include/linux/workqueue.h
 create mode 100644 tools/linker-tables/include/xen/xen.h
 create mode 100644 tools/linker-tables/kernel/locking/mutex.c
 create mode 100644 tools/linker-tables/kernel/locking/spinlock.c
 create mode 100644 tools/linker-tables/kernel/main.c
 create mode 100644 tools/linker-tables/kernel/workqueue.c
 create mode 100644 tools/linker-tables/lib/string.c
 create mode 100644 tools/linker-tables/main.c
 create mode 100644 tools/linker-tables/pci-quirks.c
 create mode 100644 tools/linker-tables/pci.c

-- 
2.9.2


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v1 1/7] tools: add a userspace tools bug.h
  2016-08-19 21:41     ` mcgrof
  (?)
@ 2016-08-19 21:41       ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This will be used later by the userspace linker-tables sandbox.
As a convenience, include bug.h on kernel.h -- this is not done
on upstream kernel.h, however most header files do include bug.h
eventually, if we were to only add the ones that need it we'd
need to copy a lot of headers to tools for the ony purpose of
includeing bug.h. This simplifies that.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/asm-generic/bug.h | 24 ++++++++++++++++++++++++
 tools/include/linux/bug.h       |  6 ++++++
 tools/include/linux/kernel.h    |  2 ++
 3 files changed, 32 insertions(+)
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/linux/bug.h

diff --git a/tools/include/asm-generic/bug.h b/tools/include/asm-generic/bug.h
new file mode 100644
index 000000000000..7b0f48b60dbe
--- /dev/null
+++ b/tools/include/asm-generic/bug.h
@@ -0,0 +1,24 @@
+#ifndef __TOOLS_ASM_GENERIC_BUG
+#define __TOOLS_ASM_GENERIC_BUG
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define BUG() do {										\
+	fprintf(stderr, "----------------------------------------------------------\n");	\
+	fprintf (stderr, "BUG on %s at %s: %i\n", __func__, __FILE__, __LINE__);		\
+	abort();										\
+}												\
+while (0)
+
+#define BUG_ON(cond) do { if (cond) BUG(); } while (0)
+
+#define WARN_ON(__test) do {									\
+	if (__test) {										\
+		fprintf(stderr, "----------------------------------------------------------\n");\
+		fprintf (stderr, "WARN_ON on %s at %s: %i\n", __func__, __FILE__, __LINE__);	\
+	}											\
+}												\
+while (0)
+
+#endif /* __TOOLS_ASM_GENERIC_BUG */
diff --git a/tools/include/linux/bug.h b/tools/include/linux/bug.h
new file mode 100644
index 000000000000..9be515b40b5c
--- /dev/null
+++ b/tools/include/linux/bug.h
@@ -0,0 +1,6 @@
+#ifndef _TOOLS_LINUX_BUG_H
+#define _TOOLS_LINUX_BUG_H
+
+#include <asm-generic/bug.h>
+
+#endif /* _TOOLS_LINUX_BUG_H */
diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
index 28607db02bd3..3d385a6d4fc1 100644
--- a/tools/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -5,6 +5,8 @@
 #include <stddef.h>
 #include <assert.h>
 
+#include <linux/bug.h>
+
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 
 #define PERF_ALIGN(x, a)	__PERF_ALIGN_MASK(x, (typeof(x))(a)-1)
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v1 1/7] tools: add a userspace tools bug.h
@ 2016-08-19 21:41       ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This will be used later by the userspace linker-tables sandbox.
As a convenience, include bug.h on kernel.h -- this is not done
on upstream kernel.h, however most header files do include bug.h
eventually, if we were to only add the ones that need it we'd
need to copy a lot of headers to tools for the ony purpose of
includeing bug.h. This simplifies that.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/asm-generic/bug.h | 24 ++++++++++++++++++++++++
 tools/include/linux/bug.h       |  6 ++++++
 tools/include/linux/kernel.h    |  2 ++
 3 files changed, 32 insertions(+)
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/linux/bug.h

diff --git a/tools/include/asm-generic/bug.h b/tools/include/asm-generic/bug.h
new file mode 100644
index 000000000000..7b0f48b60dbe
--- /dev/null
+++ b/tools/include/asm-generic/bug.h
@@ -0,0 +1,24 @@
+#ifndef __TOOLS_ASM_GENERIC_BUG
+#define __TOOLS_ASM_GENERIC_BUG
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define BUG() do {										\
+	fprintf(stderr, "----------------------------------------------------------\n");	\
+	fprintf (stderr, "BUG on %s at %s: %i\n", __func__, __FILE__, __LINE__);		\
+	abort();										\
+}												\
+while (0)
+
+#define BUG_ON(cond) do { if (cond) BUG(); } while (0)
+
+#define WARN_ON(__test) do {									\
+	if (__test) {										\
+		fprintf(stderr, "----------------------------------------------------------\n");\
+		fprintf (stderr, "WARN_ON on %s at %s: %i\n", __func__, __FILE__, __LINE__);	\
+	}											\
+}												\
+while (0)
+
+#endif /* __TOOLS_ASM_GENERIC_BUG */
diff --git a/tools/include/linux/bug.h b/tools/include/linux/bug.h
new file mode 100644
index 000000000000..9be515b40b5c
--- /dev/null
+++ b/tools/include/linux/bug.h
@@ -0,0 +1,6 @@
+#ifndef _TOOLS_LINUX_BUG_H
+#define _TOOLS_LINUX_BUG_H
+
+#include <asm-generic/bug.h>
+
+#endif /* _TOOLS_LINUX_BUG_H */
diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
index 28607db02bd3..3d385a6d4fc1 100644
--- a/tools/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -5,6 +5,8 @@
 #include <stddef.h>
 #include <assert.h>
 
+#include <linux/bug.h>
+
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 
 #define PERF_ALIGN(x, a)	__PERF_ALIGN_MASK(x, (typeof(x))(a)-1)
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v1 1/7] tools: add a userspace tools bug.h
@ 2016-08-19 21:41       ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, jolsa,
	msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This will be used later by the userspace linker-tables sandbox.
As a convenience, include bug.h on kernel.h -- this is not done
on upstream kernel.h, however most header files do include bug.h
eventually, if we were to only add the ones that need it we'd
need to copy a lot of headers to tools for the ony purpose of
includeing bug.h. This simplifies that.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/asm-generic/bug.h | 24 ++++++++++++++++++++++++
 tools/include/linux/bug.h       |  6 ++++++
 tools/include/linux/kernel.h    |  2 ++
 3 files changed, 32 insertions(+)
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/linux/bug.h

diff --git a/tools/include/asm-generic/bug.h b/tools/include/asm-generic/bug.h
new file mode 100644
index 000000000000..7b0f48b60dbe
--- /dev/null
+++ b/tools/include/asm-generic/bug.h
@@ -0,0 +1,24 @@
+#ifndef __TOOLS_ASM_GENERIC_BUG
+#define __TOOLS_ASM_GENERIC_BUG
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define BUG() do {										\
+	fprintf(stderr, "----------------------------------------------------------\n");	\
+	fprintf (stderr, "BUG on %s at %s: %i\n", __func__, __FILE__, __LINE__);		\
+	abort();										\
+}												\
+while (0)
+
+#define BUG_ON(cond) do { if (cond) BUG(); } while (0)
+
+#define WARN_ON(__test) do {									\
+	if (__test) {										\
+		fprintf(stderr, "----------------------------------------------------------\n");\
+		fprintf (stderr, "WARN_ON on %s at %s: %i\n", __func__, __FILE__, __LINE__);	\
+	}											\
+}												\
+while (0)
+
+#endif /* __TOOLS_ASM_GENERIC_BUG */
diff --git a/tools/include/linux/bug.h b/tools/include/linux/bug.h
new file mode 100644
index 000000000000..9be515b40b5c
--- /dev/null
+++ b/tools/include/linux/bug.h
@@ -0,0 +1,6 @@
+#ifndef _TOOLS_LINUX_BUG_H
+#define _TOOLS_LINUX_BUG_H
+
+#include <asm-generic/bug.h>
+
+#endif /* _TOOLS_LINUX_BUG_H */
diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
index 28607db02bd3..3d385a6d4fc1 100644
--- a/tools/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -5,6 +5,8 @@
 #include <stddef.h>
 #include <assert.h>
 
+#include <linux/bug.h>
+
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 
 #define PERF_ALIGN(x, a)	__PERF_ALIGN_MASK(x, (typeof(x))(a)-1)
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v1 2/7] tools: add a basic tools printk.h
  2016-08-19 21:41     ` mcgrof
  (?)
@ 2016-08-19 21:41       ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This will be used later by the userspace linker-tables sandbox.
Since upstream kernel.h includes printk.h mimic this so we can
match and replicate C code as-is on userspace sandbox tools.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/kernel.h |  1 +
 tools/include/linux/printk.h | 14 ++++++++++++++
 2 files changed, 15 insertions(+)
 create mode 100644 tools/include/linux/printk.h

diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
index 3d385a6d4fc1..afdf760bf35c 100644
--- a/tools/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -6,6 +6,7 @@
 #include <assert.h>
 
 #include <linux/bug.h>
+#include <linux/printk.h>
 
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 
diff --git a/tools/include/linux/printk.h b/tools/include/linux/printk.h
new file mode 100644
index 000000000000..7e34e9c817e8
--- /dev/null
+++ b/tools/include/linux/printk.h
@@ -0,0 +1,14 @@
+#ifndef __TOOLS_KERNEL_PRINTK__
+#define __TOOLS_KERNEL_PRINTK__
+
+#include <stdio.h>
+
+#ifndef pr_fmt
+#define pr_fmt(fmt)	fmt
+#endif
+
+#define pr_info(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_err(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_debug(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+
+#endif /* __TOOLS_KERNEL_PRINTK__ */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v1 2/7] tools: add a basic tools printk.h
@ 2016-08-19 21:41       ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This will be used later by the userspace linker-tables sandbox.
Since upstream kernel.h includes printk.h mimic this so we can
match and replicate C code as-is on userspace sandbox tools.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/kernel.h |  1 +
 tools/include/linux/printk.h | 14 ++++++++++++++
 2 files changed, 15 insertions(+)
 create mode 100644 tools/include/linux/printk.h

diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
index 3d385a6d4fc1..afdf760bf35c 100644
--- a/tools/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -6,6 +6,7 @@
 #include <assert.h>
 
 #include <linux/bug.h>
+#include <linux/printk.h>
 
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 
diff --git a/tools/include/linux/printk.h b/tools/include/linux/printk.h
new file mode 100644
index 000000000000..7e34e9c817e8
--- /dev/null
+++ b/tools/include/linux/printk.h
@@ -0,0 +1,14 @@
+#ifndef __TOOLS_KERNEL_PRINTK__
+#define __TOOLS_KERNEL_PRINTK__
+
+#include <stdio.h>
+
+#ifndef pr_fmt
+#define pr_fmt(fmt)	fmt
+#endif
+
+#define pr_info(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_err(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_debug(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+
+#endif /* __TOOLS_KERNEL_PRINTK__ */
-- 
2.9.2

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v1 2/7] tools: add a basic tools printk.h
@ 2016-08-19 21:41       ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, jolsa,
	msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This will be used later by the userspace linker-tables sandbox.
Since upstream kernel.h includes printk.h mimic this so we can
match and replicate C code as-is on userspace sandbox tools.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/kernel.h |  1 +
 tools/include/linux/printk.h | 14 ++++++++++++++
 2 files changed, 15 insertions(+)
 create mode 100644 tools/include/linux/printk.h

diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
index 3d385a6d4fc1..afdf760bf35c 100644
--- a/tools/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -6,6 +6,7 @@
 #include <assert.h>
 
 #include <linux/bug.h>
+#include <linux/printk.h>
 
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 
diff --git a/tools/include/linux/printk.h b/tools/include/linux/printk.h
new file mode 100644
index 000000000000..7e34e9c817e8
--- /dev/null
+++ b/tools/include/linux/printk.h
@@ -0,0 +1,14 @@
+#ifndef __TOOLS_KERNEL_PRINTK__
+#define __TOOLS_KERNEL_PRINTK__
+
+#include <stdio.h>
+
+#ifndef pr_fmt
+#define pr_fmt(fmt)	fmt
+#endif
+
+#define pr_info(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_err(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#define pr_debug(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+
+#endif /* __TOOLS_KERNEL_PRINTK__ */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v1 3/7] tools: add init.h for tools
  2016-08-19 21:41     ` mcgrof
  (?)
@ 2016-08-19 21:41       ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Start off with just __ref -- we enalbe you to override, if you do
that then you can define your own. The way you'd use this, if you
do override, is define your own __ref and then use include_next.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/init.h | 9 +++++++++
 1 file changed, 9 insertions(+)
 create mode 100644 tools/include/linux/init.h

diff --git a/tools/include/linux/init.h b/tools/include/linux/init.h
new file mode 100644
index 000000000000..6d970a360a05
--- /dev/null
+++ b/tools/include/linux/init.h
@@ -0,0 +1,9 @@
+#ifndef _TOOLS_LINUX_INIT_H
+#define _TOOLS_LINUX_INIT_H
+
+/* this means you can add your own to fit you own userspace needs */
+#ifndef __ref
+#define __ref
+#endif
+
+#endif /* _TOOLS_LINUX_INIT_H */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v1 3/7] tools: add init.h for tools
@ 2016-08-19 21:41       ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Start off with just __ref -- we enalbe you to override, if you do
that then you can define your own. The way you'd use this, if you
do override, is define your own __ref and then use include_next.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/init.h | 9 +++++++++
 1 file changed, 9 insertions(+)
 create mode 100644 tools/include/linux/init.h

diff --git a/tools/include/linux/init.h b/tools/include/linux/init.h
new file mode 100644
index 000000000000..6d970a360a05
--- /dev/null
+++ b/tools/include/linux/init.h
@@ -0,0 +1,9 @@
+#ifndef _TOOLS_LINUX_INIT_H
+#define _TOOLS_LINUX_INIT_H
+
+/* this means you can add your own to fit you own userspace needs */
+#ifndef __ref
+#define __ref
+#endif
+
+#endif /* _TOOLS_LINUX_INIT_H */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v1 3/7] tools: add init.h for tools
@ 2016-08-19 21:41       ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, jolsa,
	msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Start off with just __ref -- we enalbe you to override, if you do
that then you can define your own. The way you'd use this, if you
do override, is define your own __ref and then use include_next.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/init.h | 9 +++++++++
 1 file changed, 9 insertions(+)
 create mode 100644 tools/include/linux/init.h

diff --git a/tools/include/linux/init.h b/tools/include/linux/init.h
new file mode 100644
index 000000000000..6d970a360a05
--- /dev/null
+++ b/tools/include/linux/init.h
@@ -0,0 +1,9 @@
+#ifndef _TOOLS_LINUX_INIT_H
+#define _TOOLS_LINUX_INIT_H
+
+/* this means you can add your own to fit you own userspace needs */
+#ifndef __ref
+#define __ref
+#endif
+
+#endif /* _TOOLS_LINUX_INIT_H */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v1 4/7] tools: add __used and enable to override
  2016-08-19 21:41     ` mcgrof
  (?)
@ 2016-08-19 21:41       ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This adds __used, to be used later in the userspace linker-tables
sandbox. If any userspace applicaiton wants to override they can
add their own definition and then use include_next.

This definition should probably suffice for most uses cases though.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index e33fc1df3935..556c991de212 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -5,6 +5,12 @@
 /* The "volatile" is due to gcc bugs */
 #define barrier() __asm__ __volatile__("": : :"memory")
 
+
+/* You can override as you see fit on your userspace tool */
+#ifndef __used
+#define __used          __attribute__((__used__))
+#endif
+
 #ifndef __always_inline
 # define __always_inline	inline __attribute__((always_inline))
 #endif
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v1 4/7] tools: add __used and enable to override
@ 2016-08-19 21:41       ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This adds __used, to be used later in the userspace linker-tables
sandbox. If any userspace applicaiton wants to override they can
add their own definition and then use include_next.

This definition should probably suffice for most uses cases though.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index e33fc1df3935..556c991de212 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -5,6 +5,12 @@
 /* The "volatile" is due to gcc bugs */
 #define barrier() __asm__ __volatile__("": : :"memory")
 
+
+/* You can override as you see fit on your userspace tool */
+#ifndef __used
+#define __used          __attribute__((__used__))
+#endif
+
 #ifndef __always_inline
 # define __always_inline	inline __attribute__((always_inline))
 #endif
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v1 4/7] tools: add __used and enable to override
@ 2016-08-19 21:41       ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, jolsa,
	msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This adds __used, to be used later in the userspace linker-tables
sandbox. If any userspace applicaiton wants to override they can
add their own definition and then use include_next.

This definition should probably suffice for most uses cases though.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index e33fc1df3935..556c991de212 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -5,6 +5,12 @@
 /* The "volatile" is due to gcc bugs */
 #define barrier() __asm__ __volatile__("": : :"memory")
 
+
+/* You can override as you see fit on your userspace tool */
+#ifndef __used
+#define __used          __attribute__((__used__))
+#endif
+
 #ifndef __always_inline
 # define __always_inline	inline __attribute__((always_inline))
 #endif
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v1 5/7] tools: expand export.h with VMLINUX_SYMBOL()
  2016-08-19 21:41     ` mcgrof
  (?)
@ 2016-08-19 21:41       ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This will be used later by the linker-table userspace sandbox.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/export.h | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/tools/include/linux/export.h b/tools/include/linux/export.h
index d07e586b9ba0..cb7d6b490e08 100644
--- a/tools/include/linux/export.h
+++ b/tools/include/linux/export.h
@@ -1,6 +1,28 @@
 #ifndef _TOOLS_LINUX_EXPORT_H_
 #define _TOOLS_LINUX_EXPORT_H_
 
+/*
+ * Export symbols from the kernel to modules.  Forked from module.h
+ * to reduce the amount of pointless cruft we feed to gcc when only
+ * exporting a simple symbol or two.
+ *
+ * Try not to add #includes here.  It slows compilation and makes kernel
+ * hackers place grumpy comments in header files.
+ */
+
+/* Some toolchains use a `_' prefix for all user symbols. */
+#ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX
+#define __VMLINUX_SYMBOL(x) _##x
+#define __VMLINUX_SYMBOL_STR(x) "_" #x
+#else
+#define __VMLINUX_SYMBOL(x) x
+#define __VMLINUX_SYMBOL_STR(x) #x
+#endif
+
+/* Indirect, so macros are expanded before pasting. */
+#define VMLINUX_SYMBOL(x) __VMLINUX_SYMBOL(x)
+#define VMLINUX_SYMBOL_STR(x) __VMLINUX_SYMBOL_STR(x)
+
 #define EXPORT_SYMBOL(sym)
 #define EXPORT_SYMBOL_GPL(sym)
 #define EXPORT_SYMBOL_GPL_FUTURE(sym)
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v1 5/7] tools: expand export.h with VMLINUX_SYMBOL()
@ 2016-08-19 21:41       ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This will be used later by the linker-table userspace sandbox.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/export.h | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/tools/include/linux/export.h b/tools/include/linux/export.h
index d07e586b9ba0..cb7d6b490e08 100644
--- a/tools/include/linux/export.h
+++ b/tools/include/linux/export.h
@@ -1,6 +1,28 @@
 #ifndef _TOOLS_LINUX_EXPORT_H_
 #define _TOOLS_LINUX_EXPORT_H_
 
+/*
+ * Export symbols from the kernel to modules.  Forked from module.h
+ * to reduce the amount of pointless cruft we feed to gcc when only
+ * exporting a simple symbol or two.
+ *
+ * Try not to add #includes here.  It slows compilation and makes kernel
+ * hackers place grumpy comments in header files.
+ */
+
+/* Some toolchains use a `_' prefix for all user symbols. */
+#ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX
+#define __VMLINUX_SYMBOL(x) _##x
+#define __VMLINUX_SYMBOL_STR(x) "_" #x
+#else
+#define __VMLINUX_SYMBOL(x) x
+#define __VMLINUX_SYMBOL_STR(x) #x
+#endif
+
+/* Indirect, so macros are expanded before pasting. */
+#define VMLINUX_SYMBOL(x) __VMLINUX_SYMBOL(x)
+#define VMLINUX_SYMBOL_STR(x) __VMLINUX_SYMBOL_STR(x)
+
 #define EXPORT_SYMBOL(sym)
 #define EXPORT_SYMBOL_GPL(sym)
 #define EXPORT_SYMBOL_GPL_FUTURE(sym)
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v1 5/7] tools: expand export.h with VMLINUX_SYMBOL()
@ 2016-08-19 21:41       ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, jolsa,
	msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This will be used later by the linker-table userspace sandbox.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/export.h | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/tools/include/linux/export.h b/tools/include/linux/export.h
index d07e586b9ba0..cb7d6b490e08 100644
--- a/tools/include/linux/export.h
+++ b/tools/include/linux/export.h
@@ -1,6 +1,28 @@
 #ifndef _TOOLS_LINUX_EXPORT_H_
 #define _TOOLS_LINUX_EXPORT_H_
 
+/*
+ * Export symbols from the kernel to modules.  Forked from module.h
+ * to reduce the amount of pointless cruft we feed to gcc when only
+ * exporting a simple symbol or two.
+ *
+ * Try not to add #includes here.  It slows compilation and makes kernel
+ * hackers place grumpy comments in header files.
+ */
+
+/* Some toolchains use a `_' prefix for all user symbols. */
+#ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX
+#define __VMLINUX_SYMBOL(x) _##x
+#define __VMLINUX_SYMBOL_STR(x) "_" #x
+#else
+#define __VMLINUX_SYMBOL(x) x
+#define __VMLINUX_SYMBOL_STR(x) #x
+#endif
+
+/* Indirect, so macros are expanded before pasting. */
+#define VMLINUX_SYMBOL(x) __VMLINUX_SYMBOL(x)
+#define VMLINUX_SYMBOL_STR(x) __VMLINUX_SYMBOL_STR(x)
+
 #define EXPORT_SYMBOL(sym)
 #define EXPORT_SYMBOL_GPL(sym)
 #define EXPORT_SYMBOL_GPL_FUTURE(sym)
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v1 6/7] tools: add __section() to compiler.h
  2016-08-19 21:41     ` mcgrof
  (?)
@ 2016-08-19 21:41       ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This will be used later by the userspace linker table.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index 556c991de212..6321265df00a 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -132,4 +132,6 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 #define WRITE_ONCE(x, val) \
 	({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
 
+#define __section(S)	__attribute__ ((__section__(#S)))
+
 #endif /* _TOOLS_LINUX_COMPILER_H */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v1 6/7] tools: add __section() to compiler.h
@ 2016-08-19 21:41       ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This will be used later by the userspace linker table.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index 556c991de212..6321265df00a 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -132,4 +132,6 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 #define WRITE_ONCE(x, val) \
 	({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
 
+#define __section(S)	__attribute__ ((__section__(#S)))
+
 #endif /* _TOOLS_LINUX_COMPILER_H */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v1 6/7] tools: add __section() to compiler.h
@ 2016-08-19 21:41       ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, jolsa,
	msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley, Luis R. Rodriguez

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

This will be used later by the userspace linker table.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index 556c991de212..6321265df00a 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -132,4 +132,6 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 #define WRITE_ONCE(x, val) \
 	({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
 
+#define __section(S)	__attribute__ ((__section__(#S)))
+
 #endif /* _TOOLS_LINUX_COMPILER_H */
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v1 7/7] tools: add userspace linker table sandbox
  2016-08-19 21:41     ` mcgrof
@ 2016-08-19 21:41       ` mcgrof
  -1 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Add a userspace sandbox to allow easy experimentation and
test extensions with linker tables, section ranges and the
new section core definitions.

The userspace sandbox tries to mimic the Linux kernel development
flow as much as possible, it however relies on and uses libc. Support
is currently only provided to x86_64.

v4: this patch is new in this series -- added to the kenrel as
    suggested by Boris, as otherwise it'd be really hard to keep
    an external userspace repository in sync.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/linker-tables.rst           |   4 +-
 MAINTAINERS                                        |   1 +
 include/linux/tables.h                             |   5 +-
 tools/Makefile                                     |   3 +-
 .../arch/x86/include/generated/asm/section-core.h  |   1 +
 tools/arch/x86/include/generated/ranges.h          |   1 +
 tools/arch/x86/include/generated/tables.h          |   1 +
 tools/include/asm-generic/ranges.h                 | 103 ++++
 tools/include/asm-generic/section-core.h           | 341 +++++++++++
 tools/include/asm-generic/tables.h                 |  50 ++
 tools/include/linux/ranges.h                       | 128 ++++
 tools/include/linux/sections.h                     | 111 ++++
 tools/include/linux/string.h                       |   1 +
 tools/include/linux/tables.h                       | 664 +++++++++++++++++++++
 tools/linker-tables/.gitignore                     |   2 +
 tools/linker-tables/Makefile                       | 184 ++++++
 tools/linker-tables/README                         | 114 ++++
 tools/linker-tables/arch/x86/include/asm/asm.h     |  17 +
 tools/linker-tables/arch/x86/include/asm/boot.h    |   1 +
 .../linker-tables/arch/x86/include/asm/bootparam.h |  32 +
 tools/linker-tables/arch/x86/include/asm/kprobes.h |   7 +
 .../linker-tables/arch/x86/include/asm/ps_const.h  |  21 +
 tools/linker-tables/arch/x86/include/asm/ranges.h  |   6 +
 .../arch/x86/include/asm/section-core.h            |   1 +
 tools/linker-tables/arch/x86/include/asm/setup.h   |   6 +
 tools/linker-tables/arch/x86/include/asm/tables.h  |   6 +
 tools/linker-tables/arch/x86/include/asm/x86.h     |   4 +
 .../arch/x86/include/asm/x86_init_fn.h             | 169 ++++++
 tools/linker-tables/arch/x86/kernel/alpha.c        |   9 +
 tools/linker-tables/arch/x86/kernel/alternative.c  |  31 +
 tools/linker-tables/arch/x86/kernel/beta.c         |   9 +
 tools/linker-tables/arch/x86/kernel/head64.c       |  58 ++
 tools/linker-tables/arch/x86/kernel/init.c         |  42 ++
 tools/linker-tables/arch/x86/kernel/kasan.c        |  10 +
 tools/linker-tables/arch/x86/kernel/kprobes.c      |  51 ++
 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S  | 273 +++++++++
 tools/linker-tables/arch/x86/mm/init.c             |  10 +
 tools/linker-tables/arch/x86/xen/init.c            |  13 +
 tools/linker-tables/drivers/acme.c                 |  32 +
 tools/linker-tables/drivers/synth/common.c         |  16 +
 tools/linker-tables/drivers/synth/common.h         |   2 +
 tools/linker-tables/drivers/synth/main.c           |  35 ++
 tools/linker-tables/drivers/synth/or.S             |  39 ++
 tools/linker-tables/drivers/synth/synth.h          |   2 +
 tools/linker-tables/drivers/xen-driver.c           |  11 +
 .../include/asm-generic/arch_init_fn.h             |  50 ++
 tools/linker-tables/include/asm-generic/kprobes.h  |  26 +
 tools/linker-tables/include/linux/bitops.h         |   6 +
 tools/linker-tables/include/linux/init.h           |  40 ++
 tools/linker-tables/include/linux/kasan.h          |   5 +
 tools/linker-tables/include/linux/kprobes.h        |  11 +
 tools/linker-tables/include/linux/module.h         |  14 +
 tools/linker-tables/include/linux/mutex.h          |  17 +
 tools/linker-tables/include/linux/pci.h            |   7 +
 tools/linker-tables/include/linux/ps_const.h       |  46 ++
 tools/linker-tables/include/linux/sched.h          |   9 +
 tools/linker-tables/include/linux/spinlock.h       |  13 +
 tools/linker-tables/include/linux/start_kernel.h   |   1 +
 tools/linker-tables/include/linux/types.h          |  13 +
 tools/linker-tables/include/linux/workqueue.h      |  51 ++
 tools/linker-tables/include/xen/xen.h              |   4 +
 tools/linker-tables/kernel/locking/mutex.c         |  28 +
 tools/linker-tables/kernel/locking/spinlock.c      |  26 +
 tools/linker-tables/kernel/main.c                  |  32 +
 tools/linker-tables/kernel/workqueue.c             |  43 ++
 tools/linker-tables/lib/string.c                   |  26 +
 tools/linker-tables/main.c                         |  20 +
 tools/linker-tables/pci-quirks.c                   |  13 +
 tools/linker-tables/pci.c                          |  29 +
 69 files changed, 3152 insertions(+), 5 deletions(-)
 create mode 100644 tools/arch/x86/include/generated/asm/section-core.h
 create mode 100644 tools/arch/x86/include/generated/ranges.h
 create mode 100644 tools/arch/x86/include/generated/tables.h
 create mode 100644 tools/include/asm-generic/ranges.h
 create mode 100644 tools/include/asm-generic/section-core.h
 create mode 100644 tools/include/asm-generic/tables.h
 create mode 100644 tools/include/linux/ranges.h
 create mode 100644 tools/include/linux/sections.h
 create mode 100644 tools/include/linux/tables.h
 create mode 100644 tools/linker-tables/.gitignore
 create mode 100644 tools/linker-tables/Makefile
 create mode 100644 tools/linker-tables/README
 create mode 100644 tools/linker-tables/arch/x86/include/asm/asm.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/boot.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/bootparam.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/kprobes.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ps_const.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ranges.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/section-core.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/setup.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/tables.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
 create mode 100644 tools/linker-tables/arch/x86/kernel/alpha.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/alternative.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/beta.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/head64.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/init.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kasan.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kprobes.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
 create mode 100644 tools/linker-tables/arch/x86/mm/init.c
 create mode 100644 tools/linker-tables/arch/x86/xen/init.c
 create mode 100644 tools/linker-tables/drivers/acme.c
 create mode 100644 tools/linker-tables/drivers/synth/common.c
 create mode 100644 tools/linker-tables/drivers/synth/common.h
 create mode 100644 tools/linker-tables/drivers/synth/main.c
 create mode 100644 tools/linker-tables/drivers/synth/or.S
 create mode 100644 tools/linker-tables/drivers/synth/synth.h
 create mode 100644 tools/linker-tables/drivers/xen-driver.c
 create mode 100644 tools/linker-tables/include/asm-generic/arch_init_fn.h
 create mode 100644 tools/linker-tables/include/asm-generic/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/bitops.h
 create mode 100644 tools/linker-tables/include/linux/init.h
 create mode 100644 tools/linker-tables/include/linux/kasan.h
 create mode 100644 tools/linker-tables/include/linux/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/module.h
 create mode 100644 tools/linker-tables/include/linux/mutex.h
 create mode 100644 tools/linker-tables/include/linux/pci.h
 create mode 100644 tools/linker-tables/include/linux/ps_const.h
 create mode 100644 tools/linker-tables/include/linux/sched.h
 create mode 100644 tools/linker-tables/include/linux/spinlock.h
 create mode 100644 tools/linker-tables/include/linux/start_kernel.h
 create mode 100644 tools/linker-tables/include/linux/types.h
 create mode 100644 tools/linker-tables/include/linux/workqueue.h
 create mode 100644 tools/linker-tables/include/xen/xen.h
 create mode 100644 tools/linker-tables/kernel/locking/mutex.c
 create mode 100644 tools/linker-tables/kernel/locking/spinlock.c
 create mode 100644 tools/linker-tables/kernel/main.c
 create mode 100644 tools/linker-tables/kernel/workqueue.c
 create mode 100644 tools/linker-tables/lib/string.c
 create mode 100644 tools/linker-tables/main.c
 create mode 100644 tools/linker-tables/pci-quirks.c
 create mode 100644 tools/linker-tables/pci.c

diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index e425c5cd36d6..1fec5b81df31 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -11,11 +11,11 @@ About Linker tables
 .. kernel-doc:: include/linux/tables.h
    :doc: Introduction
 
-Linker table provenance
+Linker table provenance and userspace testing
 ---------------------------------------------
 
 .. kernel-doc:: include/linux/tables.h
-   :doc: Linker table provenance
+   :doc: Linker table provenance and userspace testing
 
 Benefits of using Linker tables
 ===============================
diff --git a/MAINTAINERS b/MAINTAINERS
index e3569ed12c86..bd57f5e6e480 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5210,6 +5210,7 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux-next.git secti
 S:	Supported
 F:	include/asm-generic/tables.h
 F:	include/linux/tables.h
+F:	tools/linker-tables/
 F:	Documentation/sections/linker-tables.rst
 
 GENERIC PHY FRAMEWORK
diff --git a/include/linux/tables.h b/include/linux/tables.h
index bf8fae7f9246..77b7efb90bc8 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -35,12 +35,13 @@
  */
 
 /**
- * DOC: Linker table provenance
+ * DOC: Linker table provenance and userspace testing
  *
  * 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].
+ * userspace linker-table tree [1]. Linux has a similar userspace application
+ * in tools/linker-tables/ to help more easily test adding new extensions.
  *
  * Contrary to iPXE's solution which strives to force compilation of
  * everything using linker tables, Linux's solution allows for developers to be
diff --git a/tools/Makefile b/tools/Makefile
index daa8fb3e4363..731d1f5837cd 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -18,6 +18,7 @@ help:
 	@echo '  iio                    - IIO tools'
 	@echo '  kvm_stat               - top-like utility for displaying kvm statistics'
 	@echo '  lguest                 - a minimal 32-bit x86 hypervisor'
+	@echo '  linker-tables		- userspace liker table sandbox and related tools'
 	@echo '  net                    - misc networking tools'
 	@echo '  perf                   - Linux performance measurement and analysis tool'
 	@echo '  selftests              - various kernel selftests'
@@ -85,7 +86,7 @@ tmon: FORCE
 freefall: FORCE
 	$(call descend,laptop/$@)
 
-all: acpi cgroup cpupower gpio hv firewire lguest \
+all: acpi cgroup cpupower gpio hv firewire lguest linker-tables \
 		perf selftests turbostat usb \
 		virtio vm net x86_energy_perf_policy \
 		tmon freefall objtool
diff --git a/tools/arch/x86/include/generated/asm/section-core.h b/tools/arch/x86/include/generated/asm/section-core.h
new file mode 100644
index 000000000000..06be2b1c424f
--- /dev/null
+++ b/tools/arch/x86/include/generated/asm/section-core.h
@@ -0,0 +1 @@
+#include <asm-generic/section-core.h>
diff --git a/tools/arch/x86/include/generated/ranges.h b/tools/arch/x86/include/generated/ranges.h
new file mode 100644
index 000000000000..dac1a9a11367
--- /dev/null
+++ b/tools/arch/x86/include/generated/ranges.h
@@ -0,0 +1 @@
+#include <asm-generic/ranges.h>
diff --git a/tools/arch/x86/include/generated/tables.h b/tools/arch/x86/include/generated/tables.h
new file mode 100644
index 000000000000..d437818275c5
--- /dev/null
+++ b/tools/arch/x86/include/generated/tables.h
@@ -0,0 +1 @@
+#include <asm-generic/tables.h>
diff --git a/tools/include/asm-generic/ranges.h b/tools/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..8cf21a1497c6
--- /dev/null
+++ b/tools/include/asm-generic/ranges.h
@@ -0,0 +1,103 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#define SECTION_RNG(section, name)					\
+	SECTION_CORE(section, rng, name,				\
+		     SECTION_ORDER_ANY)
+
+#define SECTION_RNG_LEVEL(section, name, level)				\
+	SECTION_CORE(section, rng, name, level)
+
+#define SECTION_RNG_ALL(section)					\
+	SECTION_CORE_ALL(section,rng)
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  SECTION_ORDER_ANY, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       SECTION_ORDER_ANY, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   SECTION_ORDER_ANY, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(SECTION_RNG(section, name))))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using
+ * 	binutils SORT(), the number is sorted as a string, as such be
+ * 	sure to fill with zeroes any empty digits. For instance if you are
+ * 	using 3 levels of digits for order levels, use 001 for the first entry,
+ * 	0002 for the second, 999 for the last entry. You can use however many
+ * 	digits you need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(SECTION_RNG_LEVEL(section, name, level))))
+
+#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/tools/include/asm-generic/section-core.h b/tools/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..2ab57e2c4117
--- /dev/null
+++ b/tools/include/asm-generic/section-core.h
@@ -0,0 +1,341 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Custom linker script
+ *
+ * The Linux vmlinux binary uses a custom linker script on each architecture
+ * which it uses to strategically place standard ELF sections and also adds
+ * custom specialized ELF sections. Each architecture defines its own custom
+ * linker defined in arch/$(ARCH)/kernel/vmlinux.lds.S -- these in turn
+ * include and use definitions in include/asm-generic/vmlinux.lds.h as well
+ * as some helpers documented in this chaper.
+ */
+
+/**
+ * DOC: Standard ELF section use in Linux
+ *
+ * Linux makes use of the standard ELF sections, this sections documents
+ * these.
+ */
+
+/**
+ * DOC: SECTION_RODATA
+ *
+ * Macro name for code which must be protected from write access, read only
+ * data.
+ */
+#define SECTION_RODATA			.rodata
+
+/**
+ * DOC: SECTION_TEXT
+ *
+ * Macro name used to annotate code (functions) used during regular
+ * kernel run time. This is combined with `SECTION_RODATA`, only this
+ * section also allows for execution.
+ *
+ */
+#define SECTION_TEXT			.text
+
+/**
+ * DOC: SECTION_DATA
+ *
+ * Macro name for read-write data.
+ */
+#define SECTION_DATA			.data
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: SECTION_INIT
+ *
+ * Macro name used to annotate code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+#define SECTION_INIT			.init.text
+
+/**
+ * DOC: SECTION_INIT_DATA
+ *
+ * Macro name used to annotate data structures used only during boot or driver
+ * initialization.
+ */
+#define SECTION_INIT_DATA		.init.data
+
+/**
+ * DOC: SECTION_INIT_RODATA
+ *
+ * Macro name used to annotate read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+#define SECTION_INIT_RODATA		.init.rodata
+
+/**
+ * DOC: SECTION_INIT_CALL
+ *
+ * Special macro name used to annotate subsystem init call. These calls are
+ * are now grouped by functionality into separate subsections. Ordering inside
+ * the subsections is determined by link order.
+ */
+#define SECTION_INIT_CALL		.initcall
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: SECTION_EXIT
+ *
+ * Macro name used to annotate code (functions) used only during module
+ * unload.
+ */
+#define SECTION_EXIT			.exit.text
+
+/**
+ * DOC: SECTION_EXIT_DATA
+ *
+ * Macro name used to annotate data structures used only during module
+ * unload.
+ */
+#define SECTION_EXIT_DATA		.exit.data
+
+/**
+ * DOC: SECTION_EXIT_CALL
+ *
+ * Special macro name used to annotate an exit exit routine, order
+ * is important and maintained by link order.
+ */
+#define SECTION_EXIT_CALL		.exitcall.exit
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: SECTION_REF
+ *
+ * Macro name used to annotate that code (functions) declared with this section
+ * has been vetteed as valid for its reference or use of other code (functions)
+ * or data structures which are part of the init sections.
+ */
+#define SECTION_REF			.ref.text
+
+/**
+ * DOC: SECTION_REF_DATA
+ *
+ * Macro name used to annotate data structures declared with this section have
+ * been vetteed for its reference or use of other code (functions) or data
+ * structures part of the init sections.
+ */
+#define SECTION_REF_DATA		.ref.data
+
+/**
+ * DOC: SECTION_REF_RODATA
+ *
+ * Macro name used to annotate const code (functions) const data structures
+ * which has been vetteed for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+#define SECTION_REF_RODATA		.ref.rodata
+
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections. Linux has used 'SORT()' in ``include/asm-generic/vmlinux.lds.h``
+ * for years.
+ */
+
+/**
+ * DOC: SECTION_ORDER_ANY
+ *
+ * Macro name which can be used as helper to annotate custom section
+ * ordering at link time is not relevant for specific sections.
+ */
+#define SECTION_ORDER_ANY	any
+
+/*
+ * These section _ALL() helpers are for use on linker scripts and helpers
+ */
+#define SECTION_ALL(__section)						\
+	__section##.*
+
+#define __SECTION_CORE(__section, __core, __name, __level)		\
+	__section.__core.__name.__level
+
+#define SECTION_CORE_ALL(__section, __core)				\
+	__section##.##__core##.*
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section.___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section.___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section.__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifdef LINKER_SCRIPT
+
+#  ifndef SECTION_CORE
+#   define SECTION_CORE(__section, __core, __name, __level)		\
+	__SECTION_CORE(__section,__core,__name,__level)
+#  endif
+
+# else
+
+#  ifndef SECTION_CORE
+#   define SECTION_CORE(__section, __core, __name, __level)		\
+	push_section_core(__section, __core, __name, __level,)
+#  endif
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+# ifndef SECTION_CORE
+#  define SECTION_CORE(__section, __core, __name, __level)		\
+	__stringify(__SECTION_CORE(__section,__core,__name,__level))
+# endif
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align=16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/tools/include/asm-generic/tables.h b/tools/include/asm-generic/tables.h
new file mode 100644
index 000000000000..43cd03a83bd2
--- /dev/null
+++ b/tools/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@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_ */
diff --git a/tools/include/linux/ranges.h b/tools/include/linux/ranges.h
new file mode 100644
index 000000000000..30b2182bd484
--- /dev/null
+++ b/tools/include/linux/ranges.h
@@ -0,0 +1,128 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(VMLINUX_SYMBOL(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+			     section(SECTION_RNG_LEVEL(__section, name,))))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(VMLINUX_SYMBOL(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+			     section(SECTION_RNG_LEVEL(__section, name, ~))))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) VMLINUX_SYMBOL(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) VMLINUX_SYMBOL(name##__end)[0] = {}
+
+/**
+ * SECTION_ADDR_IN_RANGE - returns true if address is in range
+ *
+ * @name: section range name
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_ADDR_IN_RANGE(name, addr)				\
+	 (addr >= (unsigned long) LINUX_SECTION_START(name) &&		\
+	  addr <  (unsigned long) LINUX_SECTION_END(name))
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
diff --git a/tools/include/linux/sections.h b/tools/include/linux/sections.h
new file mode 100644
index 000000000000..f21c6ee88ded
--- /dev/null
+++ b/tools/include/linux/sections.h
@@ -0,0 +1,111 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_SIZE - get number of entries in the section
+ *
+ * @name: section name
+ *
+ * This gives you the number of entries in the section.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINUX_SECTION_SIZE(frobnicator_fns);
+ */
+#define LINUX_SECTION_SIZE(name)					\
+	((VMLINUX_SYMBOL(name##__end)) - (VMLINUX_SYMBOL(name)))
+
+/**
+ * LINUX_SECTION_EMPTY - check if section has no entries
+ *
+ * @name: section name
+ *
+ * Returns true if section is emtpy.
+ *
+ *   bool is_empty = LINUX_SECTION_EMPTY(frobnicator_fns);
+ */
+#define LINUX_SECTION_EMPTY(name)	(LINUX_SECTION_SIZE(name) == 0)
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_TYPE(section, type, name, level)			\
+	#section "." #type "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
diff --git a/tools/include/linux/string.h b/tools/include/linux/string.h
index f436d2420a18..a6b12564bbd9 100644
--- a/tools/include/linux/string.h
+++ b/tools/include/linux/string.h
@@ -3,6 +3,7 @@
 
 
 #include <linux/types.h>	/* for size_t */
+#include <string.h>
 
 void *memdup(const void *src, size_t len);
 
diff --git a/tools/include/linux/tables.h b/tools/include/linux/tables.h
new file mode 100644
index 000000000000..deb951b4ae37
--- /dev/null
+++ b/tools/include/linux/tables.h
@@ -0,0 +1,664 @@
+#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 and userspace testing
+ *
+ * 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]. Linux has a similar userspace application
+ * in tools/linker-tables/ to help more easily test adding new extensions.
+ *
+ * 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: The code bit-rot problem
+ *
+ * Overuse of C #ifdefs can be problematic for certain types of code.  Linux
+ * provides a rich array of features, but all these features take up valuable
+ * space in a kernel image. The traditional solution to this problem has been
+ * for each feature to have its own Kconfig entry and for the respective code
+ * to be wrapped around #ifdefs, allowing the feature to be compiled in only
+ * if enabled in Kconfig.
+ *
+ * The problem with this is that over time it becomes very difficult and time
+ * consuming to compile, let alone test all possible Kconfig configurations.
+ * Code that is not typically used tends to suffer from bit-rot over time. It
+ * can become difficult to predict which combinations of compile-time options
+ * will result in code that can compile and link correctly.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem when desirable
+ *
+ * Linker tables can be used as one way to help solve the code bit-rot problem,
+ * and in turn diminish Kconfig complexity.  To use linker tables and to
+ * optionally take advantage of avoiding code bit-rot, feature code should be
+ * implemented in separate C files, and should be designed to always be
+ * compiled -- they should not be guarded with C code ``#ifdef CONFIG_FOO``
+ * statements, consideration must also be taken for sub-features which depend
+ * on the main ``CONFIG_FOO`` option, as they will be disabled if they depend
+ * on ``CONFIG_FOO`` and therefore not compiled.
+ *
+ * To take advantage of this feature enable ``CONFIG_BUILD_AVOID_BITROT``, and
+ * use special targets for your code. Either ``force-obj-y`` or ``force-lib-y``
+ * can be used for your code instead of ``obj-y`` and ``lib-y``, respectively.
+ * Without ``CONFIG_BUILD_AVOID_BITROT`` enabled these targets will work just
+ * as their respective ``obj-y`` and ``lib-y`` counters work.  When
+ * ``CONFIG_BUILD_AVOID_BITROT`` is enabled the code with the special targets
+ * will always compile, even if the respective Kconfig entry for the code in
+ * question has been disabled, this code however will only be linked in to the
+ * final kernel image if the Kconfig entry for the code was enabled.
+ *
+ * Currently only built-in features are supported, modular support is not
+ * yet supported, however you can make use of sub-features for modules
+ * if they are independent and can simply be linked into modules.
+ *
+ * Care should be taken to vet that the code using this feature may also work
+ * without ``CONFIG_BUILD_AVOID_BITROT``, otherwise it must depend on
+ * CONFIG_BUILD_AVOID_BITROT.
+ */
+
+/**
+ * DOC: Using target force-obj-y and force-lib-y
+ *
+ * Let's assume we want to always force compilation of feature ``FOO`` in the
+ * kernel but avoid linking it. When you enable the ``FOO`` feature via Kconfig
+ * you'd end up with::
+ *
+ *	#define CONFIG_FOO 1
+ *
+ * You typically would then just use this in your Makefile to selectively
+ * compile and link the feature::
+ *
+ *	obj-$(CONFIG_FOO) += foo.o
+ *
+ * You could instead optionally use the new linker table target object::
+ *
+ *	force-obj-$(CONFIG_FOO) += foo.o
+ *
+ * Alternatively, this would be the equivalent of listing::
+ *
+ *	extra += foo.o
+ *	obj-$(CONFIG_FOO) += foo.o
+ *
+ * Both are mechanisms which can be used to take advantage of forcing
+ * compilation with linker tables, however making use of::
+ *
+ *	force-obj-$(CONFIG_FOO)
+ *
+ * is encouraged as it helps with annotating linker tables clearly where
+ * compilation is forced. The ``force-lib-y`` target is the equivalent for
+ * ``lib-y`` targets.
+ */
+
+/**
+ * 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: Opting out of forcing compilation
+ *
+ * If you want to opt-out of forcing compilation simply disable
+ * ``CONFIG_BUILD_AVOID_BITROT``.  Alternatively if your kernel configuration
+ * has it and you must have it enabled and you want to opt-out of forcing
+ * compilation you would use the typical ``obj-$(CONFIG_FOO) += foo.o`` and
+ * ``foo.o`` will only be compiled and linked in when ``CONFIG_FOO`` enabled.
+ * Using both ``force-obj-$(CONFIG_FOO)`` and ``obj-($CONFIG_FOO)`` will result
+ * with the feature on your binary only if you've enabled ``CONFIG_FOO``,
+ * however using ``force-obj-$(CONFIG_FOO)`` will always force compilation if
+ * ``CONFIG_BUILD_AVOID_BITROT`` has been enabled.
+ */
+
+/**
+ * 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/tools/linker-tables/.gitignore b/tools/linker-tables/.gitignore
new file mode 100644
index 000000000000..8275b0c55385
--- /dev/null
+++ b/tools/linker-tables/.gitignore
@@ -0,0 +1,2 @@
+arch/x86/kernel/vmlinux.lds
+demo
diff --git a/tools/linker-tables/Makefile b/tools/linker-tables/Makefile
new file mode 100644
index 000000000000..9d4e6fb0d176
--- /dev/null
+++ b/tools/linker-tables/Makefile
@@ -0,0 +1,184 @@
+include ../scripts/Makefile.include
+
+all:
+
+include ../scripts/utilities.mak
+
+MAKEFLAGS += --no-print-directory
+
+unexport LC_ALL
+LC_COLLATE=C
+LC_NUMERIC=C
+export LC_COLLATE LC_NUMERIC
+
+ifeq ($(srctree),)
+	srctree := $(patsubst %/,%,$(dir $(shell pwd)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Determined 'srctree' to be $(srctree))
+endif
+
+ifneq ($(objtree),)
+#$(info Determined 'objtree' to be $(objtree))
+endif
+
+ifneq ($(OUTPUT),)
+#$(info Determined 'OUTPUT' to be $(OUTPUT))
+# Adding $(OUTPUT) as a directory to look for source files,
+# because use generated output files as sources dependency
+# for flex/bison parsers.
+VPATH += $(OUTPUT)
+export VPATH
+endif
+
+export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK
+include $(srctree)/tools/build/Makefile.include
+
+ifeq ($(V),1)
+	Q=
+	NQ=@true
+else
+	Q=@
+	NQ=@echo
+endif
+
+MAKEFLAGS += -r
+
+define allow-override
+  $(if $(or $(findstring environment,$(origin $(1))),\
+            $(findstring command line,$(origin $(1)))),,\
+    $(eval $(1) = $(2)))
+endef
+
+# Allow setting CC and AR and LD, or setting CROSS_COMPILE as a prefix.
+$(call allow-override,CC,$(CROSS_COMPILE)gcc)
+$(call allow-override,AR,$(CROSS_COMPILE)ar)
+$(call allow-override,LD,$(CROSS_COMPILE)ld)
+
+LD += $(EXTRA_LDFLAGS)
+
+include $(srctree)/tools/scripts/Makefile.arch
+
+# Refer to README to learn how to support your architecture
+SUPPORTED_ARCHS = x86
+
+ifeq ($(filter $(ARCH),$(SUPPORTED_ARCHS)),)
+$(error Unsupported arch: $(ARCH))
+endif
+
+CFLAGS += -O2 -g
+CFLAGS += -std=gnu99 -Wall -Werror
+CFLAGS += -lpthread
+CFLAGS += -DCONFIG_KPROBES
+
+# We confine the includes used below to those we know are safe
+# for this type of hack.
+CFLAGS += -D__KERNEL__
+
+# CFLAGS += -DCONFIG_HAVE_ARCH_PS_CONST
+INCLUDES = \
+	   -I include/ \
+	   -I arch/$(ARCH)/include/ \
+	   -I ../include/ \
+	   -I ../arch/$(ARCH)/include/ \
+	   -I ../arch/$(ARCH)/include/generated/
+
+CFLAGS += $(INCLUDES)
+CFLAGS +=-Wl,-Tarch/$(ARCH)/kernel/vmlinux.lds
+
+HEADERS = \
+	  ../../include/asm-generic/section-core.h \
+	  ../../include/asm-generic/ranges.h \
+	  ../../include/asm-generic/tables.h \
+	  ../../include/linux/sections.h \
+	  ../../include/linux/ranges.h \
+	  ../../include/linux/tables.h
+
+__check_headers: $(HEADERS)
+	@$(foreach h, $(HEADERS), \
+		(test -f $(h) && ( \
+			(diff -B $(subst ../,../,$(h)) $(h) >/dev/null) \
+			|| echo "Warning: $(subst ../../,tools/,$(h)) differs from kernel" >&2 ) || true);)
+
+$(OUTPUT)arch/$(ARCH)/kernel/vmlinux.lds: arch/$(ARCH)/kernel/vmlinux.lds.S
+	$(NQ) '  LD  ' $@
+	$(Q)$(CC) $(CFLAGS) $(INCLUDES) -E -P \
+		-D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
+
+# Note, we use obj-y as a convenience factor, the cmd build
+# stuff doesn't allow this magic, it resolves our depds but
+# we still need to provide a series of targets for our objects.
+# We stick to the convenient shorthand we're used to in the
+# kernel. The final object resolution build stuff is handled
+# by tool_target_obj and its caller below. This also enables
+# OUTPUT=foo-path support so you can build externally.
+obj-y += \
+	arch/$(ARCH)/kernel/head64.o \
+	arch/$(ARCH)/mm/init.o \
+	kernel/locking/mutex.o \
+	kernel/locking/spinlock.o \
+	kernel/workqueue.o \
+	kernel/main.o \
+	pci.o \
+	lib/string.o \
+	pci-quirks.o \
+	drivers/acme.o \
+	drivers/synth/main.o \
+	drivers/synth/common.o \
+	drivers/synth/or.s \
+	main.o
+
+ifeq ($(ARCH),x86)
+obj-y += \
+	arch/$(ARCH)/kernel/alternative.o \
+	arch/$(ARCH)/kernel/init.o \
+	arch/$(ARCH)/kernel/kprobes.o \
+	arch/$(ARCH)/kernel/kasan.o \
+	arch/$(ARCH)/kernel/beta.o \
+	arch/$(ARCH)/kernel/alpha.o \
+	arch/$(ARCH)/xen/init.o	\
+	drivers/xen-driver.o
+endif
+
+obj-y-out = $(patsubst %,$(OUTPUT)%,$(obj-y))
+
+__build-dir = $(subst $(OUTPUT),,$(dir $1))
+build-dir   = $(if $(__build-dir),$(__build-dir),.)
+
+build := -f $(srctree)/tools/build/Makefile.build dir=$(build-dir)
+
+define tool_target_obj
+$(1): $(subst .s,.S,$(subst .o,.c,$(patsubst $(OUTPUT)%,%,$(1))))
+	$(Q)$(MAKE) $(build) obj=$(1)
+endef
+
+$(foreach tool_obj, $(obj-y-out), \
+	$(eval $(call tool_target_obj, $(tool_obj))))
+
+$(OUTPUT)demo: $(obj-y-out)
+	$(NQ) '  CC  ' $@
+	$(Q)$(CC) $(obj-y-out) -o $@ $(CPPFLAGS) $(CFLAGS)
+
+CHECK_HEADERS := __check_headers
+PHONY += $(CHECK_HEADERS)
+
+CMD_TARGETS = $(OUTPUT)arch/$(ARCH)/kernel/vmlinux.lds $(OUTPUT)demo
+TARGETS = $(CMD_TARGETS)
+
+all: $(CHECK_HEADERS) all_cmd
+
+all_cmd: $(CMD_TARGETS)
+
+ifeq ($(OUTPUT),)
+clean_dir = ./
+else
+clean_dir = $(OUTPUT)
+endif
+
+clean::
+	$(NQ)  '  CLEAN deps'
+	$(Q)find $(clean_dir) -name \*.o \
+		-o -name \*.s \
+		-o -name \*.o.d \
+		-o -name \*.o.cmd | xargs rm -f
+	$(NQ)  '  CLEAN targets'
+	$(Q)$(foreach f, $(CMD_TARGETS), rm -f $(f);)
diff --git a/tools/linker-tables/README b/tools/linker-tables/README
new file mode 100644
index 000000000000..729241f9e4c4
--- /dev/null
+++ b/tools/linker-tables/README
@@ -0,0 +1,114 @@
+Linux linker table userspace sandbox
+====================================
+
+This is a userspace sandbox to allow easy experimentation and
+test extensions with linker tables. It tries to mimic the Linux
+kernel development flow as much as possible, it however relies
+on and uses libc and is nothing but a simple stupid userspace
+application demo.
+
+You can use the sandbox to modify the kernel's linker table
+solution or add use it in creative ways without having to run
+qemu with a real kernel or user mode linux. You can simply try
+to extend this sandbox as you would for a regular userspace
+application.
+
+History
+=======
+
+This was hacked on first in an external repository, that tree has
+the full set of history of how this work came about. Refer to that
+tree for more details if you are interested in the logic used for
+a lot of decisions made for linker tables:
+
+https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linker-tables.git/
+
+This tree is discontinued now in favor of an upstream solution which
+is kept in sync with the kernel.
+
+Compile
+=======
+
+Run:
+	make
+
+Clean:
+	make clean
+
+If you need to get object files outside of the source tree:
+
+	make OUTPUT=/tmp/path/
+	make OUTPUT=/tmp/path/ clean
+
+Supported architectures
+=======================
+
+x86_64
+
+Currently only x86_64 is supported for the demo. It should be
+relatively easy to add more. To add a new architecture you need
+a toolchain available with libc. You then need to generate a
+respective base template custom linker script for userspace
+as is provided on x86 in arch/x86/kernel/vmlinux.lds.S.
+
+A respective architecture tools/arch/$(ARCH)/include/* file for
+each section-core.h, ranges.h, tables.h will need to be provided
+as well. If your architecture's file is generated copy the generated
+file over.
+
+x86 Simulated boots
+===================
+
+This programs simulates boot on both bare metal and with the
+Xen PV entry on x86.
+
+Emulate bare metal boot:
+
+./demo
+
+Emulate Xen boot (x86):
+
+./demo -x
+
+Testing new features
+====================
+
+A copy of each kernel header file is maintained in tools/include/,
+as well as a respective generated asm file for each sandbox supported
+architecture. This sandbox has a built in checker for when these files
+get out of sync.
+
+If testing new extensions on the files:
+
+  o section-core
+  o ranges.h
+  o tables.h
+
+You'll want to copy them into tools as well. If you are working on
+using these files you can work within the current directory's namespace,
+including its own set of header files, so tools/linker-tables/include/ and
+each respective tools/linker-tables/arch/$(ARCH)/include/asm/.
+
+Features evaluation
+===================
+
+This lists features currently being evaluated in the sandbox, not yet
+present upstream. These make use of the existing set of header files
+without modification.
+
+ o Demo use of initialization on for x86, refer to arch/x86/kernel/init.c
+
+ o Demo use of porting the kernel's init call levels to linker tables, refer
+   to the init_calls linker table use on kernel/main.c
+
+ o Demo use of an asm-generic architecture init family, which could potentially
+   be used to help share initialization sequences on simple architectures.
+   Refer to include/asm-generic/arch_init_fn.h
+
+ o Building synthetic routines with the option to provide enhancements
+   per architecture in asm, refer to drivers/synth/or.S and its use on
+   synth_init_or().
+
+ o User of linker tables for alternatives with consts - refer to
+   use of the ps_set_const_table linker table and its use in
+   arch/x86/kernel/alternative.c
diff --git a/tools/linker-tables/arch/x86/include/asm/asm.h b/tools/linker-tables/arch/x86/include/asm/asm.h
new file mode 100644
index 000000000000..155a52920dfb
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/asm.h
@@ -0,0 +1,17 @@
+#ifndef _ASM_X86_ASM_H
+
+#ifdef __ASSEMBLY__
+# define __ASM_FORM(x)	x
+# define __ASM_FORM_RAW(x)     x
+# define __ASM_FORM_COMMA(x) x,
+#else
+# define __ASM_FORM(x)	" " #x " "
+# define __ASM_FORM_RAW(x)     #x
+# define __ASM_FORM_COMMA(x) " " #x ","
+#endif
+
+# define __ASM_SEL(a,b) __ASM_FORM(b)
+# define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(b)
+#define _ASM_PTR	__ASM_SEL(.long, .quad)
+
+#endif /* _ASM_X86_ASM_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/boot.h b/tools/linker-tables/arch/x86/include/asm/boot.h
new file mode 100644
index 000000000000..af91b94ad5a6
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/boot.h
@@ -0,0 +1 @@
+extern struct boot_params boot_params;
diff --git a/tools/linker-tables/arch/x86/include/asm/bootparam.h b/tools/linker-tables/arch/x86/include/asm/bootparam.h
new file mode 100644
index 000000000000..a7ef34216f7f
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/bootparam.h
@@ -0,0 +1,32 @@
+#ifndef __BOOTPARAM_H
+#define __BOOTPARAM_H
+
+#include <linux/types.h>
+
+struct setup_header {
+	__u32 hardware_subarch;
+} __attribute__((packed));
+
+struct boot_params {
+	struct setup_header hdr;
+} __attribute__((packed));
+
+enum {
+	X86_SUBARCH_PC = 0,
+	X86_SUBARCH_LGUEST,
+	X86_SUBARCH_XEN,
+	X86_SUBARCH_INTEL_MID,
+	X86_SUBARCH_CE4100,
+	X86_NR_SUBARCHS,
+};
+
+#define X86_SUBARCH_ALL_SUBARCHS 	\
+	(				\
+	BIT(X86_SUBARCH_PC) |		\
+	BIT(X86_SUBARCH_LGUEST) |	\
+	BIT(X86_SUBARCH_XEN) |		\
+	BIT(X86_SUBARCH_INTEL_MID) |	\
+	BIT(X86_SUBARCH_CE4100)		\
+	)
+
+#endif /* __BOOTPARAM_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/kprobes.h b/tools/linker-tables/arch/x86/include/asm/kprobes.h
new file mode 100644
index 000000000000..f702fc359efe
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/kprobes.h
@@ -0,0 +1,7 @@
+#ifndef _SANDBOX_ASM_X86_KPROBES_H
+#define _SANDBOX_ASM_X86_KPROBES_H
+
+/* This is all we need for the demo */
+#include <asm-generic/kprobes.h>
+
+#endif /* _SANDBOX_ASM_X86_KPROBES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/ps_const.h b/tools/linker-tables/arch/x86/include/asm/ps_const.h
new file mode 100644
index 000000000000..b9901f35cfca
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/ps_const.h
@@ -0,0 +1,21 @@
+#ifndef __X86_PS_CONST
+#define __X86_PS_CONST
+
+#include <linux/tables.h>
+#include <asm/asm.h>
+
+#define ps_shr(_in, _func)						\
+({									\
+	__typeof__(_in) _out;						\
+	asm volatile(							\
+		"shr $0,%0\n"						\
+		"1:\n"							\
+		SECTION_TBL_STR(SECTION_INIT_DATA, ps_set_const_table, 01)\
+		_ASM_PTR "1b-1, %P2, %P3\n"				\
+		".popsection\n"						\
+		: "=rm" (_out)						\
+		: "0" (_in), "i" (SET_CONST_U8), "i" (_func));		\
+	(_out);								\
+})
+
+#endif /* __X86_PS_CONST */
diff --git a/tools/linker-tables/arch/x86/include/asm/ranges.h b/tools/linker-tables/arch/x86/include/asm/ranges.h
new file mode 100644
index 000000000000..823789d2b010
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/ranges.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_RANGES_H
+#define _ASM_X86_RANGES_H
+
+#include <asm-generic/ranges.h>
+
+#endif  /* _ASM_X86_RANGES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/section-core.h b/tools/linker-tables/arch/x86/include/asm/section-core.h
new file mode 100644
index 000000000000..06be2b1c424f
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/section-core.h
@@ -0,0 +1 @@
+#include <asm-generic/section-core.h>
diff --git a/tools/linker-tables/arch/x86/include/asm/setup.h b/tools/linker-tables/arch/x86/include/asm/setup.h
new file mode 100644
index 000000000000..366c36bd2910
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/setup.h
@@ -0,0 +1,6 @@
+#ifndef __LINUX_X86_USER_SETUP_H
+#define __LINUX_X86_USER_SETUP_H
+
+/* I'm lazy */
+
+#endif /* __LINUX_X86_USER_SETUP_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/tables.h b/tools/linker-tables/arch/x86/include/asm/tables.h
new file mode 100644
index 000000000000..797df3407ee1
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/tables.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_TABLES_H
+#define _ASM_X86_TABLES_H
+
+#include <asm-generic/tables.h>
+
+#endif  /* _ASM_X86_RANGES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/x86.h b/tools/linker-tables/arch/x86/include/asm/x86.h
new file mode 100644
index 000000000000..680c1141e0de
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/x86.h
@@ -0,0 +1,4 @@
+int startup_64(void);
+int x86_64_start_reservations(void);
+void setup_arch(void);
+void late_init(void);
diff --git a/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h b/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
new file mode 100644
index 000000000000..afece8ce6dd4
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
@@ -0,0 +1,169 @@
+#ifndef __X86_INIT_TABLES_H
+#define __X86_INIT_TABLES_H
+
+#include <linux/types.h>
+#include <linux/tables.h>
+
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <asm/bootparam.h>
+
+/**
+ * struct x86_init_fn - x86 generic kernel init call
+ *
+ * Linux x86 features vary in complexity, features may require work done at
+ * different levels of the full x86 init sequence. Today there are also two
+ * different possible entry points for Linux on x86, one for bare metal, KVM
+ * and Xen HVM, and another for Xen PV guests / dom0.  Assuming a bootloader
+ * has set up 64-bit mode, roughly the x86 init sequence follows this path:
+ *
+ * Bare metal, KVM, Xen HVM                      Xen PV / dom0
+ *       startup_64()                             startup_xen()
+ *              \                                     /
+ *      x86_64_start_kernel()                 xen_start_kernel()
+ *                           \               /
+ *                      x86_64_start_reservations()
+ *                                   |
+ *                              start_kernel()
+ *                              [   ...        ]
+ *                              [ setup_arch() ]
+ *                              [   ...        ]
+ *                                  init
+ *
+ * x86_64_start_kernel() and xen_start_kernel() are the respective first C code
+ * entry starting points. The different entry points exist to enable Xen to
+ * skip a lot of hardware setup already done and managed on behalf of the
+ * hypervisor, we refer to this as "paravirtualization yielding". The different
+ * levels of init calls on the x86 init sequence exist to account for these
+ * slight differences and requirements. These different entry points also share
+ * a common entry x86 specific path, x86_64_start_reservations().
+ *
+ * A generic x86 feature can have different initialization calls, one on each
+ * of the different main x86 init sequences, but must also address both entry
+ * points in order to work properly across the board on all supported x86
+ * subarchitectures. Since x86 features can also have dependencies on other
+ * setup code or features, x86 features can at times be subordinate to other
+ * x86 features, or conditions. struct x86_init_fn enables feature developers
+ * to annotate dependency relationships to ensure subsequent init calls only
+ * run once a subordinate's dependencies have run. When needed custom
+ * dependency requirements can also be spelled out through a custom dependency
+ * checker. In order to account for the dual entry point nature of x86-64 Linux
+ * for "paravirtualization yielding" and to make annotations for support for
+ * these explicit each struct x86_init_fn must specify supported
+ * subarchitectures. The earliest x86-64 code can read the subarchitecture
+ * though is after load_idt(), as such the earliest we can currently rely on
+ * subarchitecture for semantics and a common init sequences is on the shared
+ * common x86_64_start_reservations().  Each struct x86_init_fn is associated
+ * with a specific special link order number which has been careflly thought
+ * out by x86 maintainers. You should pick a link order level associated with
+ * the specific directory your code lies in, a respective macro is used to
+ * build association to a link oder with a routine, you should use one of the
+ * provided x86_init_*() macros. You should not use __x86_init() directly.
+ *
+ * x86_init_fn enables strong semantics and dependencies to be defined and
+ * implemented on the full x86 initialization sequence.
+ *
+ * @supp_hardware_subarch: must be set, it represents the bitmask of supported
+ *	subarchitectures.  We require each struct x86_init_fn to have this set
+ *	to require developer considerations for each supported x86
+ *	subarchitecture and to build strong annotations of different possible
+ *	run time states particularly in consideration for the two main
+ *	different entry points for x86 Linux, to account for paravirtualization
+ *	yielding.
+ *
+ *	The subarchitecture is read by the kernel at early boot from the
+ *	struct boot_params hardware_subarch. Support for the subarchitecture
+ *	exists as of x86 boot protocol 2.07. The bootloader would have set up
+ *	the respective hardware_subarch on the boot sector as per
+ *	Documentation/x86/boot.txt.
+ *
+ *	What x86 entry point is used is determined at run time by the
+ *	bootloader. Linux pv_ops was designed to help enable to build one Linux
+ *	binary to support bare metal and different hypervisors.  pv_ops setup
+ *	code however is limited in that all pv_ops setup code is run late in
+ *	the x86 init sequence, during setup_arch(). In fact cpu_has_hypervisor
+ *	only works after early_cpu_init() during setup_arch(). If an x86
+ *	feature requires an earlier determination of what hypervisor was used,
+ *	or if it needs to annotate only support for certain hypervisors, the
+ *	x86 hardware_subarch should be set by the bootloader and
+ *	@supp_hardware_subarch set by the x86 feature. Using hardware_subarch
+ *	enables x86 features to fill the semantic gap between the Linux x86
+ *	entry point used and what pv_ops has to offer through a hypervisor
+ *	agnostic mechanism.
+ *
+ *	Each supported subarchitecture is set using the respective
+ *	X86_SUBARCH_* as a bit in the bitmask. For instance if a feature
+ *	is supported on PC and Xen subarchitectures only you would set this
+ *	bitmask to:
+ *
+ *		BIT(X86_SUBARCH_PC) |
+ *		BIT(X86_SUBARCH_XEN);
+ *
+ * @early_init: required, routine which will run in x86_64_start_reservations()
+ *	after we ensure boot_params.hdr.hardware_subarch is accessible and
+ *	properly set. Memory is not yet available. This the earliest we can
+ *	currently define a common shared callback since all callbacks need to
+ *	check for boot_params.hdr.hardware_subarch and this becomes accessible
+ *	on x86-64 until after load_idt().
+ */
+struct x86_init_fn {
+	__u32 supp_hardware_subarch;
+	void (*early_init)(void);
+};
+
+DECLARE_LINKTABLE(struct x86_init_fn, x86_init_fns);
+
+/* Init order levels, we can start at 0000 but reserve 0000-0999 for now */
+
+/*
+ * X86_INIT_ORDER_EARLY - early kernel init code
+ *
+ * This consists of the first parts of the Linux kernel executed.
+ */
+#define X86_INIT_ORDER_EARLY	1000
+
+/* X86_INIT_ORDER_PLATFORM - platform kernel code
+ *
+ * Code the kernel needs to initialize under arch/x86/platform/
+ * early in boot.
+ */
+#define X86_INIT_ORDER_PLATFORM	3000
+
+#define __x86_init(__level,						\
+		   __supp_hardware_subarch,				\
+		   __early_init)					\
+	static LINKTABLE_INIT_DATA(x86_init_fns, __level)		\
+	__x86_init_fn_##__early_init = {				\
+		.supp_hardware_subarch = __supp_hardware_subarch,	\
+		.early_init = __early_init,				\
+	};
+
+#define x86_init_early(__supp_hardware_subarch,				\
+		       __early_init)					\
+	__x86_init(X86_INIT_ORDER_EARLY, __supp_hardware_subarch,	\
+		   __early_init);
+
+#define x86_init_platform(__supp_hardware_subarch,			\
+		       __early_init)					\
+	__x86_init(__name, X86_INIT_ORDER_PLATFORM, __supp_hardware_subarch,\
+		   __early_init);
+
+#define x86_init_early_all(__early_init)				\
+	x86_init_early(X86_SUBARCH_ALL_SUBARCHS,			\
+		       __early_init);
+
+#define x86_init_early_pc(__early_init)					\
+	x86_init_early(BIT(X86_SUBARCH_PC),				\
+		       __early_init);
+
+#define x86_init_early_xen(__early_init)				\
+	x86_init_early(BIT(X86_SUBARCH_XEN),				\
+		       __early_init);
+/**
+ * x86_init_fn_early_init: call all early_init() callbacks
+ *
+ * This calls all early_init() callbacks on the x86_init_fns linker table.
+ */
+void x86_init_fn_early_init(void);
+
+#endif /* __X86_INIT_TABLES_H */
diff --git a/tools/linker-tables/arch/x86/kernel/alpha.c b/tools/linker-tables/arch/x86/kernel/alpha.c
new file mode 100644
index 000000000000..0f9d45734c33
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/alpha.c
@@ -0,0 +1,9 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_alpha(void) {
+	pr_info("Initializing alpha ...\n");
+	pr_info("Completed initializing alpha !\n");
+}
+
+x86_init_early_pc(early_init_alpha);
diff --git a/tools/linker-tables/arch/x86/kernel/alternative.c b/tools/linker-tables/arch/x86/kernel/alternative.c
new file mode 100644
index 000000000000..ed80a822d726
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/alternative.c
@@ -0,0 +1,31 @@
+#include <asm/x86_init_fn.h>
+
+#include <linux/kernel.h>
+#include <linux/ps_const.h>
+
+void apply_alternatives_linker_tables(void)
+{
+	unsigned int num_consts = LINUX_SECTION_SIZE(ps_set_const_table);
+	struct ps_set_const *ps_const;
+
+	if (!num_consts)
+		return;
+
+	pr_debug("Number of init entries: %d\n", num_consts);
+
+	LINKTABLE_FOR_EACH(ps_const, ps_set_const_table) {
+		switch(ps_const->type) {
+		case SET_CONST_U8:
+			*ps_const->count = (__u8) ps_const->func();
+			break;
+		case SET_CONST_U16:
+			*ps_const->count = (__u16) ps_const->func();
+			break;
+		case SET_CONST_U32:
+			*ps_const->count = (__u16) ps_const->func();
+			break;
+		}
+	}
+}
+
+x86_init_early_pc(apply_alternatives_linker_tables);
diff --git a/tools/linker-tables/arch/x86/kernel/beta.c b/tools/linker-tables/arch/x86/kernel/beta.c
new file mode 100644
index 000000000000..2bdbf49d4731
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/beta.c
@@ -0,0 +1,9 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_beta(void) {
+	pr_info("Initializing beta ...\n");
+	pr_info("Completed initializing beta !\n");
+}
+
+x86_init_early_pc(early_init_beta);
diff --git a/tools/linker-tables/arch/x86/kernel/head64.c b/tools/linker-tables/arch/x86/kernel/head64.c
new file mode 100644
index 000000000000..d14dcdfd0ea9
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/head64.c
@@ -0,0 +1,58 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+
+#include <asm/x86_init_fn.h>
+#include <asm/boot.h>
+#include <asm/bootparam.h>
+
+#include <linux/start_kernel.h>
+#include <linux/kasan.h>
+
+void x86_64_start_reservations(void)
+{
+	switch (boot_params.hdr.hardware_subarch) {
+	case X86_SUBARCH_PC:
+		pr_info("Booting bare metal\n");
+		break;
+	case X86_SUBARCH_LGUEST:
+		pr_info("Booting lguest not supported\n");
+		BUG();
+	case X86_SUBARCH_XEN:
+		pr_info("Booting a Xen guest\n");
+		break;
+	case X86_SUBARCH_INTEL_MID:
+		pr_info("Booting Intel MID not supported\n");
+		BUG();
+	case X86_SUBARCH_CE4100:
+		pr_info("Booting Intel CE4100 not supported\n");
+		BUG();
+	default:
+		pr_info("Booting sunsupported x86 hardware subarch\n");
+		BUG();
+	}
+
+	start_kernel();
+}
+
+static void x86_64_start_kernel(void)
+{
+	x86_init_fn_early_init();
+
+	x86_64_start_reservations();
+}
+
+void startup_64(void)
+{
+	pr_info("Initializing x86 bare metal world\n");
+	x86_64_start_kernel();
+}
+
+void setup_arch(void)
+{
+	/* TODO: x86_init_fn_setup_arch(); */
+}
+
+void late_init(void)
+{
+	/* TODO: x86_init_fn_late_init(); */
+}
diff --git a/tools/linker-tables/arch/x86/kernel/init.c b/tools/linker-tables/arch/x86/kernel/init.c
new file mode 100644
index 000000000000..22702365ef51
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/init.c
@@ -0,0 +1,42 @@
+#define pr_fmt(fmt) "x86-init: " fmt
+
+#include <linux/bug.h>
+#include <linux/kernel.h>
+
+#include <asm/x86_init_fn.h>
+#include <asm/bootparam.h>
+#include <asm/boot.h>
+#include <asm/setup.h>
+
+DEFINE_LINKTABLE_INIT_DATA(struct x86_init_fn, x86_init_fns);
+
+static bool x86_init_fn_supports_subarch(struct x86_init_fn *fn)
+{
+	if (!fn->supp_hardware_subarch) {
+		//pr_err("Init sequence fails to declares any supported subarchs: %pF\n", fn->early_init);
+		WARN_ON(1);
+	}
+	if (BIT(boot_params.hdr.hardware_subarch) & fn->supp_hardware_subarch)
+		return true;
+	return false;
+}
+
+void __ref x86_init_fn_early_init(void)
+{
+	struct x86_init_fn *init_fn;
+	unsigned int num_inits = LINUX_SECTION_SIZE(x86_init_fns);
+
+	if (!num_inits)
+		return;
+
+	pr_debug("Number of init entries: %d\n", num_inits);
+
+	LINKTABLE_FOR_EACH(init_fn, x86_init_fns) {
+		if (!x86_init_fn_supports_subarch(init_fn))
+			continue;
+
+		//pr_debug("Running early init %pF ...\n", init_fn->early_init);
+		init_fn->early_init();
+		//pr_debug("Completed early init %pF\n", init_fn->early_init);
+	}
+}
diff --git a/tools/linker-tables/arch/x86/kernel/kasan.c b/tools/linker-tables/arch/x86/kernel/kasan.c
new file mode 100644
index 000000000000..c0120676eb9c
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/kasan.c
@@ -0,0 +1,10 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+void kasan_early_init(void) {
+	pr_info("Initializing kasan ...\n");
+	pr_info("Early init for Kasan...\n");
+	pr_info("Completed initializing kasan !\n");
+}
+
+x86_init_early_pc(kasan_early_init);
diff --git a/tools/linker-tables/arch/x86/kernel/kprobes.c b/tools/linker-tables/arch/x86/kernel/kprobes.c
new file mode 100644
index 000000000000..1d5a74bec754
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/kprobes.c
@@ -0,0 +1,51 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <linux/ranges.h>
+#include <linux/kprobes.h>
+
+DEFINE_SECTION_RANGE(kprobes, SECTION_TEXT);
+
+void __kprobes test_kprobe_0001(void)
+{
+	pr_info("test_kprobe\n");
+}
+
+void test_kprobe_0002(void)
+{
+	pr_info("test_kprobe\n");
+}
+
+void test_kprobe_addr(const char *test, unsigned long addr, bool should_match)
+{
+	if (SECTION_ADDR_IN_RANGE(kprobes, addr))
+		if (should_match)
+			pr_info("== OK: %s within range!\n", test);
+		else
+			pr_info("== FAIL: %s should not be in range...\n",
+				test);
+	else
+		if (should_match)
+			pr_info("== FAIL: %s should be in range...\n", test);
+		else
+			pr_info("== OK: %s not in range as expected!\n", test);
+}
+
+void early_init_kprobes(void)
+{
+	unsigned long addr;
+
+	pr_info("Initializing kprobes ...\n");
+
+	addr = (unsigned long) &test_kprobe_0001;
+
+	test_kprobe_addr("test_kprobe_0001", addr, true);
+
+	addr = (unsigned long) &test_kprobe_0002;
+
+	test_kprobe_addr("test_kprobe_0002", addr, false);
+
+	pr_info("Completed initializing kprobes !\n");
+}
+
+x86_init_early_all(early_init_kprobes);
diff --git a/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S b/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
new file mode 100644
index 000000000000..2ef049fc3bdb
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
@@ -0,0 +1,273 @@
+/* Script for -z combreloc: combine and sort reloc sections */
+/* Copyright (C) 2014 Free Software Foundation, Inc.
+   Copying and distribution of this script, with or without modification,
+   are permitted in any medium without royalty provided the copyright
+   notice and this notice are preserved.  */
+
+#include <asm/section-core.h>
+#include <asm/ranges.h>
+#include <asm/tables.h>
+
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
+	      "elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(_start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
+  .interp         : { *(.interp) }
+  .note.gnu.build-id : { *(.note.gnu.build-id) }
+  .hash           : { *(.hash) }
+  .gnu.hash       : { *(.gnu.hash) }
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+  .rela.dyn       :
+    {
+      *(.rela.init)
+      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+      *(.rela.fini)
+      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+      *(.rela.ctors)
+      *(.rela.dtors)
+      *(.rela.got)
+      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+      *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
+      *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
+      *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
+      *(.rela.ifunc)
+    }
+  .rela.plt       :
+    {
+      *(.rela.plt)
+      PROVIDE_HIDDEN (__rela_iplt_start = .);
+      *(.rela.iplt)
+      PROVIDE_HIDDEN (__rela_iplt_end = .);
+    }
+  .init           :
+  {
+    KEEP (*(SORT_NONE(.init)))
+  }
+  .plt            : { *(.plt) *(.iplt) }
+  .plt.bnd        : { *(.plt.bnd) }
+  SECTION_TEXT    :
+  {
+    *(.text.unlikely .text.*_unlikely .text.unlikely.*)
+    *(.text.exit .text.exit.*)
+    *(.text.startup .text.startup.*)
+    *(.text.hot .text.hot.*)
+    *(SORT(SECTION_RNG_ALL(SECTION_TEXT)))
+    *(SORT(SECTION_TBL_ALL(SECTION_TEXT)))
+
+    *(SORT(SECTION_RNG_ALL(SECTION_INIT)))
+    *(SORT(SECTION_TBL_ALL(SECTION_INIT)))
+
+    *(SORT(SECTION_RNG_ALL(SECTION_INIT_CALL)))
+    *(SORT(SECTION_TBL_ALL(SECTION_INIT_CALL)))
+
+    *(SORT(SECTION_RNG_ALL(SECTION_EXIT)))
+    *(SORT(SECTION_TBL_ALL(SECTION_EXIT)))
+
+    *(SORT(SECTION_RNG_ALL(SECTION_EXIT_CALL)))
+    *(SORT(SECTION_TBL_ALL(SECTION_EXIT_CALL)))
+    *(SECTION_TEXT .stub SECTION_ALL(SECTION_TEXT) .gnu.linkonce.t.*)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  }
+  .fini           :
+  {
+    KEEP (*(SORT_NONE(.fini)))
+  }
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+  .rodata         :
+  {
+	*(.rodata)
+	*(SORT(.rodata.*))
+
+	*(SORT(SECTION_RNG_ALL(SECTION_RODATA)))
+	*(SORT(SECTION_TBL_ALL(SECTION_RODATA)))
+
+	*(SORT(SECTION_RNG_ALL(SECTION_INIT_RODATA)))
+	*(SORT(SECTION_TBL_ALL(SECTION_INIT_RODATA)))
+
+	*(SORT(SECTION_RNG_ALL(SECTION_REF_RODATA)))
+	*(SORT(SECTION_TBL_ALL(SECTION_REF_RODATA)))
+	*(.gnu.linkonce.r.*)
+  }
+  .rodata1        : { *(.rodata1) }
+  .eh_frame_hdr : { *(.eh_frame_hdr) }
+  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table
+  .gcc_except_table.*) }
+  /* These sections are generated by the Sun/Oracle C++ compiler.  */
+  .exception_ranges   : ONLY_IF_RO { *(.exception_ranges
+  .exception_ranges*) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  */
+  . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+  /* Exception handling  */
+  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
+  .exception_ranges   : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
+  /* Thread Local Storage sections  */
+  .tdata	  : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+  .preinit_array     :
+  {
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP (*(.preinit_array))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+  }
+  .init_array     :
+  {
+    PROVIDE_HIDDEN (__init_array_start = .);
+    KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
+    KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
+    PROVIDE_HIDDEN (__init_array_end = .);
+  }
+  .fini_array     :
+  {
+    PROVIDE_HIDDEN (__fini_array_start = .);
+    KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
+    KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
+    PROVIDE_HIDDEN (__fini_array_end = .);
+  }
+  .ctors          :
+  {
+    /* gcc uses crtbegin.o to find the start of
+       the constructors, so we make sure it is
+       first.  Because this is a wildcard, it
+       doesn't matter if the user does not
+       actually link against crtbegin.o; the
+       linker won't look for a file to match a
+       wildcard.  The wildcard also means that it
+       doesn't matter which directory crtbegin.o
+       is in.  */
+    KEEP (*crtbegin.o(.ctors))
+    KEEP (*crtbegin?.o(.ctors))
+    /* We don't want to include the .ctor section from
+       the crtend.o file until after the sorted ctors.
+       The .ctor section from the crtend file contains the
+       end of ctors marker and it must be last */
+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+  .dtors          :
+  {
+    KEEP (*crtbegin.o(.dtors))
+    KEEP (*crtbegin?.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  .jcr            : { KEEP (*(.jcr)) }
+  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
+  .dynamic        : { *(.dynamic) }
+  .got            : { *(.got) *(.igot) }
+  . = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
+  .got.plt        : { *(.got.plt)  *(.igot.plt) }
+  .data           :
+  {
+    *(.data .data.* .gnu.linkonce.d.*)
+
+    *(SORT(SECTION_RNG_ALL(SECTION_DATA)))
+    *(SORT(SECTION_TBL_ALL(SECTION_DATA)))
+
+    *(SORT(SECTION_RNG_ALL(SECTION_INIT_DATA)))
+    *(SORT(SECTION_TBL_ALL(SECTION_INIT_DATA)))
+
+    *(SORT(SECTION_RNG_ALL(SECTION_REF_DATA)))
+    *(SORT(SECTION_TBL_ALL(SECTION_REF_DATA)))
+
+    *(SORT(SECTION_RNG_ALL(SECTION_EXIT_DATA)))
+    *(SORT(SECTION_TBL_ALL(SECTION_EXIT_DATA)))
+
+    SORT(CONSTRUCTORS)
+  }
+  .data1          : { *(.data1) }
+  _edata = .; PROVIDE (edata = .);
+  . = .;
+
+  __bss_start = .;
+  .bss            :
+  {
+   *(.dynbss)
+   *(.bss .bss.* .gnu.linkonce.b.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.
+      FIXME: Why do we need it? When there is no .bss section, we don't
+      pad the .data section.  */
+   . = ALIGN(. != 0 ? 64 / 8 : 1);
+  }
+  .lbss   :
+  {
+    *(.dynlbss)
+    *(.lbss .lbss.* .gnu.linkonce.lb.*)
+    *(LARGE_COMMON)
+  }
+  . = ALIGN(64 / 8);
+  . = SEGMENT_START("ldata-segment", .);
+  .lrodata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+  {
+    *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
+  }
+  .ldata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+  {
+    *(.ldata .ldata.* .gnu.linkonce.l.*)
+    . = ALIGN(. != 0 ? 64 / 8 : 1);
+  }
+  . = ALIGN(64 / 8);
+  _end = .; PROVIDE (end = .);
+  . = DATA_SEGMENT_END (.);
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line .debug_line.* .debug_line_end ) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  /* DWARF 3 */
+  .debug_pubtypes 0 : { *(.debug_pubtypes) }
+  .debug_ranges   0 : { *(.debug_ranges) }
+  /* DWARF Extension.  */
+  .debug_macro    0 : { *(.debug_macro) }
+  .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
+}
diff --git a/tools/linker-tables/arch/x86/mm/init.c b/tools/linker-tables/arch/x86/mm/init.c
new file mode 100644
index 000000000000..dbf1a85a4043
--- /dev/null
+++ b/tools/linker-tables/arch/x86/mm/init.c
@@ -0,0 +1,10 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_memory(void) {
+	pr_info("Initializing memory ...\n");
+	sleep(1);
+	pr_info("Completed initializing memory !\n");
+}
+
+x86_init_early_all(early_init_memory);
diff --git a/tools/linker-tables/arch/x86/xen/init.c b/tools/linker-tables/arch/x86/xen/init.c
new file mode 100644
index 000000000000..40ad493daee8
--- /dev/null
+++ b/tools/linker-tables/arch/x86/xen/init.c
@@ -0,0 +1,13 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <asm/x86.h>
+
+void startup_xen(void)
+{
+	pr_info("Initializing Xen guest\n");
+
+	x86_init_fn_early_init();
+
+	x86_64_start_reservations();
+}
diff --git a/tools/linker-tables/drivers/acme.c b/tools/linker-tables/drivers/acme.c
new file mode 100644
index 000000000000..dd321686dd49
--- /dev/null
+++ b/tools/linker-tables/drivers/acme.c
@@ -0,0 +1,32 @@
+#define pr_fmt(fmt) "ACME: " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/workqueue.h>
+
+void *acme_todo(void *arg);
+static DECLARE_WORK(acme_work, acme_todo);
+
+void *acme_todo(void *arg)
+{
+	pr_info("Running scheduled work\n");
+	pthread_exit(NULL);
+}
+
+static int acme_init_driver(void) {
+	pr_info("Initializing ...\n");
+	sleep(2);
+	pr_info("Finished init ... !\n");
+
+	init_work(&acme_work);
+	schedule_work(&acme_work);
+
+	return 0;
+}
+module_init(acme_init_driver);
+
+static void acme_exit(void)
+{
+	cancel_work_sync(&acme_work);
+};
+module_exit(acme_exit);
diff --git a/tools/linker-tables/drivers/synth/common.c b/tools/linker-tables/drivers/synth/common.c
new file mode 100644
index 000000000000..b44d9fcc7a9b
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/common.c
@@ -0,0 +1,16 @@
+int demo_or_1(int arg)
+{
+	switch (arg) {
+	case 1:
+		return 0xDEA00000;
+	case 2:
+		return 0X000D0000;
+	default:
+		return arg * 2;
+	}
+}
+
+int demo_or_2(void)
+{
+	return 0x0000BEEF;
+}
diff --git a/tools/linker-tables/drivers/synth/common.h b/tools/linker-tables/drivers/synth/common.h
new file mode 100644
index 000000000000..92827004f532
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/common.h
@@ -0,0 +1,2 @@
+int demo_or_1(int arg);
+int demo_or_2(void);
diff --git a/tools/linker-tables/drivers/synth/main.c b/tools/linker-tables/drivers/synth/main.c
new file mode 100644
index 000000000000..555cf97a5cbb
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/main.c
@@ -0,0 +1,35 @@
+#define pr_fmt(fmt) "Synthetics: " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ps_const.h>
+
+#include "common.h"
+#include "synth.h"
+
+DEFINE_LINKTABLE_INIT_DATA(struct ps_set_const, ps_set_const_table);
+
+unsigned int get_demo_shr(void)
+{
+	return 16;
+}
+
+static int synth_init(void)
+{
+	int synth_or;
+	int val = 2;
+	const unsigned int reg =  ps_shr(0xDEADBEEF, get_demo_shr);
+
+	synth_or = synth_init_or(val);
+	pr_info("synth_init_or(%d) returns: 0x%08X\n", val, synth_or);
+
+	pr_info("ps_shr(0x%08X, get_demo_shr) returns: 0x%08X\n", 0xDEADBEEF, reg);
+
+	return 0;
+}
+module_init(synth_init);
+
+static void synth_exit(void)
+{
+}
+module_exit(synth_exit);
diff --git a/tools/linker-tables/drivers/synth/or.S b/tools/linker-tables/drivers/synth/or.S
new file mode 100644
index 000000000000..983d913c8052
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/or.S
@@ -0,0 +1,39 @@
+#include <asm/ranges.h>
+
+	DEFINE_SECTION_RANGE(SECTION_TEXT, synth_init_or)
+
+	push_section_rng_level(SECTION_TEXT, synth_init_or, "01", )
+	/* err = 0; */
+	pushq %rbp
+	movq %rsp,%rbp
+	pushq %rbx
+	xorq %rbx,%rbx
+	.popsection
+
+	push_section_rng_level(SECTION_TEXT, synth_init_or, "99", )
+	/* return err; */
+	movq %rbx,%rax
+	popq %rbx
+	popq %rbp
+	retq
+	.popsection
+
+	push_section_rng_level(SECTION_TEXT, synth_init_or, "50", )
+	/* err |= demo_or_1(1); */
+	movl $1,%edi
+	call demo_or_1
+	orq %rax,%rbx
+	.popsection
+
+	push_section_rng_level(SECTION_TEXT, synth_init_or, "50", )
+	/* err |= demo_or_1(2); */
+	movl $2,%edi
+	call demo_or_1
+	orq %rax,%rbx
+	.popsection
+
+	push_section_rng_level(SECTION_TEXT, synth_init_or, "50", )
+	/* err |= demo_or_2(); */
+	call demo_or_2
+	orq %rax,%rbx
+	.popsection
diff --git a/tools/linker-tables/drivers/synth/synth.h b/tools/linker-tables/drivers/synth/synth.h
new file mode 100644
index 000000000000..abbb9afac374
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/synth.h
@@ -0,0 +1,2 @@
+/* Synthetic demos go here */
+int synth_init_or(int arg);
diff --git a/tools/linker-tables/drivers/xen-driver.c b/tools/linker-tables/drivers/xen-driver.c
new file mode 100644
index 000000000000..79d229f72818
--- /dev/null
+++ b/tools/linker-tables/drivers/xen-driver.c
@@ -0,0 +1,11 @@
+#include <asm/x86_init_fn.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <xen/xen.h>
+
+static void early_xen_init_driver(void) {
+	pr_info("Initializing xen driver\n");
+	sleep(2);
+}
+
+x86_init_early_xen(early_xen_init_driver);
diff --git a/tools/linker-tables/include/asm-generic/arch_init_fn.h b/tools/linker-tables/include/asm-generic/arch_init_fn.h
new file mode 100644
index 000000000000..61a04a50b453
--- /dev/null
+++ b/tools/linker-tables/include/asm-generic/arch_init_fn.h
@@ -0,0 +1,50 @@
+#ifndef __ARCH_INIT_TABLES_H
+#define __ARCH_INIT_TABLES_H
+
+#include <linux/types.h>
+#include <linux/tables.h>
+#include <linux/init.h>
+
+/**
+ * struct arch_init_fn - architecture-generic kernel init call
+ *
+ * Architectures must initialize a series of things prior to handing off
+ * control to the kernel. This structure can be used if the architecture is
+ * simple and it just needs a basic set of calls on its way up.
+ *
+ * @early_init: required, routine which will run in startup_64(). Memory is
+ * 	not yet available.
+ */
+struct arch_init_fn {
+	void (*early_init)(void);
+};
+
+DECLARE_LINKTABLE(struct arch_init_fn, arch_init_fns);
+
+/* Init order levels, we can start at 0000 but reserve 0000-0999 for now */
+
+/*
+ * ARCH_INIT_ORDER_EARLY - early kernel init code
+ *
+ * This consists of the first parts of the Linux kernel executed.
+ */
+#define ARCH_INIT_ORDER_EARLY	1000
+
+#define __arch_init(__level,						\
+		    __early_init)					\
+	static LINKTABLE_INIT_DATA(arch_init_fns, __level)		\
+	__arch_init_fn_##__early_init = {				\
+		.early_init = __early_init,				\
+	}
+
+#define arch_init_early(__early_init)					\
+	__arch_init(ARCH_INIT_ORDER_EARLY, __early_init)
+
+/**
+ * arch_init_fn_early_init: call all early_init() callbacks
+ *
+ * This calls all early_init() callbacks on the arch_init_fns linker table.
+ */
+void arch_init_fn_early_init(void);
+
+#endif /* __ARCH_INIT_TABLES_H */
diff --git a/tools/linker-tables/include/asm-generic/kprobes.h b/tools/linker-tables/include/asm-generic/kprobes.h
new file mode 100644
index 000000000000..d41d7e9b607d
--- /dev/null
+++ b/tools/linker-tables/include/asm-generic/kprobes.h
@@ -0,0 +1,26 @@
+#ifndef _SANDBOX_ASM_GENERIC_KPROBES_H
+#define _SANDBOX_ASM_GENERIC_KPROBES_H
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#ifdef CONFIG_KPROBES
+#include <linux/tables.h>
+#include <asm/ranges.h>
+/*
+ * Blacklist ganerating macro. Specify functions which is not probed
+ * by using this macro.
+ */
+# define __NOKPROBE_SYMBOL(fname)				\
+static LINKTABLE_INIT_DATA(_kprobe_blacklist, all)		\
+	_kbl_addr_##fname = (unsigned long)fname;
+# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
+/* Use this to forbid a kprobes attach on very low level functions */
+# define __kprobes	__LINUX_RANGE(SECTION_TEXT, kprobes)
+# define nokprobe_inline	__always_inline
+#else
+# define NOKPROBE_SYMBOL(fname)
+# define __kprobes
+# define nokprobe_inline	inline
+#endif
+#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
+
+#endif /* _SANDBOX_ASM_GENERIC_KPROBES_H */
diff --git a/tools/linker-tables/include/linux/bitops.h b/tools/linker-tables/include/linux/bitops.h
new file mode 100644
index 000000000000..2960e8089ebc
--- /dev/null
+++ b/tools/linker-tables/include/linux/bitops.h
@@ -0,0 +1,6 @@
+#ifndef _LINUX_BITOPS_H
+#define _LINUX_BITOPS_H
+
+#define BIT(nr)		(1UL << (nr))
+
+#endif /* _LINUX_BITOPS_H */
diff --git a/tools/linker-tables/include/linux/init.h b/tools/linker-tables/include/linux/init.h
new file mode 100644
index 000000000000..2eeca40fd97d
--- /dev/null
+++ b/tools/linker-tables/include/linux/init.h
@@ -0,0 +1,40 @@
+#ifndef _SANDBOX_LINUX_INIT_H
+#define _SANDBOX_LINUX_INIT_H
+
+#include_next <linux/init.h>
+#include <linux/types.h>
+#include <linux/sections.h>
+
+#define __init	__section(SECTION_INIT)
+#define __exit	__section(SECTION_EXIT)
+
+#ifndef __ASSEMBLY__
+#include <linux/tables.h>
+typedef int (*initcall_t)(void);
+typedef void (*exitcall_t)(void);
+
+DECLARE_LINKTABLE(initcall_t, init_calls);
+DECLARE_LINKTABLE(exitcall_t, exit_calls);
+
+#define __define_initcall(fn, id)					\
+	static LINKTABLE_INIT_DATA(init_calls, id)			\
+	__initcall_##fn##id = fn
+
+#define pure_initcall(fn)			__define_initcall(fn, 0)
+#define core_initcall(fn)			__define_initcall(fn, 1)
+#define postcore_initcall(fn)			__define_initcall(fn, 2)
+#define arch_initcall(fn)			__define_initcall(fn, 3)
+#define subsys_initcall(fn)			__define_initcall(fn, 4)
+#define fs_initcall(fn)				__define_initcall(fn, 5)
+#define device_initcall(fn)			__define_initcall(fn, 6)
+#define late_initcall(fn)			__define_initcall(fn, 7)
+
+#define __initcall(fn)				device_initcall(fn)
+
+#define __exitcall(fn)							\
+	static LINKTABLE_INIT_DATA(exit_calls, SECTION_ORDER_ANY)	\
+	__exitcall_##fn = fn;
+
+#endif
+
+#endif /* _SANDBOX_LINUX_INIT_H */
diff --git a/tools/linker-tables/include/linux/kasan.h b/tools/linker-tables/include/linux/kasan.h
new file mode 100644
index 000000000000..41791187854e
--- /dev/null
+++ b/tools/linker-tables/include/linux/kasan.h
@@ -0,0 +1,5 @@
+#include <linux/types.h>
+
+void kasan_early_init(void);
+int kasan_init(void);
+bool is_kasan_setup(void);
diff --git a/tools/linker-tables/include/linux/kprobes.h b/tools/linker-tables/include/linux/kprobes.h
new file mode 100644
index 000000000000..ecd5a0a69ae6
--- /dev/null
+++ b/tools/linker-tables/include/linux/kprobes.h
@@ -0,0 +1,11 @@
+#ifndef _SANDBOX_LINUX_KPROBES_H
+#define _SANDBOX_LINUX_KPROBES_H
+
+#include <asm/kprobes.h>
+#include <linux/ranges.h>
+
+#ifdef CONFIG_KPROBES
+DECLARE_SECTION_RANGE(kprobes);
+#endif
+
+#endif /* _SANDBOX_LINUX_KPROBES_H */
diff --git a/tools/linker-tables/include/linux/module.h b/tools/linker-tables/include/linux/module.h
new file mode 100644
index 000000000000..b59e55f3f04e
--- /dev/null
+++ b/tools/linker-tables/include/linux/module.h
@@ -0,0 +1,14 @@
+#ifndef _LINUX_MODULE_H
+#define _LINUX_MODULE_H
+
+#include <linux/init.h>
+
+#define module_init(x)  __initcall(x);
+#define module_exit(x)  __exitcall(x);
+
+struct module {
+	int (*init)(void);
+	void (*exit)(void);
+};
+
+#endif /* _LINUX_MODULE_H */
diff --git a/tools/linker-tables/include/linux/mutex.h b/tools/linker-tables/include/linux/mutex.h
new file mode 100644
index 000000000000..a74f951ceb42
--- /dev/null
+++ b/tools/linker-tables/include/linux/mutex.h
@@ -0,0 +1,17 @@
+#ifndef __LINUX_MUTEX_H
+#define __LINUX_MUTEX_H
+
+#include <sys/types.h>
+#include <linux/sched.h>
+#include <pthread.h>
+
+struct mutex {
+	pthread_mutex_t lock;
+};
+
+void mutex_init(struct mutex *lock);
+void mutex_destroy(struct mutex *lock);
+void mutex_lock(struct mutex *lock);
+void mutex_unlock(struct mutex *lock);
+
+#endif /* __LINUX_MUTEX_H */
diff --git a/tools/linker-tables/include/linux/pci.h b/tools/linker-tables/include/linux/pci.h
new file mode 100644
index 000000000000..8518c46631f7
--- /dev/null
+++ b/tools/linker-tables/include/linux/pci.h
@@ -0,0 +1,7 @@
+#include <linux/types.h>
+
+struct pci_fixup {
+	void (*hook)(void);
+};
+
+bool detect_pci(void);
diff --git a/tools/linker-tables/include/linux/ps_const.h b/tools/linker-tables/include/linux/ps_const.h
new file mode 100644
index 000000000000..5eab3a124e00
--- /dev/null
+++ b/tools/linker-tables/include/linux/ps_const.h
@@ -0,0 +1,46 @@
+#ifndef __PS_CONST
+#define __PS_CONST
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/tables.h>
+
+/* Helpers for partially static settings */
+
+enum ps_static_type {
+	SET_CONST_U8 = 0,
+	SET_CONST_U16,
+	SET_CONST_U32,
+};
+
+struct ps_set_const {
+	unsigned int *count;
+	enum ps_static_type type;
+	unsigned int (*func)(void);
+};
+
+DECLARE_LINKTABLE(struct ps_set_const, ps_set_const_table);
+
+#ifdef CONFIG_HAVE_ARCH_PS_CONST
+#include <asm/ps_const.h>
+#endif
+
+/*
+ * ps_ stands for "partially static", so we "partialloy static shift right"
+ * You can optimize this for your architecture.
+ *
+ * ps_shr(unsigned int in, unsigned char (*func)(void))
+ */
+#ifndef ps_shr
+#define ps_shr(_in, _func)						\
+({									\
+	static unsigned int _count;					\
+	static LINKTABLE_INIT_DATA(ps_set_const_table, 01)		\
+		__ps_shr##__func =					\
+		{ &_count, SET_CONST_U8, (_func) };			\
+									\
+	(_in) >> _count;						\
+})
+#endif /* ps_shr */
+
+#endif /* __PS_CONST */
diff --git a/tools/linker-tables/include/linux/sched.h b/tools/linker-tables/include/linux/sched.h
new file mode 100644
index 000000000000..63db7da0e8e4
--- /dev/null
+++ b/tools/linker-tables/include/linux/sched.h
@@ -0,0 +1,9 @@
+#ifndef _LINUX_SCHED_H
+#define _LINUX_SCHED_H
+
+#include <linux/ranges.h>
+
+DECLARE_SECTION_RANGE(sched_text);
+#define __sched		__LINUX_RANGE(SECTION_TEXT, sched_text)
+
+#endif /* _LINUX_SCHED_H */
diff --git a/tools/linker-tables/include/linux/spinlock.h b/tools/linker-tables/include/linux/spinlock.h
new file mode 100644
index 000000000000..e62bc3bc5e6a
--- /dev/null
+++ b/tools/linker-tables/include/linux/spinlock.h
@@ -0,0 +1,13 @@
+#ifndef __LINUX_SPINLOCK_H
+#define __LINUX_SPINLOCK_H
+
+#include <pthread.h>
+
+#define spinlock_t pthread_spinlock_t
+
+void spin_lock_init(spinlock_t *lock);
+void spin_lock_destroy(spinlock_t *lock);
+void spin_lock(spinlock_t *lock);
+void spin_unlock(spinlock_t *lock);
+
+#endif /* __LINUX_SPINLOCK_H */
diff --git a/tools/linker-tables/include/linux/start_kernel.h b/tools/linker-tables/include/linux/start_kernel.h
new file mode 100644
index 000000000000..5c2cb9a5cb0c
--- /dev/null
+++ b/tools/linker-tables/include/linux/start_kernel.h
@@ -0,0 +1 @@
+int start_kernel(void);
diff --git a/tools/linker-tables/include/linux/types.h b/tools/linker-tables/include/linux/types.h
new file mode 100644
index 000000000000..3fc87b2c84e2
--- /dev/null
+++ b/tools/linker-tables/include/linux/types.h
@@ -0,0 +1,13 @@
+#ifndef __LINUX_USER_TYPES_H
+#define __LINUX_USER_TYPES_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+typedef unsigned char __u8;
+typedef unsigned short __u16;
+typedef unsigned int __u32;
+
+#endif /* __LINUX_USER_TYPES_H */
diff --git a/tools/linker-tables/include/linux/workqueue.h b/tools/linker-tables/include/linux/workqueue.h
new file mode 100644
index 000000000000..69e1c6de5051
--- /dev/null
+++ b/tools/linker-tables/include/linux/workqueue.h
@@ -0,0 +1,51 @@
+#ifndef _LINUX_WORKQUEUE_H
+#define _LINUX_WORKQUEUE_H
+
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <pthread.h>
+
+struct work {
+	bool ready;
+
+	pthread_t thread;
+	struct mutex mutex;
+	pthread_cond_t cond;
+
+	void *arg;
+	void *(*work_cb)(void *arg);
+};
+
+#define DECLARE_WORK(_w, _w_cb) \
+struct work _w = { \
+	.work_cb = _w_cb, \
+	.arg = NULL, \
+};
+
+extern void *run_work(void *arg);
+
+static inline void init_work(struct work *w)
+{
+	w->ready = false;
+
+	mutex_init(&w->mutex);
+	pthread_cond_init(&w->cond, NULL);
+
+	pthread_create(&w->thread, NULL, run_work, (void *) w);
+
+	while (1) {
+		mutex_lock(&w->mutex);
+		if (w->ready) {
+			pthread_mutex_unlock(&w->mutex.lock);
+			break;
+		}
+		mutex_unlock(&w->mutex);
+	}
+}
+
+void schedule_work(struct work *w);
+void cancel_work_sync(struct work *w);
+void init_work(struct work *w);
+
+#endif /* _LINUX_WORKQUEUE_H */
diff --git a/tools/linker-tables/include/xen/xen.h b/tools/linker-tables/include/xen/xen.h
new file mode 100644
index 000000000000..782c799a0064
--- /dev/null
+++ b/tools/linker-tables/include/xen/xen.h
@@ -0,0 +1,4 @@
+#include <linux/types.h>
+
+bool booting_xen(void);
+int startup_xen(void);
diff --git a/tools/linker-tables/kernel/locking/mutex.c b/tools/linker-tables/kernel/locking/mutex.c
new file mode 100644
index 000000000000..131097fccd13
--- /dev/null
+++ b/tools/linker-tables/kernel/locking/mutex.c
@@ -0,0 +1,28 @@
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+
+DEFINE_SECTION_RANGE(sched_text, SECTION_TEXT);
+
+void __sched mutex_init(struct mutex *lock)
+{
+	int r;
+
+	r = pthread_mutex_init(&lock->lock, NULL);
+	if (r)
+		BUG_ON(r);
+}
+
+void __sched mutex_destroy(struct mutex *lock)
+{
+	pthread_mutex_destroy(&lock->lock);
+}
+
+void __sched mutex_lock(struct mutex *lock)
+{
+	pthread_mutex_lock(&lock->lock);
+}
+
+void __sched mutex_unlock(struct mutex *lock)
+{
+	pthread_mutex_unlock(&lock->lock);
+}
diff --git a/tools/linker-tables/kernel/locking/spinlock.c b/tools/linker-tables/kernel/locking/spinlock.c
new file mode 100644
index 000000000000..5be2bc7cdece
--- /dev/null
+++ b/tools/linker-tables/kernel/locking/spinlock.c
@@ -0,0 +1,26 @@
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+
+void spin_lock_init(spinlock_t *lock)
+{
+	int r;
+
+	r = pthread_spin_init(lock, PTHREAD_PROCESS_SHARED);
+	if (r)
+		BUG_ON(r);
+}
+
+void spin_lock_destroy(spinlock_t *lock)
+{
+	pthread_spin_destroy(lock);
+}
+
+void spin_lock(spinlock_t *lock)
+{
+	pthread_spin_lock(lock);
+}
+
+void spin_unlock(spinlock_t *lock)
+{
+	pthread_spin_unlock(lock);
+}
diff --git a/tools/linker-tables/kernel/main.c b/tools/linker-tables/kernel/main.c
new file mode 100644
index 000000000000..f3826cdb2ca8
--- /dev/null
+++ b/tools/linker-tables/kernel/main.c
@@ -0,0 +1,32 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/x86_init_fn.h>
+#include <asm/x86.h>
+
+DEFINE_LINKTABLE_INIT_DATA(initcall_t, init_calls);
+
+int do_one_initcall(initcall_t fn)
+{
+	int ret;
+
+	ret = fn();
+
+	return ret;
+}
+
+static void do_initcalls(void)
+{
+	initcall_t *fn;
+
+	 LINKTABLE_FOR_EACH(fn, init_calls)
+		 do_one_initcall(*fn);
+}
+
+void start_kernel(void)
+{
+	pr_info("Calling start_kernel()...\n");
+
+	setup_arch();
+	late_init();
+	do_initcalls();
+}
diff --git a/tools/linker-tables/kernel/workqueue.c b/tools/linker-tables/kernel/workqueue.c
new file mode 100644
index 000000000000..5ba73c7e7c8b
--- /dev/null
+++ b/tools/linker-tables/kernel/workqueue.c
@@ -0,0 +1,43 @@
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <linux/workqueue.h>
+#include <linux/kernel.h>
+
+void schedule_work(struct work *w)
+{
+	mutex_lock(&w->mutex);
+	pthread_cond_signal(&w->cond);
+	mutex_unlock(&w->mutex);
+}
+
+void cancel_work_sync(struct work *w)
+{
+	pthread_exit(NULL);
+}
+
+void *run_work(void *arg)
+{
+	struct work *w;
+	int r;
+
+	w = (struct work *) arg;
+
+	mutex_lock(&w->mutex);
+
+	while (true) {
+		if (!w->ready)
+			w->ready = true;
+		r = pthread_cond_wait(&w->cond, &w->mutex.lock);
+		if (r != 0) {
+			printf("(%s)\n", strerror(r));
+			BUG_ON(r);
+		}
+		w->work_cb(w->arg);
+	}
+
+	mutex_unlock(&w->mutex);
+
+	pthread_exit(NULL);
+}
diff --git a/tools/linker-tables/lib/string.c b/tools/linker-tables/lib/string.c
new file mode 100644
index 000000000000..95631c742f1d
--- /dev/null
+++ b/tools/linker-tables/lib/string.c
@@ -0,0 +1,26 @@
+/*
+ *  linux/lib/string.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  Licensed under GPLv2 - taken from linux-next next-20160803
+ */
+
+#include <linux/kernel.h>
+
+/**
+ * memset - Fill a region of memory with the given value
+ * @s: Pointer to the start of the area.
+ * @c: The byte to fill the area with
+ * @count: The size of the area.
+ *
+ * Do not use memset() to access IO space, use memset_io() instead.
+ */
+void *memset(void *s, int c, size_t count)
+{
+	char *xs = s;
+
+	while (count--)
+		*xs++ = c;
+	return s;
+}
diff --git a/tools/linker-tables/main.c b/tools/linker-tables/main.c
new file mode 100644
index 000000000000..c0b1f4c95112
--- /dev/null
+++ b/tools/linker-tables/main.c
@@ -0,0 +1,20 @@
+#include <linux/string.h>
+#include <xen/xen.h>
+#include <asm/x86.h>
+#include <asm/bootparam.h>
+
+struct boot_params boot_params __attribute__((aligned(16)));
+
+int main(int arg, char *argc[])
+{
+	memset(&boot_params, 0, sizeof(struct boot_params));
+
+	if (arg <= 1)
+		startup_64();
+	else {
+		boot_params.hdr.hardware_subarch = X86_SUBARCH_XEN;
+		startup_xen();
+	}
+
+	return 0;
+}
diff --git a/tools/linker-tables/pci-quirks.c b/tools/linker-tables/pci-quirks.c
new file mode 100644
index 000000000000..2cd1116dd0fc
--- /dev/null
+++ b/tools/linker-tables/pci-quirks.c
@@ -0,0 +1,13 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <linux/pci.h>
+
+DEFINE_LINKTABLE_RO(struct pci_fixup, pci_fixup_early);
+
+static void foo_fixup(void) {
+	pr_info("foo_fixup\n");
+};
+
+LINKTABLE_RO(pci_fixup_early, 50) quirk_foo = {
+	.hook = foo_fixup,
+};
diff --git a/tools/linker-tables/pci.c b/tools/linker-tables/pci.c
new file mode 100644
index 000000000000..d2a57701290d
--- /dev/null
+++ b/tools/linker-tables/pci.c
@@ -0,0 +1,29 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <asm/bootparam.h>
+#include <linux/pci.h>
+
+DECLARE_LINKTABLE(struct pci_fixup, pci_fixup_early);
+
+void early_init_pci(void) {
+
+	const struct pci_fixup *fixup;
+	unsigned int tbl_size = LINUX_SECTION_SIZE(pci_fixup_early);
+
+	pr_info("Initializing pci ...\n");
+
+	pr_info("PCI fixup size: %d\n", tbl_size);
+
+	sleep(1);
+	pr_info("Demo: Using LINKTABLE_FOR_EACH\n");
+	LINKTABLE_FOR_EACH(fixup, pci_fixup_early)
+		fixup->hook();
+
+	pr_info("Demo: Using LINKTABLE_RUN_ALL\n");
+	LINKTABLE_RUN_ALL(pci_fixup_early, hook,);
+
+	pr_info("Completed initializing pci !\n");
+}
+
+x86_init_early_all(early_init_pci);
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v1 7/7] tools: add userspace linker table sandbox
@ 2016-08-19 21:41       ` mcgrof
  0 siblings, 0 replies; 480+ messages in thread
From: mcgrof @ 2016-08-19 21:41 UTC (permalink / raw)
  To: acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

From: "Luis R. Rodriguez" <mcgrof@kernel.org>

Add a userspace sandbox to allow easy experimentation and
test extensions with linker tables, section ranges and the
new section core definitions.

The userspace sandbox tries to mimic the Linux kernel development
flow as much as possible, it however relies on and uses libc. Support
is currently only provided to x86_64.

v4: this patch is new in this series -- added to the kenrel as
    suggested by Boris, as otherwise it'd be really hard to keep
    an external userspace repository in sync.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/linker-tables.rst           |   4 +-
 MAINTAINERS                                        |   1 +
 include/linux/tables.h                             |   5 +-
 tools/Makefile                                     |   3 +-
 .../arch/x86/include/generated/asm/section-core.h  |   1 +
 tools/arch/x86/include/generated/ranges.h          |   1 +
 tools/arch/x86/include/generated/tables.h          |   1 +
 tools/include/asm-generic/ranges.h                 | 103 ++++
 tools/include/asm-generic/section-core.h           | 341 +++++++++++
 tools/include/asm-generic/tables.h                 |  50 ++
 tools/include/linux/ranges.h                       | 128 ++++
 tools/include/linux/sections.h                     | 111 ++++
 tools/include/linux/string.h                       |   1 +
 tools/include/linux/tables.h                       | 664 +++++++++++++++++++++
 tools/linker-tables/.gitignore                     |   2 +
 tools/linker-tables/Makefile                       | 184 ++++++
 tools/linker-tables/README                         | 114 ++++
 tools/linker-tables/arch/x86/include/asm/asm.h     |  17 +
 tools/linker-tables/arch/x86/include/asm/boot.h    |   1 +
 .../linker-tables/arch/x86/include/asm/bootparam.h |  32 +
 tools/linker-tables/arch/x86/include/asm/kprobes.h |   7 +
 .../linker-tables/arch/x86/include/asm/ps_const.h  |  21 +
 tools/linker-tables/arch/x86/include/asm/ranges.h  |   6 +
 .../arch/x86/include/asm/section-core.h            |   1 +
 tools/linker-tables/arch/x86/include/asm/setup.h   |   6 +
 tools/linker-tables/arch/x86/include/asm/tables.h  |   6 +
 tools/linker-tables/arch/x86/include/asm/x86.h     |   4 +
 .../arch/x86/include/asm/x86_init_fn.h             | 169 ++++++
 tools/linker-tables/arch/x86/kernel/alpha.c        |   9 +
 tools/linker-tables/arch/x86/kernel/alternative.c  |  31 +
 tools/linker-tables/arch/x86/kernel/beta.c         |   9 +
 tools/linker-tables/arch/x86/kernel/head64.c       |  58 ++
 tools/linker-tables/arch/x86/kernel/init.c         |  42 ++
 tools/linker-tables/arch/x86/kernel/kasan.c        |  10 +
 tools/linker-tables/arch/x86/kernel/kprobes.c      |  51 ++
 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S  | 273 +++++++++
 tools/linker-tables/arch/x86/mm/init.c             |  10 +
 tools/linker-tables/arch/x86/xen/init.c            |  13 +
 tools/linker-tables/drivers/acme.c                 |  32 +
 tools/linker-tables/drivers/synth/common.c         |  16 +
 tools/linker-tables/drivers/synth/common.h         |   2 +
 tools/linker-tables/drivers/synth/main.c           |  35 ++
 tools/linker-tables/drivers/synth/or.S             |  39 ++
 tools/linker-tables/drivers/synth/synth.h          |   2 +
 tools/linker-tables/drivers/xen-driver.c           |  11 +
 .../include/asm-generic/arch_init_fn.h             |  50 ++
 tools/linker-tables/include/asm-generic/kprobes.h  |  26 +
 tools/linker-tables/include/linux/bitops.h         |   6 +
 tools/linker-tables/include/linux/init.h           |  40 ++
 tools/linker-tables/include/linux/kasan.h          |   5 +
 tools/linker-tables/include/linux/kprobes.h        |  11 +
 tools/linker-tables/include/linux/module.h         |  14 +
 tools/linker-tables/include/linux/mutex.h          |  17 +
 tools/linker-tables/include/linux/pci.h            |   7 +
 tools/linker-tables/include/linux/ps_const.h       |  46 ++
 tools/linker-tables/include/linux/sched.h          |   9 +
 tools/linker-tables/include/linux/spinlock.h       |  13 +
 tools/linker-tables/include/linux/start_kernel.h   |   1 +
 tools/linker-tables/include/linux/types.h          |  13 +
 tools/linker-tables/include/linux/workqueue.h      |  51 ++
 tools/linker-tables/include/xen/xen.h              |   4 +
 tools/linker-tables/kernel/locking/mutex.c         |  28 +
 tools/linker-tables/kernel/locking/spinlock.c      |  26 +
 tools/linker-tables/kernel/main.c                  |  32 +
 tools/linker-tables/kernel/workqueue.c             |  43 ++
 tools/linker-tables/lib/string.c                   |  26 +
 tools/linker-tables/main.c                         |  20 +
 tools/linker-tables/pci-quirks.c                   |  13 +
 tools/linker-tables/pci.c                          |  29 +
 69 files changed, 3152 insertions(+), 5 deletions(-)
 create mode 100644 tools/arch/x86/include/generated/asm/section-core.h
 create mode 100644 tools/arch/x86/include/generated/ranges.h
 create mode 100644 tools/arch/x86/include/generated/tables.h
 create mode 100644 tools/include/asm-generic/ranges.h
 create mode 100644 tools/include/asm-generic/section-core.h
 create mode 100644 tools/include/asm-generic/tables.h
 create mode 100644 tools/include/linux/ranges.h
 create mode 100644 tools/include/linux/sections.h
 create mode 100644 tools/include/linux/tables.h
 create mode 100644 tools/linker-tables/.gitignore
 create mode 100644 tools/linker-tables/Makefile
 create mode 100644 tools/linker-tables/README
 create mode 100644 tools/linker-tables/arch/x86/include/asm/asm.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/boot.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/bootparam.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/kprobes.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ps_const.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ranges.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/section-core.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/setup.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/tables.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
 create mode 100644 tools/linker-tables/arch/x86/kernel/alpha.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/alternative.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/beta.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/head64.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/init.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kasan.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kprobes.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
 create mode 100644 tools/linker-tables/arch/x86/mm/init.c
 create mode 100644 tools/linker-tables/arch/x86/xen/init.c
 create mode 100644 tools/linker-tables/drivers/acme.c
 create mode 100644 tools/linker-tables/drivers/synth/common.c
 create mode 100644 tools/linker-tables/drivers/synth/common.h
 create mode 100644 tools/linker-tables/drivers/synth/main.c
 create mode 100644 tools/linker-tables/drivers/synth/or.S
 create mode 100644 tools/linker-tables/drivers/synth/synth.h
 create mode 100644 tools/linker-tables/drivers/xen-driver.c
 create mode 100644 tools/linker-tables/include/asm-generic/arch_init_fn.h
 create mode 100644 tools/linker-tables/include/asm-generic/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/bitops.h
 create mode 100644 tools/linker-tables/include/linux/init.h
 create mode 100644 tools/linker-tables/include/linux/kasan.h
 create mode 100644 tools/linker-tables/include/linux/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/module.h
 create mode 100644 tools/linker-tables/include/linux/mutex.h
 create mode 100644 tools/linker-tables/include/linux/pci.h
 create mode 100644 tools/linker-tables/include/linux/ps_const.h
 create mode 100644 tools/linker-tables/include/linux/sched.h
 create mode 100644 tools/linker-tables/include/linux/spinlock.h
 create mode 100644 tools/linker-tables/include/linux/start_kernel.h
 create mode 100644 tools/linker-tables/include/linux/types.h
 create mode 100644 tools/linker-tables/include/linux/workqueue.h
 create mode 100644 tools/linker-tables/include/xen/xen.h
 create mode 100644 tools/linker-tables/kernel/locking/mutex.c
 create mode 100644 tools/linker-tables/kernel/locking/spinlock.c
 create mode 100644 tools/linker-tables/kernel/main.c
 create mode 100644 tools/linker-tables/kernel/workqueue.c
 create mode 100644 tools/linker-tables/lib/string.c
 create mode 100644 tools/linker-tables/main.c
 create mode 100644 tools/linker-tables/pci-quirks.c
 create mode 100644 tools/linker-tables/pci.c

diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index e425c5cd36d6..1fec5b81df31 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -11,11 +11,11 @@ About Linker tables
 .. kernel-doc:: include/linux/tables.h
    :doc: Introduction
 
-Linker table provenance
+Linker table provenance and userspace testing
 ---------------------------------------------
 
 .. kernel-doc:: include/linux/tables.h
-   :doc: Linker table provenance
+   :doc: Linker table provenance and userspace testing
 
 Benefits of using Linker tables
 ===============diff --git a/MAINTAINERS b/MAINTAINERS
index e3569ed12c86..bd57f5e6e480 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5210,6 +5210,7 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux-next.git secti
 S:	Supported
 F:	include/asm-generic/tables.h
 F:	include/linux/tables.h
+F:	tools/linker-tables/
 F:	Documentation/sections/linker-tables.rst
 
 GENERIC PHY FRAMEWORK
diff --git a/include/linux/tables.h b/include/linux/tables.h
index bf8fae7f9246..77b7efb90bc8 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -35,12 +35,13 @@
  */
 
 /**
- * DOC: Linker table provenance
+ * DOC: Linker table provenance and userspace testing
  *
  * 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].
+ * userspace linker-table tree [1]. Linux has a similar userspace application
+ * in tools/linker-tables/ to help more easily test adding new extensions.
  *
  * Contrary to iPXE's solution which strives to force compilation of
  * everything using linker tables, Linux's solution allows for developers to be
diff --git a/tools/Makefile b/tools/Makefile
index daa8fb3e4363..731d1f5837cd 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -18,6 +18,7 @@ help:
 	@echo '  iio                    - IIO tools'
 	@echo '  kvm_stat               - top-like utility for displaying kvm statistics'
 	@echo '  lguest                 - a minimal 32-bit x86 hypervisor'
+	@echo '  linker-tables		- userspace liker table sandbox and related tools'
 	@echo '  net                    - misc networking tools'
 	@echo '  perf                   - Linux performance measurement and analysis tool'
 	@echo '  selftests              - various kernel selftests'
@@ -85,7 +86,7 @@ tmon: FORCE
 freefall: FORCE
 	$(call descend,laptop/$@)
 
-all: acpi cgroup cpupower gpio hv firewire lguest \
+all: acpi cgroup cpupower gpio hv firewire lguest linker-tables \
 		perf selftests turbostat usb \
 		virtio vm net x86_energy_perf_policy \
 		tmon freefall objtool
diff --git a/tools/arch/x86/include/generated/asm/section-core.h b/tools/arch/x86/include/generated/asm/section-core.h
new file mode 100644
index 000000000000..06be2b1c424f
--- /dev/null
+++ b/tools/arch/x86/include/generated/asm/section-core.h
@@ -0,0 +1 @@
+#include <asm-generic/section-core.h>
diff --git a/tools/arch/x86/include/generated/ranges.h b/tools/arch/x86/include/generated/ranges.h
new file mode 100644
index 000000000000..dac1a9a11367
--- /dev/null
+++ b/tools/arch/x86/include/generated/ranges.h
@@ -0,0 +1 @@
+#include <asm-generic/ranges.h>
diff --git a/tools/arch/x86/include/generated/tables.h b/tools/arch/x86/include/generated/tables.h
new file mode 100644
index 000000000000..d437818275c5
--- /dev/null
+++ b/tools/arch/x86/include/generated/tables.h
@@ -0,0 +1 @@
+#include <asm-generic/tables.h>
diff --git a/tools/include/asm-generic/ranges.h b/tools/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..8cf21a1497c6
--- /dev/null
+++ b/tools/include/asm-generic/ranges.h
@@ -0,0 +1,103 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#define SECTION_RNG(section, name)					\
+	SECTION_CORE(section, rng, name,				\
+		     SECTION_ORDER_ANY)
+
+#define SECTION_RNG_LEVEL(section, name, level)				\
+	SECTION_CORE(section, rng, name, level)
+
+#define SECTION_RNG_ALL(section)					\
+	SECTION_CORE_ALL(section,rng)
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  SECTION_ORDER_ANY, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       SECTION_ORDER_ANY, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   SECTION_ORDER_ANY, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(SECTION_RNG(section, name))))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using
+ * 	binutils SORT(), the number is sorted as a string, as such be
+ * 	sure to fill with zeroes any empty digits. For instance if you are
+ * 	using 3 levels of digits for order levels, use 001 for the first entry,
+ * 	0002 for the second, 999 for the last entry. You can use however many
+ * 	digits you need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(SECTION_RNG_LEVEL(section, name, level))))
+
+#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/tools/include/asm-generic/section-core.h b/tools/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..2ab57e2c4117
--- /dev/null
+++ b/tools/include/asm-generic/section-core.h
@@ -0,0 +1,341 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Custom linker script
+ *
+ * The Linux vmlinux binary uses a custom linker script on each architecture
+ * which it uses to strategically place standard ELF sections and also adds
+ * custom specialized ELF sections. Each architecture defines its own custom
+ * linker defined in arch/$(ARCH)/kernel/vmlinux.lds.S -- these in turn
+ * include and use definitions in include/asm-generic/vmlinux.lds.h as well
+ * as some helpers documented in this chaper.
+ */
+
+/**
+ * DOC: Standard ELF section use in Linux
+ *
+ * Linux makes use of the standard ELF sections, this sections documents
+ * these.
+ */
+
+/**
+ * DOC: SECTION_RODATA
+ *
+ * Macro name for code which must be protected from write access, read only
+ * data.
+ */
+#define SECTION_RODATA			.rodata
+
+/**
+ * DOC: SECTION_TEXT
+ *
+ * Macro name used to annotate code (functions) used during regular
+ * kernel run time. This is combined with `SECTION_RODATA`, only this
+ * section also allows for execution.
+ *
+ */
+#define SECTION_TEXT			.text
+
+/**
+ * DOC: SECTION_DATA
+ *
+ * Macro name for read-write data.
+ */
+#define SECTION_DATA			.data
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: SECTION_INIT
+ *
+ * Macro name used to annotate code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+#define SECTION_INIT			.init.text
+
+/**
+ * DOC: SECTION_INIT_DATA
+ *
+ * Macro name used to annotate data structures used only during boot or driver
+ * initialization.
+ */
+#define SECTION_INIT_DATA		.init.data
+
+/**
+ * DOC: SECTION_INIT_RODATA
+ *
+ * Macro name used to annotate read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+#define SECTION_INIT_RODATA		.init.rodata
+
+/**
+ * DOC: SECTION_INIT_CALL
+ *
+ * Special macro name used to annotate subsystem init call. These calls are
+ * are now grouped by functionality into separate subsections. Ordering inside
+ * the subsections is determined by link order.
+ */
+#define SECTION_INIT_CALL		.initcall
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: SECTION_EXIT
+ *
+ * Macro name used to annotate code (functions) used only during module
+ * unload.
+ */
+#define SECTION_EXIT			.exit.text
+
+/**
+ * DOC: SECTION_EXIT_DATA
+ *
+ * Macro name used to annotate data structures used only during module
+ * unload.
+ */
+#define SECTION_EXIT_DATA		.exit.data
+
+/**
+ * DOC: SECTION_EXIT_CALL
+ *
+ * Special macro name used to annotate an exit exit routine, order
+ * is important and maintained by link order.
+ */
+#define SECTION_EXIT_CALL		.exitcall.exit
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: SECTION_REF
+ *
+ * Macro name used to annotate that code (functions) declared with this section
+ * has been vetteed as valid for its reference or use of other code (functions)
+ * or data structures which are part of the init sections.
+ */
+#define SECTION_REF			.ref.text
+
+/**
+ * DOC: SECTION_REF_DATA
+ *
+ * Macro name used to annotate data structures declared with this section have
+ * been vetteed for its reference or use of other code (functions) or data
+ * structures part of the init sections.
+ */
+#define SECTION_REF_DATA		.ref.data
+
+/**
+ * DOC: SECTION_REF_RODATA
+ *
+ * Macro name used to annotate const code (functions) const data structures
+ * which has been vetteed for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+#define SECTION_REF_RODATA		.ref.rodata
+
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections. Linux has used 'SORT()' in ``include/asm-generic/vmlinux.lds.h``
+ * for years.
+ */
+
+/**
+ * DOC: SECTION_ORDER_ANY
+ *
+ * Macro name which can be used as helper to annotate custom section
+ * ordering at link time is not relevant for specific sections.
+ */
+#define SECTION_ORDER_ANY	any
+
+/*
+ * These section _ALL() helpers are for use on linker scripts and helpers
+ */
+#define SECTION_ALL(__section)						\
+	__section##.*
+
+#define __SECTION_CORE(__section, __core, __name, __level)		\
+	__section.__core.__name.__level
+
+#define SECTION_CORE_ALL(__section, __core)				\
+	__section##.##__core##.*
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section.___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section.___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section.__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifdef LINKER_SCRIPT
+
+#  ifndef SECTION_CORE
+#   define SECTION_CORE(__section, __core, __name, __level)		\
+	__SECTION_CORE(__section,__core,__name,__level)
+#  endif
+
+# else
+
+#  ifndef SECTION_CORE
+#   define SECTION_CORE(__section, __core, __name, __level)		\
+	push_section_core(__section, __core, __name, __level,)
+#  endif
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+# ifndef SECTION_CORE
+#  define SECTION_CORE(__section, __core, __name, __level)		\
+	__stringify(__SECTION_CORE(__section,__core,__name,__level))
+# endif
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align\x16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/tools/include/asm-generic/tables.h b/tools/include/asm-generic/tables.h
new file mode 100644
index 000000000000..43cd03a83bd2
--- /dev/null
+++ b/tools/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@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_ */
diff --git a/tools/include/linux/ranges.h b/tools/include/linux/ranges.h
new file mode 100644
index 000000000000..30b2182bd484
--- /dev/null
+++ b/tools/include/linux/ranges.h
@@ -0,0 +1,128 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(VMLINUX_SYMBOL(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+			     section(SECTION_RNG_LEVEL(__section, name,))))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(VMLINUX_SYMBOL(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
+			     section(SECTION_RNG_LEVEL(__section, name, ~))))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) VMLINUX_SYMBOL(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) VMLINUX_SYMBOL(name##__end)[0] = {}
+
+/**
+ * SECTION_ADDR_IN_RANGE - returns true if address is in range
+ *
+ * @name: section range name
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_ADDR_IN_RANGE(name, addr)				\
+	 (addr >= (unsigned long) LINUX_SECTION_START(name) &&		\
+	  addr <  (unsigned long) LINUX_SECTION_END(name))
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
diff --git a/tools/include/linux/sections.h b/tools/include/linux/sections.h
new file mode 100644
index 000000000000..f21c6ee88ded
--- /dev/null
+++ b/tools/include/linux/sections.h
@@ -0,0 +1,111 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_SIZE - get number of entries in the section
+ *
+ * @name: section name
+ *
+ * This gives you the number of entries in the section.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINUX_SECTION_SIZE(frobnicator_fns);
+ */
+#define LINUX_SECTION_SIZE(name)					\
+	((VMLINUX_SYMBOL(name##__end)) - (VMLINUX_SYMBOL(name)))
+
+/**
+ * LINUX_SECTION_EMPTY - check if section has no entries
+ *
+ * @name: section name
+ *
+ * Returns true if section is emtpy.
+ *
+ *   bool is_empty = LINUX_SECTION_EMPTY(frobnicator_fns);
+ */
+#define LINUX_SECTION_EMPTY(name)	(LINUX_SECTION_SIZE(name) = 0)
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_TYPE(section, type, name, level)			\
+	#section "." #type "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
diff --git a/tools/include/linux/string.h b/tools/include/linux/string.h
index f436d2420a18..a6b12564bbd9 100644
--- a/tools/include/linux/string.h
+++ b/tools/include/linux/string.h
@@ -3,6 +3,7 @@
 
 
 #include <linux/types.h>	/* for size_t */
+#include <string.h>
 
 void *memdup(const void *src, size_t len);
 
diff --git a/tools/include/linux/tables.h b/tools/include/linux/tables.h
new file mode 100644
index 000000000000..deb951b4ae37
--- /dev/null
+++ b/tools/include/linux/tables.h
@@ -0,0 +1,664 @@
+#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 and userspace testing
+ *
+ * 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]. Linux has a similar userspace application
+ * in tools/linker-tables/ to help more easily test adding new extensions.
+ *
+ * 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: The code bit-rot problem
+ *
+ * Overuse of C #ifdefs can be problematic for certain types of code.  Linux
+ * provides a rich array of features, but all these features take up valuable
+ * space in a kernel image. The traditional solution to this problem has been
+ * for each feature to have its own Kconfig entry and for the respective code
+ * to be wrapped around #ifdefs, allowing the feature to be compiled in only
+ * if enabled in Kconfig.
+ *
+ * The problem with this is that over time it becomes very difficult and time
+ * consuming to compile, let alone test all possible Kconfig configurations.
+ * Code that is not typically used tends to suffer from bit-rot over time. It
+ * can become difficult to predict which combinations of compile-time options
+ * will result in code that can compile and link correctly.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem when desirable
+ *
+ * Linker tables can be used as one way to help solve the code bit-rot problem,
+ * and in turn diminish Kconfig complexity.  To use linker tables and to
+ * optionally take advantage of avoiding code bit-rot, feature code should be
+ * implemented in separate C files, and should be designed to always be
+ * compiled -- they should not be guarded with C code ``#ifdef CONFIG_FOO``
+ * statements, consideration must also be taken for sub-features which depend
+ * on the main ``CONFIG_FOO`` option, as they will be disabled if they depend
+ * on ``CONFIG_FOO`` and therefore not compiled.
+ *
+ * To take advantage of this feature enable ``CONFIG_BUILD_AVOID_BITROT``, and
+ * use special targets for your code. Either ``force-obj-y`` or ``force-lib-y``
+ * can be used for your code instead of ``obj-y`` and ``lib-y``, respectively.
+ * Without ``CONFIG_BUILD_AVOID_BITROT`` enabled these targets will work just
+ * as their respective ``obj-y`` and ``lib-y`` counters work.  When
+ * ``CONFIG_BUILD_AVOID_BITROT`` is enabled the code with the special targets
+ * will always compile, even if the respective Kconfig entry for the code in
+ * question has been disabled, this code however will only be linked in to the
+ * final kernel image if the Kconfig entry for the code was enabled.
+ *
+ * Currently only built-in features are supported, modular support is not
+ * yet supported, however you can make use of sub-features for modules
+ * if they are independent and can simply be linked into modules.
+ *
+ * Care should be taken to vet that the code using this feature may also work
+ * without ``CONFIG_BUILD_AVOID_BITROT``, otherwise it must depend on
+ * CONFIG_BUILD_AVOID_BITROT.
+ */
+
+/**
+ * DOC: Using target force-obj-y and force-lib-y
+ *
+ * Let's assume we want to always force compilation of feature ``FOO`` in the
+ * kernel but avoid linking it. When you enable the ``FOO`` feature via Kconfig
+ * you'd end up with::
+ *
+ *	#define CONFIG_FOO 1
+ *
+ * You typically would then just use this in your Makefile to selectively
+ * compile and link the feature::
+ *
+ *	obj-$(CONFIG_FOO) += foo.o
+ *
+ * You could instead optionally use the new linker table target object::
+ *
+ *	force-obj-$(CONFIG_FOO) += foo.o
+ *
+ * Alternatively, this would be the equivalent of listing::
+ *
+ *	extra += foo.o
+ *	obj-$(CONFIG_FOO) += foo.o
+ *
+ * Both are mechanisms which can be used to take advantage of forcing
+ * compilation with linker tables, however making use of::
+ *
+ *	force-obj-$(CONFIG_FOO)
+ *
+ * is encouraged as it helps with annotating linker tables clearly where
+ * compilation is forced. The ``force-lib-y`` target is the equivalent for
+ * ``lib-y`` targets.
+ */
+
+/**
+ * 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: Opting out of forcing compilation
+ *
+ * If you want to opt-out of forcing compilation simply disable
+ * ``CONFIG_BUILD_AVOID_BITROT``.  Alternatively if your kernel configuration
+ * has it and you must have it enabled and you want to opt-out of forcing
+ * compilation you would use the typical ``obj-$(CONFIG_FOO) += foo.o`` and
+ * ``foo.o`` will only be compiled and linked in when ``CONFIG_FOO`` enabled.
+ * Using both ``force-obj-$(CONFIG_FOO)`` and ``obj-($CONFIG_FOO)`` will result
+ * with the feature on your binary only if you've enabled ``CONFIG_FOO``,
+ * however using ``force-obj-$(CONFIG_FOO)`` will always force compilation if
+ * ``CONFIG_BUILD_AVOID_BITROT`` has been enabled.
+ */
+
+/**
+ * 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/tools/linker-tables/.gitignore b/tools/linker-tables/.gitignore
new file mode 100644
index 000000000000..8275b0c55385
--- /dev/null
+++ b/tools/linker-tables/.gitignore
@@ -0,0 +1,2 @@
+arch/x86/kernel/vmlinux.lds
+demo
diff --git a/tools/linker-tables/Makefile b/tools/linker-tables/Makefile
new file mode 100644
index 000000000000..9d4e6fb0d176
--- /dev/null
+++ b/tools/linker-tables/Makefile
@@ -0,0 +1,184 @@
+include ../scripts/Makefile.include
+
+all:
+
+include ../scripts/utilities.mak
+
+MAKEFLAGS += --no-print-directory
+
+unexport LC_ALL
+LC_COLLATE=C
+LC_NUMERIC=C
+export LC_COLLATE LC_NUMERIC
+
+ifeq ($(srctree),)
+	srctree := $(patsubst %/,%,$(dir $(shell pwd)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Determined 'srctree' to be $(srctree))
+endif
+
+ifneq ($(objtree),)
+#$(info Determined 'objtree' to be $(objtree))
+endif
+
+ifneq ($(OUTPUT),)
+#$(info Determined 'OUTPUT' to be $(OUTPUT))
+# Adding $(OUTPUT) as a directory to look for source files,
+# because use generated output files as sources dependency
+# for flex/bison parsers.
+VPATH += $(OUTPUT)
+export VPATH
+endif
+
+export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK
+include $(srctree)/tools/build/Makefile.include
+
+ifeq ($(V),1)
+	Q+	NQ=@true
+else
+	Q=@
+	NQ=@echo
+endif
+
+MAKEFLAGS += -r
+
+define allow-override
+  $(if $(or $(findstring environment,$(origin $(1))),\
+            $(findstring command line,$(origin $(1)))),,\
+    $(eval $(1) = $(2)))
+endef
+
+# Allow setting CC and AR and LD, or setting CROSS_COMPILE as a prefix.
+$(call allow-override,CC,$(CROSS_COMPILE)gcc)
+$(call allow-override,AR,$(CROSS_COMPILE)ar)
+$(call allow-override,LD,$(CROSS_COMPILE)ld)
+
+LD += $(EXTRA_LDFLAGS)
+
+include $(srctree)/tools/scripts/Makefile.arch
+
+# Refer to README to learn how to support your architecture
+SUPPORTED_ARCHS = x86
+
+ifeq ($(filter $(ARCH),$(SUPPORTED_ARCHS)),)
+$(error Unsupported arch: $(ARCH))
+endif
+
+CFLAGS += -O2 -g
+CFLAGS += -std=gnu99 -Wall -Werror
+CFLAGS += -lpthread
+CFLAGS += -DCONFIG_KPROBES
+
+# We confine the includes used below to those we know are safe
+# for this type of hack.
+CFLAGS += -D__KERNEL__
+
+# CFLAGS += -DCONFIG_HAVE_ARCH_PS_CONST
+INCLUDES = \
+	   -I include/ \
+	   -I arch/$(ARCH)/include/ \
+	   -I ../include/ \
+	   -I ../arch/$(ARCH)/include/ \
+	   -I ../arch/$(ARCH)/include/generated/
+
+CFLAGS += $(INCLUDES)
+CFLAGS +=-Wl,-Tarch/$(ARCH)/kernel/vmlinux.lds
+
+HEADERS = \
+	  ../../include/asm-generic/section-core.h \
+	  ../../include/asm-generic/ranges.h \
+	  ../../include/asm-generic/tables.h \
+	  ../../include/linux/sections.h \
+	  ../../include/linux/ranges.h \
+	  ../../include/linux/tables.h
+
+__check_headers: $(HEADERS)
+	@$(foreach h, $(HEADERS), \
+		(test -f $(h) && ( \
+			(diff -B $(subst ../,../,$(h)) $(h) >/dev/null) \
+			|| echo "Warning: $(subst ../../,tools/,$(h)) differs from kernel" >&2 ) || true);)
+
+$(OUTPUT)arch/$(ARCH)/kernel/vmlinux.lds: arch/$(ARCH)/kernel/vmlinux.lds.S
+	$(NQ) '  LD  ' $@
+	$(Q)$(CC) $(CFLAGS) $(INCLUDES) -E -P \
+		-D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
+
+# Note, we use obj-y as a convenience factor, the cmd build
+# stuff doesn't allow this magic, it resolves our depds but
+# we still need to provide a series of targets for our objects.
+# We stick to the convenient shorthand we're used to in the
+# kernel. The final object resolution build stuff is handled
+# by tool_target_obj and its caller below. This also enables
+# OUTPUT=foo-path support so you can build externally.
+obj-y += \
+	arch/$(ARCH)/kernel/head64.o \
+	arch/$(ARCH)/mm/init.o \
+	kernel/locking/mutex.o \
+	kernel/locking/spinlock.o \
+	kernel/workqueue.o \
+	kernel/main.o \
+	pci.o \
+	lib/string.o \
+	pci-quirks.o \
+	drivers/acme.o \
+	drivers/synth/main.o \
+	drivers/synth/common.o \
+	drivers/synth/or.s \
+	main.o
+
+ifeq ($(ARCH),x86)
+obj-y += \
+	arch/$(ARCH)/kernel/alternative.o \
+	arch/$(ARCH)/kernel/init.o \
+	arch/$(ARCH)/kernel/kprobes.o \
+	arch/$(ARCH)/kernel/kasan.o \
+	arch/$(ARCH)/kernel/beta.o \
+	arch/$(ARCH)/kernel/alpha.o \
+	arch/$(ARCH)/xen/init.o	\
+	drivers/xen-driver.o
+endif
+
+obj-y-out = $(patsubst %,$(OUTPUT)%,$(obj-y))
+
+__build-dir = $(subst $(OUTPUT),,$(dir $1))
+build-dir   = $(if $(__build-dir),$(__build-dir),.)
+
+build := -f $(srctree)/tools/build/Makefile.build dir=$(build-dir)
+
+define tool_target_obj
+$(1): $(subst .s,.S,$(subst .o,.c,$(patsubst $(OUTPUT)%,%,$(1))))
+	$(Q)$(MAKE) $(build) obj=$(1)
+endef
+
+$(foreach tool_obj, $(obj-y-out), \
+	$(eval $(call tool_target_obj, $(tool_obj))))
+
+$(OUTPUT)demo: $(obj-y-out)
+	$(NQ) '  CC  ' $@
+	$(Q)$(CC) $(obj-y-out) -o $@ $(CPPFLAGS) $(CFLAGS)
+
+CHECK_HEADERS := __check_headers
+PHONY += $(CHECK_HEADERS)
+
+CMD_TARGETS = $(OUTPUT)arch/$(ARCH)/kernel/vmlinux.lds $(OUTPUT)demo
+TARGETS = $(CMD_TARGETS)
+
+all: $(CHECK_HEADERS) all_cmd
+
+all_cmd: $(CMD_TARGETS)
+
+ifeq ($(OUTPUT),)
+clean_dir = ./
+else
+clean_dir = $(OUTPUT)
+endif
+
+clean::
+	$(NQ)  '  CLEAN deps'
+	$(Q)find $(clean_dir) -name \*.o \
+		-o -name \*.s \
+		-o -name \*.o.d \
+		-o -name \*.o.cmd | xargs rm -f
+	$(NQ)  '  CLEAN targets'
+	$(Q)$(foreach f, $(CMD_TARGETS), rm -f $(f);)
diff --git a/tools/linker-tables/README b/tools/linker-tables/README
new file mode 100644
index 000000000000..729241f9e4c4
--- /dev/null
+++ b/tools/linker-tables/README
@@ -0,0 +1,114 @@
+Linux linker table userspace sandbox
+==================
+
+This is a userspace sandbox to allow easy experimentation and
+test extensions with linker tables. It tries to mimic the Linux
+kernel development flow as much as possible, it however relies
+on and uses libc and is nothing but a simple stupid userspace
+application demo.
+
+You can use the sandbox to modify the kernel's linker table
+solution or add use it in creative ways without having to run
+qemu with a real kernel or user mode linux. You can simply try
+to extend this sandbox as you would for a regular userspace
+application.
+
+History
+===+
+This was hacked on first in an external repository, that tree has
+the full set of history of how this work came about. Refer to that
+tree for more details if you are interested in the logic used for
+a lot of decisions made for linker tables:
+
+https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linker-tables.git/
+
+This tree is discontinued now in favor of an upstream solution which
+is kept in sync with the kernel.
+
+Compile
+===+
+Run:
+	make
+
+Clean:
+	make clean
+
+If you need to get object files outside of the source tree:
+
+	make OUTPUT=/tmp/path/
+	make OUTPUT=/tmp/path/ clean
+
+Supported architectures
+===========+
+x86_64
+
+Currently only x86_64 is supported for the demo. It should be
+relatively easy to add more. To add a new architecture you need
+a toolchain available with libc. You then need to generate a
+respective base template custom linker script for userspace
+as is provided on x86 in arch/x86/kernel/vmlinux.lds.S.
+
+A respective architecture tools/arch/$(ARCH)/include/* file for
+each section-core.h, ranges.h, tables.h will need to be provided
+as well. If your architecture's file is generated copy the generated
+file over.
+
+x86 Simulated boots
+=========+
+This programs simulates boot on both bare metal and with the
+Xen PV entry on x86.
+
+Emulate bare metal boot:
+
+./demo
+
+Emulate Xen boot (x86):
+
+./demo -x
+
+Testing new features
+==========
+
+A copy of each kernel header file is maintained in tools/include/,
+as well as a respective generated asm file for each sandbox supported
+architecture. This sandbox has a built in checker for when these files
+get out of sync.
+
+If testing new extensions on the files:
+
+  o section-core
+  o ranges.h
+  o tables.h
+
+You'll want to copy them into tools as well. If you are working on
+using these files you can work within the current directory's namespace,
+including its own set of header files, so tools/linker-tables/include/ and
+each respective tools/linker-tables/arch/$(ARCH)/include/asm/.
+
+Features evaluation
+=========+
+This lists features currently being evaluated in the sandbox, not yet
+present upstream. These make use of the existing set of header files
+without modification.
+
+ o Demo use of initialization on for x86, refer to arch/x86/kernel/init.c
+
+ o Demo use of porting the kernel's init call levels to linker tables, refer
+   to the init_calls linker table use on kernel/main.c
+
+ o Demo use of an asm-generic architecture init family, which could potentially
+   be used to help share initialization sequences on simple architectures.
+   Refer to include/asm-generic/arch_init_fn.h
+
+ o Building synthetic routines with the option to provide enhancements
+   per architecture in asm, refer to drivers/synth/or.S and its use on
+   synth_init_or().
+
+ o User of linker tables for alternatives with consts - refer to
+   use of the ps_set_const_table linker table and its use in
+   arch/x86/kernel/alternative.c
diff --git a/tools/linker-tables/arch/x86/include/asm/asm.h b/tools/linker-tables/arch/x86/include/asm/asm.h
new file mode 100644
index 000000000000..155a52920dfb
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/asm.h
@@ -0,0 +1,17 @@
+#ifndef _ASM_X86_ASM_H
+
+#ifdef __ASSEMBLY__
+# define __ASM_FORM(x)	x
+# define __ASM_FORM_RAW(x)     x
+# define __ASM_FORM_COMMA(x) x,
+#else
+# define __ASM_FORM(x)	" " #x " "
+# define __ASM_FORM_RAW(x)     #x
+# define __ASM_FORM_COMMA(x) " " #x ","
+#endif
+
+# define __ASM_SEL(a,b) __ASM_FORM(b)
+# define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(b)
+#define _ASM_PTR	__ASM_SEL(.long, .quad)
+
+#endif /* _ASM_X86_ASM_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/boot.h b/tools/linker-tables/arch/x86/include/asm/boot.h
new file mode 100644
index 000000000000..af91b94ad5a6
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/boot.h
@@ -0,0 +1 @@
+extern struct boot_params boot_params;
diff --git a/tools/linker-tables/arch/x86/include/asm/bootparam.h b/tools/linker-tables/arch/x86/include/asm/bootparam.h
new file mode 100644
index 000000000000..a7ef34216f7f
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/bootparam.h
@@ -0,0 +1,32 @@
+#ifndef __BOOTPARAM_H
+#define __BOOTPARAM_H
+
+#include <linux/types.h>
+
+struct setup_header {
+	__u32 hardware_subarch;
+} __attribute__((packed));
+
+struct boot_params {
+	struct setup_header hdr;
+} __attribute__((packed));
+
+enum {
+	X86_SUBARCH_PC = 0,
+	X86_SUBARCH_LGUEST,
+	X86_SUBARCH_XEN,
+	X86_SUBARCH_INTEL_MID,
+	X86_SUBARCH_CE4100,
+	X86_NR_SUBARCHS,
+};
+
+#define X86_SUBARCH_ALL_SUBARCHS 	\
+	(				\
+	BIT(X86_SUBARCH_PC) |		\
+	BIT(X86_SUBARCH_LGUEST) |	\
+	BIT(X86_SUBARCH_XEN) |		\
+	BIT(X86_SUBARCH_INTEL_MID) |	\
+	BIT(X86_SUBARCH_CE4100)		\
+	)
+
+#endif /* __BOOTPARAM_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/kprobes.h b/tools/linker-tables/arch/x86/include/asm/kprobes.h
new file mode 100644
index 000000000000..f702fc359efe
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/kprobes.h
@@ -0,0 +1,7 @@
+#ifndef _SANDBOX_ASM_X86_KPROBES_H
+#define _SANDBOX_ASM_X86_KPROBES_H
+
+/* This is all we need for the demo */
+#include <asm-generic/kprobes.h>
+
+#endif /* _SANDBOX_ASM_X86_KPROBES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/ps_const.h b/tools/linker-tables/arch/x86/include/asm/ps_const.h
new file mode 100644
index 000000000000..b9901f35cfca
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/ps_const.h
@@ -0,0 +1,21 @@
+#ifndef __X86_PS_CONST
+#define __X86_PS_CONST
+
+#include <linux/tables.h>
+#include <asm/asm.h>
+
+#define ps_shr(_in, _func)						\
+({									\
+	__typeof__(_in) _out;						\
+	asm volatile(							\
+		"shr $0,%0\n"						\
+		"1:\n"							\
+		SECTION_TBL_STR(SECTION_INIT_DATA, ps_set_const_table, 01)\
+		_ASM_PTR "1b-1, %P2, %P3\n"				\
+		".popsection\n"						\
+		: "=rm" (_out)						\
+		: "0" (_in), "i" (SET_CONST_U8), "i" (_func));		\
+	(_out);								\
+})
+
+#endif /* __X86_PS_CONST */
diff --git a/tools/linker-tables/arch/x86/include/asm/ranges.h b/tools/linker-tables/arch/x86/include/asm/ranges.h
new file mode 100644
index 000000000000..823789d2b010
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/ranges.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_RANGES_H
+#define _ASM_X86_RANGES_H
+
+#include <asm-generic/ranges.h>
+
+#endif  /* _ASM_X86_RANGES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/section-core.h b/tools/linker-tables/arch/x86/include/asm/section-core.h
new file mode 100644
index 000000000000..06be2b1c424f
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/section-core.h
@@ -0,0 +1 @@
+#include <asm-generic/section-core.h>
diff --git a/tools/linker-tables/arch/x86/include/asm/setup.h b/tools/linker-tables/arch/x86/include/asm/setup.h
new file mode 100644
index 000000000000..366c36bd2910
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/setup.h
@@ -0,0 +1,6 @@
+#ifndef __LINUX_X86_USER_SETUP_H
+#define __LINUX_X86_USER_SETUP_H
+
+/* I'm lazy */
+
+#endif /* __LINUX_X86_USER_SETUP_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/tables.h b/tools/linker-tables/arch/x86/include/asm/tables.h
new file mode 100644
index 000000000000..797df3407ee1
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/tables.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_TABLES_H
+#define _ASM_X86_TABLES_H
+
+#include <asm-generic/tables.h>
+
+#endif  /* _ASM_X86_RANGES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/x86.h b/tools/linker-tables/arch/x86/include/asm/x86.h
new file mode 100644
index 000000000000..680c1141e0de
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/x86.h
@@ -0,0 +1,4 @@
+int startup_64(void);
+int x86_64_start_reservations(void);
+void setup_arch(void);
+void late_init(void);
diff --git a/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h b/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
new file mode 100644
index 000000000000..afece8ce6dd4
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
@@ -0,0 +1,169 @@
+#ifndef __X86_INIT_TABLES_H
+#define __X86_INIT_TABLES_H
+
+#include <linux/types.h>
+#include <linux/tables.h>
+
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <asm/bootparam.h>
+
+/**
+ * struct x86_init_fn - x86 generic kernel init call
+ *
+ * Linux x86 features vary in complexity, features may require work done at
+ * different levels of the full x86 init sequence. Today there are also two
+ * different possible entry points for Linux on x86, one for bare metal, KVM
+ * and Xen HVM, and another for Xen PV guests / dom0.  Assuming a bootloader
+ * has set up 64-bit mode, roughly the x86 init sequence follows this path:
+ *
+ * Bare metal, KVM, Xen HVM                      Xen PV / dom0
+ *       startup_64()                             startup_xen()
+ *              \                                     /
+ *      x86_64_start_kernel()                 xen_start_kernel()
+ *                           \               /
+ *                      x86_64_start_reservations()
+ *                                   |
+ *                              start_kernel()
+ *                              [   ...        ]
+ *                              [ setup_arch() ]
+ *                              [   ...        ]
+ *                                  init
+ *
+ * x86_64_start_kernel() and xen_start_kernel() are the respective first C code
+ * entry starting points. The different entry points exist to enable Xen to
+ * skip a lot of hardware setup already done and managed on behalf of the
+ * hypervisor, we refer to this as "paravirtualization yielding". The different
+ * levels of init calls on the x86 init sequence exist to account for these
+ * slight differences and requirements. These different entry points also share
+ * a common entry x86 specific path, x86_64_start_reservations().
+ *
+ * A generic x86 feature can have different initialization calls, one on each
+ * of the different main x86 init sequences, but must also address both entry
+ * points in order to work properly across the board on all supported x86
+ * subarchitectures. Since x86 features can also have dependencies on other
+ * setup code or features, x86 features can at times be subordinate to other
+ * x86 features, or conditions. struct x86_init_fn enables feature developers
+ * to annotate dependency relationships to ensure subsequent init calls only
+ * run once a subordinate's dependencies have run. When needed custom
+ * dependency requirements can also be spelled out through a custom dependency
+ * checker. In order to account for the dual entry point nature of x86-64 Linux
+ * for "paravirtualization yielding" and to make annotations for support for
+ * these explicit each struct x86_init_fn must specify supported
+ * subarchitectures. The earliest x86-64 code can read the subarchitecture
+ * though is after load_idt(), as such the earliest we can currently rely on
+ * subarchitecture for semantics and a common init sequences is on the shared
+ * common x86_64_start_reservations().  Each struct x86_init_fn is associated
+ * with a specific special link order number which has been careflly thought
+ * out by x86 maintainers. You should pick a link order level associated with
+ * the specific directory your code lies in, a respective macro is used to
+ * build association to a link oder with a routine, you should use one of the
+ * provided x86_init_*() macros. You should not use __x86_init() directly.
+ *
+ * x86_init_fn enables strong semantics and dependencies to be defined and
+ * implemented on the full x86 initialization sequence.
+ *
+ * @supp_hardware_subarch: must be set, it represents the bitmask of supported
+ *	subarchitectures.  We require each struct x86_init_fn to have this set
+ *	to require developer considerations for each supported x86
+ *	subarchitecture and to build strong annotations of different possible
+ *	run time states particularly in consideration for the two main
+ *	different entry points for x86 Linux, to account for paravirtualization
+ *	yielding.
+ *
+ *	The subarchitecture is read by the kernel at early boot from the
+ *	struct boot_params hardware_subarch. Support for the subarchitecture
+ *	exists as of x86 boot protocol 2.07. The bootloader would have set up
+ *	the respective hardware_subarch on the boot sector as per
+ *	Documentation/x86/boot.txt.
+ *
+ *	What x86 entry point is used is determined at run time by the
+ *	bootloader. Linux pv_ops was designed to help enable to build one Linux
+ *	binary to support bare metal and different hypervisors.  pv_ops setup
+ *	code however is limited in that all pv_ops setup code is run late in
+ *	the x86 init sequence, during setup_arch(). In fact cpu_has_hypervisor
+ *	only works after early_cpu_init() during setup_arch(). If an x86
+ *	feature requires an earlier determination of what hypervisor was used,
+ *	or if it needs to annotate only support for certain hypervisors, the
+ *	x86 hardware_subarch should be set by the bootloader and
+ *	@supp_hardware_subarch set by the x86 feature. Using hardware_subarch
+ *	enables x86 features to fill the semantic gap between the Linux x86
+ *	entry point used and what pv_ops has to offer through a hypervisor
+ *	agnostic mechanism.
+ *
+ *	Each supported subarchitecture is set using the respective
+ *	X86_SUBARCH_* as a bit in the bitmask. For instance if a feature
+ *	is supported on PC and Xen subarchitectures only you would set this
+ *	bitmask to:
+ *
+ *		BIT(X86_SUBARCH_PC) |
+ *		BIT(X86_SUBARCH_XEN);
+ *
+ * @early_init: required, routine which will run in x86_64_start_reservations()
+ *	after we ensure boot_params.hdr.hardware_subarch is accessible and
+ *	properly set. Memory is not yet available. This the earliest we can
+ *	currently define a common shared callback since all callbacks need to
+ *	check for boot_params.hdr.hardware_subarch and this becomes accessible
+ *	on x86-64 until after load_idt().
+ */
+struct x86_init_fn {
+	__u32 supp_hardware_subarch;
+	void (*early_init)(void);
+};
+
+DECLARE_LINKTABLE(struct x86_init_fn, x86_init_fns);
+
+/* Init order levels, we can start at 0000 but reserve 0000-0999 for now */
+
+/*
+ * X86_INIT_ORDER_EARLY - early kernel init code
+ *
+ * This consists of the first parts of the Linux kernel executed.
+ */
+#define X86_INIT_ORDER_EARLY	1000
+
+/* X86_INIT_ORDER_PLATFORM - platform kernel code
+ *
+ * Code the kernel needs to initialize under arch/x86/platform/
+ * early in boot.
+ */
+#define X86_INIT_ORDER_PLATFORM	3000
+
+#define __x86_init(__level,						\
+		   __supp_hardware_subarch,				\
+		   __early_init)					\
+	static LINKTABLE_INIT_DATA(x86_init_fns, __level)		\
+	__x86_init_fn_##__early_init = {				\
+		.supp_hardware_subarch = __supp_hardware_subarch,	\
+		.early_init = __early_init,				\
+	};
+
+#define x86_init_early(__supp_hardware_subarch,				\
+		       __early_init)					\
+	__x86_init(X86_INIT_ORDER_EARLY, __supp_hardware_subarch,	\
+		   __early_init);
+
+#define x86_init_platform(__supp_hardware_subarch,			\
+		       __early_init)					\
+	__x86_init(__name, X86_INIT_ORDER_PLATFORM, __supp_hardware_subarch,\
+		   __early_init);
+
+#define x86_init_early_all(__early_init)				\
+	x86_init_early(X86_SUBARCH_ALL_SUBARCHS,			\
+		       __early_init);
+
+#define x86_init_early_pc(__early_init)					\
+	x86_init_early(BIT(X86_SUBARCH_PC),				\
+		       __early_init);
+
+#define x86_init_early_xen(__early_init)				\
+	x86_init_early(BIT(X86_SUBARCH_XEN),				\
+		       __early_init);
+/**
+ * x86_init_fn_early_init: call all early_init() callbacks
+ *
+ * This calls all early_init() callbacks on the x86_init_fns linker table.
+ */
+void x86_init_fn_early_init(void);
+
+#endif /* __X86_INIT_TABLES_H */
diff --git a/tools/linker-tables/arch/x86/kernel/alpha.c b/tools/linker-tables/arch/x86/kernel/alpha.c
new file mode 100644
index 000000000000..0f9d45734c33
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/alpha.c
@@ -0,0 +1,9 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_alpha(void) {
+	pr_info("Initializing alpha ...\n");
+	pr_info("Completed initializing alpha !\n");
+}
+
+x86_init_early_pc(early_init_alpha);
diff --git a/tools/linker-tables/arch/x86/kernel/alternative.c b/tools/linker-tables/arch/x86/kernel/alternative.c
new file mode 100644
index 000000000000..ed80a822d726
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/alternative.c
@@ -0,0 +1,31 @@
+#include <asm/x86_init_fn.h>
+
+#include <linux/kernel.h>
+#include <linux/ps_const.h>
+
+void apply_alternatives_linker_tables(void)
+{
+	unsigned int num_consts = LINUX_SECTION_SIZE(ps_set_const_table);
+	struct ps_set_const *ps_const;
+
+	if (!num_consts)
+		return;
+
+	pr_debug("Number of init entries: %d\n", num_consts);
+
+	LINKTABLE_FOR_EACH(ps_const, ps_set_const_table) {
+		switch(ps_const->type) {
+		case SET_CONST_U8:
+			*ps_const->count = (__u8) ps_const->func();
+			break;
+		case SET_CONST_U16:
+			*ps_const->count = (__u16) ps_const->func();
+			break;
+		case SET_CONST_U32:
+			*ps_const->count = (__u16) ps_const->func();
+			break;
+		}
+	}
+}
+
+x86_init_early_pc(apply_alternatives_linker_tables);
diff --git a/tools/linker-tables/arch/x86/kernel/beta.c b/tools/linker-tables/arch/x86/kernel/beta.c
new file mode 100644
index 000000000000..2bdbf49d4731
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/beta.c
@@ -0,0 +1,9 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_beta(void) {
+	pr_info("Initializing beta ...\n");
+	pr_info("Completed initializing beta !\n");
+}
+
+x86_init_early_pc(early_init_beta);
diff --git a/tools/linker-tables/arch/x86/kernel/head64.c b/tools/linker-tables/arch/x86/kernel/head64.c
new file mode 100644
index 000000000000..d14dcdfd0ea9
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/head64.c
@@ -0,0 +1,58 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+
+#include <asm/x86_init_fn.h>
+#include <asm/boot.h>
+#include <asm/bootparam.h>
+
+#include <linux/start_kernel.h>
+#include <linux/kasan.h>
+
+void x86_64_start_reservations(void)
+{
+	switch (boot_params.hdr.hardware_subarch) {
+	case X86_SUBARCH_PC:
+		pr_info("Booting bare metal\n");
+		break;
+	case X86_SUBARCH_LGUEST:
+		pr_info("Booting lguest not supported\n");
+		BUG();
+	case X86_SUBARCH_XEN:
+		pr_info("Booting a Xen guest\n");
+		break;
+	case X86_SUBARCH_INTEL_MID:
+		pr_info("Booting Intel MID not supported\n");
+		BUG();
+	case X86_SUBARCH_CE4100:
+		pr_info("Booting Intel CE4100 not supported\n");
+		BUG();
+	default:
+		pr_info("Booting sunsupported x86 hardware subarch\n");
+		BUG();
+	}
+
+	start_kernel();
+}
+
+static void x86_64_start_kernel(void)
+{
+	x86_init_fn_early_init();
+
+	x86_64_start_reservations();
+}
+
+void startup_64(void)
+{
+	pr_info("Initializing x86 bare metal world\n");
+	x86_64_start_kernel();
+}
+
+void setup_arch(void)
+{
+	/* TODO: x86_init_fn_setup_arch(); */
+}
+
+void late_init(void)
+{
+	/* TODO: x86_init_fn_late_init(); */
+}
diff --git a/tools/linker-tables/arch/x86/kernel/init.c b/tools/linker-tables/arch/x86/kernel/init.c
new file mode 100644
index 000000000000..22702365ef51
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/init.c
@@ -0,0 +1,42 @@
+#define pr_fmt(fmt) "x86-init: " fmt
+
+#include <linux/bug.h>
+#include <linux/kernel.h>
+
+#include <asm/x86_init_fn.h>
+#include <asm/bootparam.h>
+#include <asm/boot.h>
+#include <asm/setup.h>
+
+DEFINE_LINKTABLE_INIT_DATA(struct x86_init_fn, x86_init_fns);
+
+static bool x86_init_fn_supports_subarch(struct x86_init_fn *fn)
+{
+	if (!fn->supp_hardware_subarch) {
+		//pr_err("Init sequence fails to declares any supported subarchs: %pF\n", fn->early_init);
+		WARN_ON(1);
+	}
+	if (BIT(boot_params.hdr.hardware_subarch) & fn->supp_hardware_subarch)
+		return true;
+	return false;
+}
+
+void __ref x86_init_fn_early_init(void)
+{
+	struct x86_init_fn *init_fn;
+	unsigned int num_inits = LINUX_SECTION_SIZE(x86_init_fns);
+
+	if (!num_inits)
+		return;
+
+	pr_debug("Number of init entries: %d\n", num_inits);
+
+	LINKTABLE_FOR_EACH(init_fn, x86_init_fns) {
+		if (!x86_init_fn_supports_subarch(init_fn))
+			continue;
+
+		//pr_debug("Running early init %pF ...\n", init_fn->early_init);
+		init_fn->early_init();
+		//pr_debug("Completed early init %pF\n", init_fn->early_init);
+	}
+}
diff --git a/tools/linker-tables/arch/x86/kernel/kasan.c b/tools/linker-tables/arch/x86/kernel/kasan.c
new file mode 100644
index 000000000000..c0120676eb9c
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/kasan.c
@@ -0,0 +1,10 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+void kasan_early_init(void) {
+	pr_info("Initializing kasan ...\n");
+	pr_info("Early init for Kasan...\n");
+	pr_info("Completed initializing kasan !\n");
+}
+
+x86_init_early_pc(kasan_early_init);
diff --git a/tools/linker-tables/arch/x86/kernel/kprobes.c b/tools/linker-tables/arch/x86/kernel/kprobes.c
new file mode 100644
index 000000000000..1d5a74bec754
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/kprobes.c
@@ -0,0 +1,51 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <linux/ranges.h>
+#include <linux/kprobes.h>
+
+DEFINE_SECTION_RANGE(kprobes, SECTION_TEXT);
+
+void __kprobes test_kprobe_0001(void)
+{
+	pr_info("test_kprobe\n");
+}
+
+void test_kprobe_0002(void)
+{
+	pr_info("test_kprobe\n");
+}
+
+void test_kprobe_addr(const char *test, unsigned long addr, bool should_match)
+{
+	if (SECTION_ADDR_IN_RANGE(kprobes, addr))
+		if (should_match)
+			pr_info("= OK: %s within range!\n", test);
+		else
+			pr_info("= FAIL: %s should not be in range...\n",
+				test);
+	else
+		if (should_match)
+			pr_info("= FAIL: %s should be in range...\n", test);
+		else
+			pr_info("= OK: %s not in range as expected!\n", test);
+}
+
+void early_init_kprobes(void)
+{
+	unsigned long addr;
+
+	pr_info("Initializing kprobes ...\n");
+
+	addr = (unsigned long) &test_kprobe_0001;
+
+	test_kprobe_addr("test_kprobe_0001", addr, true);
+
+	addr = (unsigned long) &test_kprobe_0002;
+
+	test_kprobe_addr("test_kprobe_0002", addr, false);
+
+	pr_info("Completed initializing kprobes !\n");
+}
+
+x86_init_early_all(early_init_kprobes);
diff --git a/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S b/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
new file mode 100644
index 000000000000..2ef049fc3bdb
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
@@ -0,0 +1,273 @@
+/* Script for -z combreloc: combine and sort reloc sections */
+/* Copyright (C) 2014 Free Software Foundation, Inc.
+   Copying and distribution of this script, with or without modification,
+   are permitted in any medium without royalty provided the copyright
+   notice and this notice are preserved.  */
+
+#include <asm/section-core.h>
+#include <asm/ranges.h>
+#include <asm/tables.h>
+
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
+	      "elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(_start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
+  .interp         : { *(.interp) }
+  .note.gnu.build-id : { *(.note.gnu.build-id) }
+  .hash           : { *(.hash) }
+  .gnu.hash       : { *(.gnu.hash) }
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+  .rela.dyn       :
+    {
+      *(.rela.init)
+      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+      *(.rela.fini)
+      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+      *(.rela.ctors)
+      *(.rela.dtors)
+      *(.rela.got)
+      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+      *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
+      *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
+      *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
+      *(.rela.ifunc)
+    }
+  .rela.plt       :
+    {
+      *(.rela.plt)
+      PROVIDE_HIDDEN (__rela_iplt_start = .);
+      *(.rela.iplt)
+      PROVIDE_HIDDEN (__rela_iplt_end = .);
+    }
+  .init           :
+  {
+    KEEP (*(SORT_NONE(.init)))
+  }
+  .plt            : { *(.plt) *(.iplt) }
+  .plt.bnd        : { *(.plt.bnd) }
+  SECTION_TEXT    :
+  {
+    *(.text.unlikely .text.*_unlikely .text.unlikely.*)
+    *(.text.exit .text.exit.*)
+    *(.text.startup .text.startup.*)
+    *(.text.hot .text.hot.*)
+    *(SORT(SECTION_RNG_ALL(SECTION_TEXT)))
+    *(SORT(SECTION_TBL_ALL(SECTION_TEXT)))
+
+    *(SORT(SECTION_RNG_ALL(SECTION_INIT)))
+    *(SORT(SECTION_TBL_ALL(SECTION_INIT)))
+
+    *(SORT(SECTION_RNG_ALL(SECTION_INIT_CALL)))
+    *(SORT(SECTION_TBL_ALL(SECTION_INIT_CALL)))
+
+    *(SORT(SECTION_RNG_ALL(SECTION_EXIT)))
+    *(SORT(SECTION_TBL_ALL(SECTION_EXIT)))
+
+    *(SORT(SECTION_RNG_ALL(SECTION_EXIT_CALL)))
+    *(SORT(SECTION_TBL_ALL(SECTION_EXIT_CALL)))
+    *(SECTION_TEXT .stub SECTION_ALL(SECTION_TEXT) .gnu.linkonce.t.*)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  }
+  .fini           :
+  {
+    KEEP (*(SORT_NONE(.fini)))
+  }
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+  .rodata         :
+  {
+	*(.rodata)
+	*(SORT(.rodata.*))
+
+	*(SORT(SECTION_RNG_ALL(SECTION_RODATA)))
+	*(SORT(SECTION_TBL_ALL(SECTION_RODATA)))
+
+	*(SORT(SECTION_RNG_ALL(SECTION_INIT_RODATA)))
+	*(SORT(SECTION_TBL_ALL(SECTION_INIT_RODATA)))
+
+	*(SORT(SECTION_RNG_ALL(SECTION_REF_RODATA)))
+	*(SORT(SECTION_TBL_ALL(SECTION_REF_RODATA)))
+	*(.gnu.linkonce.r.*)
+  }
+  .rodata1        : { *(.rodata1) }
+  .eh_frame_hdr : { *(.eh_frame_hdr) }
+  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table
+  .gcc_except_table.*) }
+  /* These sections are generated by the Sun/Oracle C++ compiler.  */
+  .exception_ranges   : ONLY_IF_RO { *(.exception_ranges
+  .exception_ranges*) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  */
+  . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+  /* Exception handling  */
+  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
+  .exception_ranges   : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
+  /* Thread Local Storage sections  */
+  .tdata	  : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+  .preinit_array     :
+  {
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP (*(.preinit_array))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+  }
+  .init_array     :
+  {
+    PROVIDE_HIDDEN (__init_array_start = .);
+    KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
+    KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
+    PROVIDE_HIDDEN (__init_array_end = .);
+  }
+  .fini_array     :
+  {
+    PROVIDE_HIDDEN (__fini_array_start = .);
+    KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
+    KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
+    PROVIDE_HIDDEN (__fini_array_end = .);
+  }
+  .ctors          :
+  {
+    /* gcc uses crtbegin.o to find the start of
+       the constructors, so we make sure it is
+       first.  Because this is a wildcard, it
+       doesn't matter if the user does not
+       actually link against crtbegin.o; the
+       linker won't look for a file to match a
+       wildcard.  The wildcard also means that it
+       doesn't matter which directory crtbegin.o
+       is in.  */
+    KEEP (*crtbegin.o(.ctors))
+    KEEP (*crtbegin?.o(.ctors))
+    /* We don't want to include the .ctor section from
+       the crtend.o file until after the sorted ctors.
+       The .ctor section from the crtend file contains the
+       end of ctors marker and it must be last */
+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+  .dtors          :
+  {
+    KEEP (*crtbegin.o(.dtors))
+    KEEP (*crtbegin?.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  .jcr            : { KEEP (*(.jcr)) }
+  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
+  .dynamic        : { *(.dynamic) }
+  .got            : { *(.got) *(.igot) }
+  . = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
+  .got.plt        : { *(.got.plt)  *(.igot.plt) }
+  .data           :
+  {
+    *(.data .data.* .gnu.linkonce.d.*)
+
+    *(SORT(SECTION_RNG_ALL(SECTION_DATA)))
+    *(SORT(SECTION_TBL_ALL(SECTION_DATA)))
+
+    *(SORT(SECTION_RNG_ALL(SECTION_INIT_DATA)))
+    *(SORT(SECTION_TBL_ALL(SECTION_INIT_DATA)))
+
+    *(SORT(SECTION_RNG_ALL(SECTION_REF_DATA)))
+    *(SORT(SECTION_TBL_ALL(SECTION_REF_DATA)))
+
+    *(SORT(SECTION_RNG_ALL(SECTION_EXIT_DATA)))
+    *(SORT(SECTION_TBL_ALL(SECTION_EXIT_DATA)))
+
+    SORT(CONSTRUCTORS)
+  }
+  .data1          : { *(.data1) }
+  _edata = .; PROVIDE (edata = .);
+  . = .;
+
+  __bss_start = .;
+  .bss            :
+  {
+   *(.dynbss)
+   *(.bss .bss.* .gnu.linkonce.b.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.
+      FIXME: Why do we need it? When there is no .bss section, we don't
+      pad the .data section.  */
+   . = ALIGN(. != 0 ? 64 / 8 : 1);
+  }
+  .lbss   :
+  {
+    *(.dynlbss)
+    *(.lbss .lbss.* .gnu.linkonce.lb.*)
+    *(LARGE_COMMON)
+  }
+  . = ALIGN(64 / 8);
+  . = SEGMENT_START("ldata-segment", .);
+  .lrodata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+  {
+    *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
+  }
+  .ldata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+  {
+    *(.ldata .ldata.* .gnu.linkonce.l.*)
+    . = ALIGN(. != 0 ? 64 / 8 : 1);
+  }
+  . = ALIGN(64 / 8);
+  _end = .; PROVIDE (end = .);
+  . = DATA_SEGMENT_END (.);
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line .debug_line.* .debug_line_end ) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  /* DWARF 3 */
+  .debug_pubtypes 0 : { *(.debug_pubtypes) }
+  .debug_ranges   0 : { *(.debug_ranges) }
+  /* DWARF Extension.  */
+  .debug_macro    0 : { *(.debug_macro) }
+  .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
+}
diff --git a/tools/linker-tables/arch/x86/mm/init.c b/tools/linker-tables/arch/x86/mm/init.c
new file mode 100644
index 000000000000..dbf1a85a4043
--- /dev/null
+++ b/tools/linker-tables/arch/x86/mm/init.c
@@ -0,0 +1,10 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_memory(void) {
+	pr_info("Initializing memory ...\n");
+	sleep(1);
+	pr_info("Completed initializing memory !\n");
+}
+
+x86_init_early_all(early_init_memory);
diff --git a/tools/linker-tables/arch/x86/xen/init.c b/tools/linker-tables/arch/x86/xen/init.c
new file mode 100644
index 000000000000..40ad493daee8
--- /dev/null
+++ b/tools/linker-tables/arch/x86/xen/init.c
@@ -0,0 +1,13 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <asm/x86.h>
+
+void startup_xen(void)
+{
+	pr_info("Initializing Xen guest\n");
+
+	x86_init_fn_early_init();
+
+	x86_64_start_reservations();
+}
diff --git a/tools/linker-tables/drivers/acme.c b/tools/linker-tables/drivers/acme.c
new file mode 100644
index 000000000000..dd321686dd49
--- /dev/null
+++ b/tools/linker-tables/drivers/acme.c
@@ -0,0 +1,32 @@
+#define pr_fmt(fmt) "ACME: " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/workqueue.h>
+
+void *acme_todo(void *arg);
+static DECLARE_WORK(acme_work, acme_todo);
+
+void *acme_todo(void *arg)
+{
+	pr_info("Running scheduled work\n");
+	pthread_exit(NULL);
+}
+
+static int acme_init_driver(void) {
+	pr_info("Initializing ...\n");
+	sleep(2);
+	pr_info("Finished init ... !\n");
+
+	init_work(&acme_work);
+	schedule_work(&acme_work);
+
+	return 0;
+}
+module_init(acme_init_driver);
+
+static void acme_exit(void)
+{
+	cancel_work_sync(&acme_work);
+};
+module_exit(acme_exit);
diff --git a/tools/linker-tables/drivers/synth/common.c b/tools/linker-tables/drivers/synth/common.c
new file mode 100644
index 000000000000..b44d9fcc7a9b
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/common.c
@@ -0,0 +1,16 @@
+int demo_or_1(int arg)
+{
+	switch (arg) {
+	case 1:
+		return 0xDEA00000;
+	case 2:
+		return 0X000D0000;
+	default:
+		return arg * 2;
+	}
+}
+
+int demo_or_2(void)
+{
+	return 0x0000BEEF;
+}
diff --git a/tools/linker-tables/drivers/synth/common.h b/tools/linker-tables/drivers/synth/common.h
new file mode 100644
index 000000000000..92827004f532
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/common.h
@@ -0,0 +1,2 @@
+int demo_or_1(int arg);
+int demo_or_2(void);
diff --git a/tools/linker-tables/drivers/synth/main.c b/tools/linker-tables/drivers/synth/main.c
new file mode 100644
index 000000000000..555cf97a5cbb
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/main.c
@@ -0,0 +1,35 @@
+#define pr_fmt(fmt) "Synthetics: " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ps_const.h>
+
+#include "common.h"
+#include "synth.h"
+
+DEFINE_LINKTABLE_INIT_DATA(struct ps_set_const, ps_set_const_table);
+
+unsigned int get_demo_shr(void)
+{
+	return 16;
+}
+
+static int synth_init(void)
+{
+	int synth_or;
+	int val = 2;
+	const unsigned int reg =  ps_shr(0xDEADBEEF, get_demo_shr);
+
+	synth_or = synth_init_or(val);
+	pr_info("synth_init_or(%d) returns: 0x%08X\n", val, synth_or);
+
+	pr_info("ps_shr(0x%08X, get_demo_shr) returns: 0x%08X\n", 0xDEADBEEF, reg);
+
+	return 0;
+}
+module_init(synth_init);
+
+static void synth_exit(void)
+{
+}
+module_exit(synth_exit);
diff --git a/tools/linker-tables/drivers/synth/or.S b/tools/linker-tables/drivers/synth/or.S
new file mode 100644
index 000000000000..983d913c8052
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/or.S
@@ -0,0 +1,39 @@
+#include <asm/ranges.h>
+
+	DEFINE_SECTION_RANGE(SECTION_TEXT, synth_init_or)
+
+	push_section_rng_level(SECTION_TEXT, synth_init_or, "01", )
+	/* err = 0; */
+	pushq %rbp
+	movq %rsp,%rbp
+	pushq %rbx
+	xorq %rbx,%rbx
+	.popsection
+
+	push_section_rng_level(SECTION_TEXT, synth_init_or, "99", )
+	/* return err; */
+	movq %rbx,%rax
+	popq %rbx
+	popq %rbp
+	retq
+	.popsection
+
+	push_section_rng_level(SECTION_TEXT, synth_init_or, "50", )
+	/* err |= demo_or_1(1); */
+	movl $1,%edi
+	call demo_or_1
+	orq %rax,%rbx
+	.popsection
+
+	push_section_rng_level(SECTION_TEXT, synth_init_or, "50", )
+	/* err |= demo_or_1(2); */
+	movl $2,%edi
+	call demo_or_1
+	orq %rax,%rbx
+	.popsection
+
+	push_section_rng_level(SECTION_TEXT, synth_init_or, "50", )
+	/* err |= demo_or_2(); */
+	call demo_or_2
+	orq %rax,%rbx
+	.popsection
diff --git a/tools/linker-tables/drivers/synth/synth.h b/tools/linker-tables/drivers/synth/synth.h
new file mode 100644
index 000000000000..abbb9afac374
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/synth.h
@@ -0,0 +1,2 @@
+/* Synthetic demos go here */
+int synth_init_or(int arg);
diff --git a/tools/linker-tables/drivers/xen-driver.c b/tools/linker-tables/drivers/xen-driver.c
new file mode 100644
index 000000000000..79d229f72818
--- /dev/null
+++ b/tools/linker-tables/drivers/xen-driver.c
@@ -0,0 +1,11 @@
+#include <asm/x86_init_fn.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <xen/xen.h>
+
+static void early_xen_init_driver(void) {
+	pr_info("Initializing xen driver\n");
+	sleep(2);
+}
+
+x86_init_early_xen(early_xen_init_driver);
diff --git a/tools/linker-tables/include/asm-generic/arch_init_fn.h b/tools/linker-tables/include/asm-generic/arch_init_fn.h
new file mode 100644
index 000000000000..61a04a50b453
--- /dev/null
+++ b/tools/linker-tables/include/asm-generic/arch_init_fn.h
@@ -0,0 +1,50 @@
+#ifndef __ARCH_INIT_TABLES_H
+#define __ARCH_INIT_TABLES_H
+
+#include <linux/types.h>
+#include <linux/tables.h>
+#include <linux/init.h>
+
+/**
+ * struct arch_init_fn - architecture-generic kernel init call
+ *
+ * Architectures must initialize a series of things prior to handing off
+ * control to the kernel. This structure can be used if the architecture is
+ * simple and it just needs a basic set of calls on its way up.
+ *
+ * @early_init: required, routine which will run in startup_64(). Memory is
+ * 	not yet available.
+ */
+struct arch_init_fn {
+	void (*early_init)(void);
+};
+
+DECLARE_LINKTABLE(struct arch_init_fn, arch_init_fns);
+
+/* Init order levels, we can start at 0000 but reserve 0000-0999 for now */
+
+/*
+ * ARCH_INIT_ORDER_EARLY - early kernel init code
+ *
+ * This consists of the first parts of the Linux kernel executed.
+ */
+#define ARCH_INIT_ORDER_EARLY	1000
+
+#define __arch_init(__level,						\
+		    __early_init)					\
+	static LINKTABLE_INIT_DATA(arch_init_fns, __level)		\
+	__arch_init_fn_##__early_init = {				\
+		.early_init = __early_init,				\
+	}
+
+#define arch_init_early(__early_init)					\
+	__arch_init(ARCH_INIT_ORDER_EARLY, __early_init)
+
+/**
+ * arch_init_fn_early_init: call all early_init() callbacks
+ *
+ * This calls all early_init() callbacks on the arch_init_fns linker table.
+ */
+void arch_init_fn_early_init(void);
+
+#endif /* __ARCH_INIT_TABLES_H */
diff --git a/tools/linker-tables/include/asm-generic/kprobes.h b/tools/linker-tables/include/asm-generic/kprobes.h
new file mode 100644
index 000000000000..d41d7e9b607d
--- /dev/null
+++ b/tools/linker-tables/include/asm-generic/kprobes.h
@@ -0,0 +1,26 @@
+#ifndef _SANDBOX_ASM_GENERIC_KPROBES_H
+#define _SANDBOX_ASM_GENERIC_KPROBES_H
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#ifdef CONFIG_KPROBES
+#include <linux/tables.h>
+#include <asm/ranges.h>
+/*
+ * Blacklist ganerating macro. Specify functions which is not probed
+ * by using this macro.
+ */
+# define __NOKPROBE_SYMBOL(fname)				\
+static LINKTABLE_INIT_DATA(_kprobe_blacklist, all)		\
+	_kbl_addr_##fname = (unsigned long)fname;
+# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
+/* Use this to forbid a kprobes attach on very low level functions */
+# define __kprobes	__LINUX_RANGE(SECTION_TEXT, kprobes)
+# define nokprobe_inline	__always_inline
+#else
+# define NOKPROBE_SYMBOL(fname)
+# define __kprobes
+# define nokprobe_inline	inline
+#endif
+#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
+
+#endif /* _SANDBOX_ASM_GENERIC_KPROBES_H */
diff --git a/tools/linker-tables/include/linux/bitops.h b/tools/linker-tables/include/linux/bitops.h
new file mode 100644
index 000000000000..2960e8089ebc
--- /dev/null
+++ b/tools/linker-tables/include/linux/bitops.h
@@ -0,0 +1,6 @@
+#ifndef _LINUX_BITOPS_H
+#define _LINUX_BITOPS_H
+
+#define BIT(nr)		(1UL << (nr))
+
+#endif /* _LINUX_BITOPS_H */
diff --git a/tools/linker-tables/include/linux/init.h b/tools/linker-tables/include/linux/init.h
new file mode 100644
index 000000000000..2eeca40fd97d
--- /dev/null
+++ b/tools/linker-tables/include/linux/init.h
@@ -0,0 +1,40 @@
+#ifndef _SANDBOX_LINUX_INIT_H
+#define _SANDBOX_LINUX_INIT_H
+
+#include_next <linux/init.h>
+#include <linux/types.h>
+#include <linux/sections.h>
+
+#define __init	__section(SECTION_INIT)
+#define __exit	__section(SECTION_EXIT)
+
+#ifndef __ASSEMBLY__
+#include <linux/tables.h>
+typedef int (*initcall_t)(void);
+typedef void (*exitcall_t)(void);
+
+DECLARE_LINKTABLE(initcall_t, init_calls);
+DECLARE_LINKTABLE(exitcall_t, exit_calls);
+
+#define __define_initcall(fn, id)					\
+	static LINKTABLE_INIT_DATA(init_calls, id)			\
+	__initcall_##fn##id = fn
+
+#define pure_initcall(fn)			__define_initcall(fn, 0)
+#define core_initcall(fn)			__define_initcall(fn, 1)
+#define postcore_initcall(fn)			__define_initcall(fn, 2)
+#define arch_initcall(fn)			__define_initcall(fn, 3)
+#define subsys_initcall(fn)			__define_initcall(fn, 4)
+#define fs_initcall(fn)				__define_initcall(fn, 5)
+#define device_initcall(fn)			__define_initcall(fn, 6)
+#define late_initcall(fn)			__define_initcall(fn, 7)
+
+#define __initcall(fn)				device_initcall(fn)
+
+#define __exitcall(fn)							\
+	static LINKTABLE_INIT_DATA(exit_calls, SECTION_ORDER_ANY)	\
+	__exitcall_##fn = fn;
+
+#endif
+
+#endif /* _SANDBOX_LINUX_INIT_H */
diff --git a/tools/linker-tables/include/linux/kasan.h b/tools/linker-tables/include/linux/kasan.h
new file mode 100644
index 000000000000..41791187854e
--- /dev/null
+++ b/tools/linker-tables/include/linux/kasan.h
@@ -0,0 +1,5 @@
+#include <linux/types.h>
+
+void kasan_early_init(void);
+int kasan_init(void);
+bool is_kasan_setup(void);
diff --git a/tools/linker-tables/include/linux/kprobes.h b/tools/linker-tables/include/linux/kprobes.h
new file mode 100644
index 000000000000..ecd5a0a69ae6
--- /dev/null
+++ b/tools/linker-tables/include/linux/kprobes.h
@@ -0,0 +1,11 @@
+#ifndef _SANDBOX_LINUX_KPROBES_H
+#define _SANDBOX_LINUX_KPROBES_H
+
+#include <asm/kprobes.h>
+#include <linux/ranges.h>
+
+#ifdef CONFIG_KPROBES
+DECLARE_SECTION_RANGE(kprobes);
+#endif
+
+#endif /* _SANDBOX_LINUX_KPROBES_H */
diff --git a/tools/linker-tables/include/linux/module.h b/tools/linker-tables/include/linux/module.h
new file mode 100644
index 000000000000..b59e55f3f04e
--- /dev/null
+++ b/tools/linker-tables/include/linux/module.h
@@ -0,0 +1,14 @@
+#ifndef _LINUX_MODULE_H
+#define _LINUX_MODULE_H
+
+#include <linux/init.h>
+
+#define module_init(x)  __initcall(x);
+#define module_exit(x)  __exitcall(x);
+
+struct module {
+	int (*init)(void);
+	void (*exit)(void);
+};
+
+#endif /* _LINUX_MODULE_H */
diff --git a/tools/linker-tables/include/linux/mutex.h b/tools/linker-tables/include/linux/mutex.h
new file mode 100644
index 000000000000..a74f951ceb42
--- /dev/null
+++ b/tools/linker-tables/include/linux/mutex.h
@@ -0,0 +1,17 @@
+#ifndef __LINUX_MUTEX_H
+#define __LINUX_MUTEX_H
+
+#include <sys/types.h>
+#include <linux/sched.h>
+#include <pthread.h>
+
+struct mutex {
+	pthread_mutex_t lock;
+};
+
+void mutex_init(struct mutex *lock);
+void mutex_destroy(struct mutex *lock);
+void mutex_lock(struct mutex *lock);
+void mutex_unlock(struct mutex *lock);
+
+#endif /* __LINUX_MUTEX_H */
diff --git a/tools/linker-tables/include/linux/pci.h b/tools/linker-tables/include/linux/pci.h
new file mode 100644
index 000000000000..8518c46631f7
--- /dev/null
+++ b/tools/linker-tables/include/linux/pci.h
@@ -0,0 +1,7 @@
+#include <linux/types.h>
+
+struct pci_fixup {
+	void (*hook)(void);
+};
+
+bool detect_pci(void);
diff --git a/tools/linker-tables/include/linux/ps_const.h b/tools/linker-tables/include/linux/ps_const.h
new file mode 100644
index 000000000000..5eab3a124e00
--- /dev/null
+++ b/tools/linker-tables/include/linux/ps_const.h
@@ -0,0 +1,46 @@
+#ifndef __PS_CONST
+#define __PS_CONST
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/tables.h>
+
+/* Helpers for partially static settings */
+
+enum ps_static_type {
+	SET_CONST_U8 = 0,
+	SET_CONST_U16,
+	SET_CONST_U32,
+};
+
+struct ps_set_const {
+	unsigned int *count;
+	enum ps_static_type type;
+	unsigned int (*func)(void);
+};
+
+DECLARE_LINKTABLE(struct ps_set_const, ps_set_const_table);
+
+#ifdef CONFIG_HAVE_ARCH_PS_CONST
+#include <asm/ps_const.h>
+#endif
+
+/*
+ * ps_ stands for "partially static", so we "partialloy static shift right"
+ * You can optimize this for your architecture.
+ *
+ * ps_shr(unsigned int in, unsigned char (*func)(void))
+ */
+#ifndef ps_shr
+#define ps_shr(_in, _func)						\
+({									\
+	static unsigned int _count;					\
+	static LINKTABLE_INIT_DATA(ps_set_const_table, 01)		\
+		__ps_shr##__func =					\
+		{ &_count, SET_CONST_U8, (_func) };			\
+									\
+	(_in) >> _count;						\
+})
+#endif /* ps_shr */
+
+#endif /* __PS_CONST */
diff --git a/tools/linker-tables/include/linux/sched.h b/tools/linker-tables/include/linux/sched.h
new file mode 100644
index 000000000000..63db7da0e8e4
--- /dev/null
+++ b/tools/linker-tables/include/linux/sched.h
@@ -0,0 +1,9 @@
+#ifndef _LINUX_SCHED_H
+#define _LINUX_SCHED_H
+
+#include <linux/ranges.h>
+
+DECLARE_SECTION_RANGE(sched_text);
+#define __sched		__LINUX_RANGE(SECTION_TEXT, sched_text)
+
+#endif /* _LINUX_SCHED_H */
diff --git a/tools/linker-tables/include/linux/spinlock.h b/tools/linker-tables/include/linux/spinlock.h
new file mode 100644
index 000000000000..e62bc3bc5e6a
--- /dev/null
+++ b/tools/linker-tables/include/linux/spinlock.h
@@ -0,0 +1,13 @@
+#ifndef __LINUX_SPINLOCK_H
+#define __LINUX_SPINLOCK_H
+
+#include <pthread.h>
+
+#define spinlock_t pthread_spinlock_t
+
+void spin_lock_init(spinlock_t *lock);
+void spin_lock_destroy(spinlock_t *lock);
+void spin_lock(spinlock_t *lock);
+void spin_unlock(spinlock_t *lock);
+
+#endif /* __LINUX_SPINLOCK_H */
diff --git a/tools/linker-tables/include/linux/start_kernel.h b/tools/linker-tables/include/linux/start_kernel.h
new file mode 100644
index 000000000000..5c2cb9a5cb0c
--- /dev/null
+++ b/tools/linker-tables/include/linux/start_kernel.h
@@ -0,0 +1 @@
+int start_kernel(void);
diff --git a/tools/linker-tables/include/linux/types.h b/tools/linker-tables/include/linux/types.h
new file mode 100644
index 000000000000..3fc87b2c84e2
--- /dev/null
+++ b/tools/linker-tables/include/linux/types.h
@@ -0,0 +1,13 @@
+#ifndef __LINUX_USER_TYPES_H
+#define __LINUX_USER_TYPES_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+typedef unsigned char __u8;
+typedef unsigned short __u16;
+typedef unsigned int __u32;
+
+#endif /* __LINUX_USER_TYPES_H */
diff --git a/tools/linker-tables/include/linux/workqueue.h b/tools/linker-tables/include/linux/workqueue.h
new file mode 100644
index 000000000000..69e1c6de5051
--- /dev/null
+++ b/tools/linker-tables/include/linux/workqueue.h
@@ -0,0 +1,51 @@
+#ifndef _LINUX_WORKQUEUE_H
+#define _LINUX_WORKQUEUE_H
+
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <pthread.h>
+
+struct work {
+	bool ready;
+
+	pthread_t thread;
+	struct mutex mutex;
+	pthread_cond_t cond;
+
+	void *arg;
+	void *(*work_cb)(void *arg);
+};
+
+#define DECLARE_WORK(_w, _w_cb) \
+struct work _w = { \
+	.work_cb = _w_cb, \
+	.arg = NULL, \
+};
+
+extern void *run_work(void *arg);
+
+static inline void init_work(struct work *w)
+{
+	w->ready = false;
+
+	mutex_init(&w->mutex);
+	pthread_cond_init(&w->cond, NULL);
+
+	pthread_create(&w->thread, NULL, run_work, (void *) w);
+
+	while (1) {
+		mutex_lock(&w->mutex);
+		if (w->ready) {
+			pthread_mutex_unlock(&w->mutex.lock);
+			break;
+		}
+		mutex_unlock(&w->mutex);
+	}
+}
+
+void schedule_work(struct work *w);
+void cancel_work_sync(struct work *w);
+void init_work(struct work *w);
+
+#endif /* _LINUX_WORKQUEUE_H */
diff --git a/tools/linker-tables/include/xen/xen.h b/tools/linker-tables/include/xen/xen.h
new file mode 100644
index 000000000000..782c799a0064
--- /dev/null
+++ b/tools/linker-tables/include/xen/xen.h
@@ -0,0 +1,4 @@
+#include <linux/types.h>
+
+bool booting_xen(void);
+int startup_xen(void);
diff --git a/tools/linker-tables/kernel/locking/mutex.c b/tools/linker-tables/kernel/locking/mutex.c
new file mode 100644
index 000000000000..131097fccd13
--- /dev/null
+++ b/tools/linker-tables/kernel/locking/mutex.c
@@ -0,0 +1,28 @@
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+
+DEFINE_SECTION_RANGE(sched_text, SECTION_TEXT);
+
+void __sched mutex_init(struct mutex *lock)
+{
+	int r;
+
+	r = pthread_mutex_init(&lock->lock, NULL);
+	if (r)
+		BUG_ON(r);
+}
+
+void __sched mutex_destroy(struct mutex *lock)
+{
+	pthread_mutex_destroy(&lock->lock);
+}
+
+void __sched mutex_lock(struct mutex *lock)
+{
+	pthread_mutex_lock(&lock->lock);
+}
+
+void __sched mutex_unlock(struct mutex *lock)
+{
+	pthread_mutex_unlock(&lock->lock);
+}
diff --git a/tools/linker-tables/kernel/locking/spinlock.c b/tools/linker-tables/kernel/locking/spinlock.c
new file mode 100644
index 000000000000..5be2bc7cdece
--- /dev/null
+++ b/tools/linker-tables/kernel/locking/spinlock.c
@@ -0,0 +1,26 @@
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+
+void spin_lock_init(spinlock_t *lock)
+{
+	int r;
+
+	r = pthread_spin_init(lock, PTHREAD_PROCESS_SHARED);
+	if (r)
+		BUG_ON(r);
+}
+
+void spin_lock_destroy(spinlock_t *lock)
+{
+	pthread_spin_destroy(lock);
+}
+
+void spin_lock(spinlock_t *lock)
+{
+	pthread_spin_lock(lock);
+}
+
+void spin_unlock(spinlock_t *lock)
+{
+	pthread_spin_unlock(lock);
+}
diff --git a/tools/linker-tables/kernel/main.c b/tools/linker-tables/kernel/main.c
new file mode 100644
index 000000000000..f3826cdb2ca8
--- /dev/null
+++ b/tools/linker-tables/kernel/main.c
@@ -0,0 +1,32 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/x86_init_fn.h>
+#include <asm/x86.h>
+
+DEFINE_LINKTABLE_INIT_DATA(initcall_t, init_calls);
+
+int do_one_initcall(initcall_t fn)
+{
+	int ret;
+
+	ret = fn();
+
+	return ret;
+}
+
+static void do_initcalls(void)
+{
+	initcall_t *fn;
+
+	 LINKTABLE_FOR_EACH(fn, init_calls)
+		 do_one_initcall(*fn);
+}
+
+void start_kernel(void)
+{
+	pr_info("Calling start_kernel()...\n");
+
+	setup_arch();
+	late_init();
+	do_initcalls();
+}
diff --git a/tools/linker-tables/kernel/workqueue.c b/tools/linker-tables/kernel/workqueue.c
new file mode 100644
index 000000000000..5ba73c7e7c8b
--- /dev/null
+++ b/tools/linker-tables/kernel/workqueue.c
@@ -0,0 +1,43 @@
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <linux/workqueue.h>
+#include <linux/kernel.h>
+
+void schedule_work(struct work *w)
+{
+	mutex_lock(&w->mutex);
+	pthread_cond_signal(&w->cond);
+	mutex_unlock(&w->mutex);
+}
+
+void cancel_work_sync(struct work *w)
+{
+	pthread_exit(NULL);
+}
+
+void *run_work(void *arg)
+{
+	struct work *w;
+	int r;
+
+	w = (struct work *) arg;
+
+	mutex_lock(&w->mutex);
+
+	while (true) {
+		if (!w->ready)
+			w->ready = true;
+		r = pthread_cond_wait(&w->cond, &w->mutex.lock);
+		if (r != 0) {
+			printf("(%s)\n", strerror(r));
+			BUG_ON(r);
+		}
+		w->work_cb(w->arg);
+	}
+
+	mutex_unlock(&w->mutex);
+
+	pthread_exit(NULL);
+}
diff --git a/tools/linker-tables/lib/string.c b/tools/linker-tables/lib/string.c
new file mode 100644
index 000000000000..95631c742f1d
--- /dev/null
+++ b/tools/linker-tables/lib/string.c
@@ -0,0 +1,26 @@
+/*
+ *  linux/lib/string.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  Licensed under GPLv2 - taken from linux-next next-20160803
+ */
+
+#include <linux/kernel.h>
+
+/**
+ * memset - Fill a region of memory with the given value
+ * @s: Pointer to the start of the area.
+ * @c: The byte to fill the area with
+ * @count: The size of the area.
+ *
+ * Do not use memset() to access IO space, use memset_io() instead.
+ */
+void *memset(void *s, int c, size_t count)
+{
+	char *xs = s;
+
+	while (count--)
+		*xs++ = c;
+	return s;
+}
diff --git a/tools/linker-tables/main.c b/tools/linker-tables/main.c
new file mode 100644
index 000000000000..c0b1f4c95112
--- /dev/null
+++ b/tools/linker-tables/main.c
@@ -0,0 +1,20 @@
+#include <linux/string.h>
+#include <xen/xen.h>
+#include <asm/x86.h>
+#include <asm/bootparam.h>
+
+struct boot_params boot_params __attribute__((aligned(16)));
+
+int main(int arg, char *argc[])
+{
+	memset(&boot_params, 0, sizeof(struct boot_params));
+
+	if (arg <= 1)
+		startup_64();
+	else {
+		boot_params.hdr.hardware_subarch = X86_SUBARCH_XEN;
+		startup_xen();
+	}
+
+	return 0;
+}
diff --git a/tools/linker-tables/pci-quirks.c b/tools/linker-tables/pci-quirks.c
new file mode 100644
index 000000000000..2cd1116dd0fc
--- /dev/null
+++ b/tools/linker-tables/pci-quirks.c
@@ -0,0 +1,13 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <linux/pci.h>
+
+DEFINE_LINKTABLE_RO(struct pci_fixup, pci_fixup_early);
+
+static void foo_fixup(void) {
+	pr_info("foo_fixup\n");
+};
+
+LINKTABLE_RO(pci_fixup_early, 50) quirk_foo = {
+	.hook = foo_fixup,
+};
diff --git a/tools/linker-tables/pci.c b/tools/linker-tables/pci.c
new file mode 100644
index 000000000000..d2a57701290d
--- /dev/null
+++ b/tools/linker-tables/pci.c
@@ -0,0 +1,29 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <asm/bootparam.h>
+#include <linux/pci.h>
+
+DECLARE_LINKTABLE(struct pci_fixup, pci_fixup_early);
+
+void early_init_pci(void) {
+
+	const struct pci_fixup *fixup;
+	unsigned int tbl_size = LINUX_SECTION_SIZE(pci_fixup_early);
+
+	pr_info("Initializing pci ...\n");
+
+	pr_info("PCI fixup size: %d\n", tbl_size);
+
+	sleep(1);
+	pr_info("Demo: Using LINKTABLE_FOR_EACH\n");
+	LINKTABLE_FOR_EACH(fixup, pci_fixup_early)
+		fixup->hook();
+
+	pr_info("Demo: Using LINKTABLE_RUN_ALL\n");
+	LINKTABLE_RUN_ALL(pci_fixup_early, hook,);
+
+	pr_info("Completed initializing pci !\n");
+}
+
+x86_init_early_all(early_init_pci);
-- 
2.9.2


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
  2016-08-19 21:32   ` mcgrof
  (?)
  (?)
@ 2016-08-19 21:47   ` Kees Cook
  2016-08-22 23:13     ` Luis R. Rodriguez
  -1 siblings, 1 reply; 480+ messages in thread
From: Kees Cook @ 2016-08-19 21:47 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: gnomes, linux-ia64, Jiri Kosina, benh, Ming Lei, Heiko Carstens,
	platform-driver-x86, James Bottomley, Paul Gortmaker,
	Paul Mackerras, Michael Ellerman, H. Peter Anvin,
	Masami Hiramatsu, Mauro Carvalho Chehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, Russell King - ARM Linux,
	linux-sh, Will Deacon

On Fri, Aug 19, 2016 at 2:32 PM,  <mcgrof@kernel.org> wrote:
> From: "Luis R. Rodriguez" <mcgrof@kernel.org>
>
> Linux makes extensive use of custom ELF header sections,
> documentation for these are well scatterred. Unify this
> documentation in a central place and provide helpers to
> build custom Linux sections.
>
> This also generalizes sections code to enable avoiding
> modifying the linker scripts when we want to add new
> custom Linux sections. In order to make this generally
> useful we need to ensure all architectures can make use of
> core section helpers but that they can also override should
> this be needed. Instead of relying on section.h this adds
> a sections-core.h since this will be targetted to be safe
> to be used on asm code, linker scripts and C code.
>
> v4:
>
> o Port to shiny new sphinx documentation format
>
> o fix a unicore32 build, turns out this actually fixes unicore32
>   defconfig builds which were failing for a long while. unicore32
>   does not seem to grok well the type passed on a section declaration,
>   this ignores it.
>
> o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
>   this was causing final linker issues with blackfin -- this is
>   a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
>   being metatag. metatag is not supported on 0-day so I cannot confirm
>   compilation there.
>
> o Added SECTION_CORE() for C code, used later by __LINUX_RANGE()
>
> o Since SECTION_CORE() is defined for linker script and C code, share
>   the same helper and just use a __stringify() for the C code as is done
>   for the other C helpers.
>
> o move generic sections to asm-generic/section-core.h instead.
>   PowerPC compilation blows up if asm/jump_labels.h gets
>   section.h included, fixing this is not in any way easy.
>   The list of issues are endless. Moving new data to a new
>   simple file resolves this.
>
> o since things are now in asm-generic/section-core.h the
>   guard changes on asm-generic/sections.h and each architecture
>   sections.h are no longer needed
>
> o Give generic sections some maintainer love, that change is
>   Acked-by Arnd Bergmann, Josh and hpa.
>
> o A few checkpatch.pl style fixes
>
> o As suggested by James Hogan use generic-y to copy generic
>   header files on architectures that do not have a sections.h
>   instead of writing a simple file only to include the generic one.
>
> v3:
>
> o add missing sections.h for architectures that did not
>   have it
>
> o move generic sections to asm-generic/sections.h
>
> o add generic asm helpers section_type(), section_type_asmtype(),
>   push_section_type() -- these helpers enable easy use for
>   for later declaring and using of custom linux sections using
>   more standard APIs in both C code, asm code (C asm calls, or
>   asm files), enabling future standardized section types to
>   be more immediately accessible to asm code, not just C code.
>   Note for ASM_CMD_SEP we use by default "\n", architectures needed
>   to override can do so on their own sections.h prior to inclusion
>   of asm-generic/sections.h
>
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  Documentation/index.rst                   |   1 +
>  Documentation/sections/conf.py            |   4 +
>  Documentation/sections/index.rst          |  11 +
>  Documentation/sections/section-core.rst   | 153 ++++++++++++++
>  MAINTAINERS                               |  14 ++
>  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/Kbuild               |   1 +
>  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/section-core.h |  19 ++
>  arch/x86/include/asm/Kbuild               |   1 +
>  arch/xtensa/include/asm/Kbuild            |   1 +
>  include/asm-generic/section-core.h        | 341 ++++++++++++++++++++++++++++++
>  include/asm-generic/sections.h            |   2 +
>  include/asm-generic/vmlinux.lds.h         |  27 +--
>  include/linux/sections.h                  | 111 ++++++++++
>  40 files changed, 700 insertions(+), 13 deletions(-)
>  create mode 100644 Documentation/sections/conf.py
>  create mode 100644 Documentation/sections/index.rst
>  create mode 100644 Documentation/sections/section-core.rst
>  create mode 100644 arch/unicore32/include/asm/section-core.h
>  create mode 100644 include/asm-generic/section-core.h
>  create mode 100644 include/linux/sections.h
>
> diff --git a/Documentation/index.rst b/Documentation/index.rst
> index a15f81855b39..10c9b867e326 100644
> --- a/Documentation/index.rst
> +++ b/Documentation/index.rst
> @@ -14,6 +14,7 @@ Contents:
>     kernel-documentation
>     media/index
>     gpu/index
> +   sections/index
>
>  Indices and tables
>  ==================
> diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
> new file mode 100644
> index 000000000000..faa1c57595e1
> --- /dev/null
> +++ b/Documentation/sections/conf.py
> @@ -0,0 +1,4 @@
> +# -*- coding: utf-8; mode: python -*-
> +
> +project = 'Linux Kernel ELF sections'
> +html_search_language = 'en'
> diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
> new file mode 100644
> index 000000000000..d411e9b22eb3
> --- /dev/null
> +++ b/Documentation/sections/index.rst
> @@ -0,0 +1,11 @@
> +=========================
> +Linux Kernel ELF sections
> +=========================
> +
> +This book documents the Linux kernel's use of ELF sections, as well as helpers
> +used throughout the kernel to help declare and define them.
> +
> +.. toctree::
> +   :maxdepth: 4
> +
> +   section-core
> diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
> new file mode 100644
> index 000000000000..ecf4228bc4f8
> --- /dev/null
> +++ b/Documentation/sections/section-core.rst
> @@ -0,0 +1,153 @@
> +==============================
> +Core Linux kernel ELF sections
> +==============================
> +
> +About
> +=====
> +
> +This book documents the different standard and custom ELF sections used
> +on the Linux kernel, which we refer to as the ``core Linux sections``. We
> +start off by documenting the standard ELF sections used by Linux and move
> +on to the basic custom ELF sections, followed by a set of helpers. Each
> +section documented describes the goal of the section, and addresses
> +concurrency considerations when applicable.
> +
> +.. kernel-doc:: include/asm-generic/section-core.h
> +   :doc: Custom linker script
> +
> +Standard ELF section use in Linux
> +=================================
> +
> +.. kernel-doc:: include/asm-generic/section-core.h
> +   :doc: Standard ELF section use in Linux
> +
> +SECTION_RODATA
> +--------------
> +.. kernel-doc:: include/asm-generic/section-core.h
> +   :doc: SECTION_RODATA
> +
> +SECTION_RODATA

Typo: should this be called SECTION_TEXT instead?

> +--------------
> +.. kernel-doc:: include/asm-generic/section-core.h
> +   :doc: SECTION_TEXT
> +
> +SECTION_DATA
> +------------
> +.. kernel-doc:: include/asm-generic/section-core.h
> +   :doc: SECTION_DATA

Missing from this list are things like the __read_mostly
(".data..read_mostly") and __ro_after_init (".data..ro_after_init")
sections. Should those be included too, or are you only doing the "top
level" sections?

-Kees

-- 
Kees Cook
Nexus Security

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 06/16] ranges.h: add helpers to build and identify Linux section ranges
  2016-08-19 21:32   ` mcgrof
  (?)
  (?)
@ 2016-08-19 21:55   ` Kees Cook
  2016-08-22 23:48     ` Luis R. Rodriguez
  -1 siblings, 1 reply; 480+ messages in thread
From: Kees Cook @ 2016-08-19 21:55 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: gnomes, linux-ia64, Jiri Kosina, benh, Ming Lei, Heiko Carstens,
	platform-driver-x86, James Bottomley, Paul Gortmaker,
	Paul Mackerras, Michael Ellerman, H. Peter Anvin,
	Masami Hiramatsu, Mauro Carvalho Chehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, Russell King - ARM Linux,
	linux-sh, Will Deacon

On Fri, Aug 19, 2016 at 2:32 PM,  <mcgrof@kernel.org> wrote:
> From: "Luis R. Rodriguez" <mcgrof@kernel.org>
>
> Section ranges are on one of the types of custom sections
> types used in Linux. This provides a series of helpers for
> defining them and using them. Most importantly this also
> enables us to avoid modifying the linker script when we
> add a new section range.
>
> It turns out a lot of custom sections are actually section ranges,
> and these are typically spelled out in their architecture specific
> asm/sections.h file -- we anable architectures to override what asm

Typo: anable -> enable

> is used for section ranges but start by default trusting the
> asm-generic version all around.

Can you explain the addition of the SORT() stuff in this patch? Its
purpose isn't clear to me and doesn't appear to be mentioned in the
commit log.

>
> v4:
>
> o tons of documentation love
> o fix arch/x86/tools/relocs.c typo - which caused compilation issues
>   on old toolchains
> o port to new shiny sphinx documentation
> o sprinkle a few more needed VMLINUX_SYMBOL() - fixes
>   compilation on blackfin
> o name changes as suggested 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
> - rebrand DECLARE_SECTION_RNG() as DEFINE_SECTION_RANGE() - this is
>   the asm version of the respective C version, this will have a
>   userspace C demo added later.
> o move __LINUX_RANGE() and __LINUX_RANGE_ORDER() - fixes builds
>   on sparc
> o adds section ranges to linker script
> o rename SECTION_RANGE_ALL()
> o use default alignment, fixes builds on powerpc and arm for both
>   __LINUX_RANGE() and __LINUX_RANGE_ORDER()
> o expand documentation to document modules support
> o add maintainers
> o use generic-y
>
> v3: new in this series, uses copyleft-next
>
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  Documentation/sections/index.rst   |   1 +
>  Documentation/sections/ranges.rst  |  49 ++++++++++++++
>  MAINTAINERS                        |  10 +++
>  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/Kbuild        |   1 +
>  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       |  89 ++++++++++++++++++++++++++
>  include/asm-generic/vmlinux.lds.h  |  12 +++-
>  include/linux/ranges.h             | 128 +++++++++++++++++++++++++++++++++++++
>  38 files changed, 320 insertions(+), 2 deletions(-)
>  create mode 100644 Documentation/sections/ranges.rst
>  create mode 100644 include/asm-generic/ranges.h
>  create mode 100644 include/linux/ranges.h
>
> diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
> index d411e9b22eb3..6dd93ddd5dbe 100644
> --- a/Documentation/sections/index.rst
> +++ b/Documentation/sections/index.rst
> @@ -9,3 +9,4 @@ used throughout the kernel to help declare and define them.
>     :maxdepth: 4
>
>     section-core
> +   ranges
> diff --git a/Documentation/sections/ranges.rst b/Documentation/sections/ranges.rst
> new file mode 100644
> index 000000000000..1293dcb3ab38
> --- /dev/null
> +++ b/Documentation/sections/ranges.rst
> @@ -0,0 +1,49 @@
> +====================
> +Linux section ranges
> +====================
> +
> +This documents Linux' use of section ranges, how you can use
> +them and how they work.
> +
> +About section ranges
> +====================
> +
> +Introduction
> +------------
> +.. kernel-doc:: include/linux/ranges.h
> +   :doc: Introduction
> +
> +Section range module support
> +----------------------------
> +.. kernel-doc:: include/linux/ranges.h
> +   :doc: Section range module support
> +
> +Section range helpers
> +=====================
> +.. kernel-doc:: include/linux/ranges.h
> +   :doc: Section range helpers
> +
> +DECLARE_SECTION_RANGE
> +---------------------
> +.. kernel-doc:: include/linux/ranges.h
> +   :functions: DECLARE_SECTION_RANGE
> +
> +DEFINE_SECTION_RANGE
> +--------------------
> +.. kernel-doc:: include/linux/ranges.h
> +   :functions: DEFINE_SECTION_RANGE
> +
> +SECTION_ADDR_IN_RANGE
> +---------------------
> +.. kernel-doc:: include/linux/ranges.h
> +   :functions: SECTION_ADDR_IN_RANGE
> +
> +__LINUX_RANGE
> +-------------
> +.. kernel-doc:: include/asm-generic/ranges.h
> +   :functions: __LINUX_RANGE
> +
> +__LINUX_RANGE_ORDER
> +-------------------
> +.. kernel-doc:: include/asm-generic/ranges.h
> +   :functions: __LINUX_RANGE_ORDER
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 689c12075842..1a217751aa8a 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -5217,6 +5217,16 @@ S:       Supported
>  F:     drivers/base/power/domain*.c
>  F:     include/linux/pm_domain.h
>
> +GENERIC SECTION RANGES
> +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
> +S:     Supported
> +F:     include/asm-generic/ranges.h
> +F:     include/linux/ranges.h
> +F:     Documentation/sections/ranges.rst
> +
>  GENERIC SECTIONS
>  M:     "Luis R. Rodriguez" <mcgrof@kernel.org>
>  M:     Josh Poimboeuf <jpoimboe@redhat.com>
> diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
> index 5422827f1585..e44c896b91c4 100644
> --- a/arch/alpha/include/asm/Kbuild
> +++ b/arch/alpha/include/asm/Kbuild
> @@ -11,3 +11,4 @@ generic-y += preempt.h
>  generic-y += sections.h
>  generic-y += trace_clock.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
> index 9a0929576de1..e5295413fdf8 100644
> --- a/arch/arc/include/asm/Kbuild
> +++ b/arch/arc/include/asm/Kbuild
> @@ -51,3 +51,4 @@ generic-y += vga.h
>  generic-y += word-at-a-time.h
>  generic-y += xor.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
> index 47923635be16..8e52300e1eed 100644
> --- a/arch/arm/include/asm/Kbuild
> +++ b/arch/arm/include/asm/Kbuild
> @@ -40,3 +40,4 @@ generic-y += timex.h
>  generic-y += trace_clock.h
>  generic-y += unaligned.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
> index 42d00806e4fb..5ff184574976 100644
> --- a/arch/arm64/include/asm/Kbuild
> +++ b/arch/arm64/include/asm/Kbuild
> @@ -53,3 +53,4 @@ generic-y += user.h
>  generic-y += vga.h
>  generic-y += xor.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
> index f2c3b656a0e7..edc176348d7c 100644
> --- a/arch/avr32/include/asm/Kbuild
> +++ b/arch/avr32/include/asm/Kbuild
> @@ -23,3 +23,4 @@ generic-y += vga.h
>  generic-y += word-at-a-time.h
>  generic-y += xor.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
> index 7de674411bed..35b7752e65c0 100644
> --- a/arch/blackfin/include/asm/Kbuild
> +++ b/arch/blackfin/include/asm/Kbuild
> @@ -49,3 +49,4 @@ generic-y += user.h
>  generic-y += word-at-a-time.h
>  generic-y += xor.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
> index 38127ce747be..cede2a950fbf 100644
> --- a/arch/c6x/include/asm/Kbuild
> +++ b/arch/c6x/include/asm/Kbuild
> @@ -63,3 +63,4 @@ generic-y += vga.h
>  generic-y += word-at-a-time.h
>  generic-y += xor.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
> index 385cd88a9d9e..fb8bb4112773 100644
> --- a/arch/cris/include/asm/Kbuild
> +++ b/arch/cris/include/asm/Kbuild
> @@ -46,3 +46,4 @@ generic-y += vga.h
>  generic-y += word-at-a-time.h
>  generic-y += xor.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
> index 46d7c599d9b8..5191fec655d7 100644
> --- a/arch/frv/include/asm/Kbuild
> +++ b/arch/frv/include/asm/Kbuild
> @@ -9,3 +9,4 @@ generic-y += preempt.h
>  generic-y += trace_clock.h
>  generic-y += word-at-a-time.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
> index 1ec04ec1c82b..7929a992566c 100644
> --- a/arch/h8300/include/asm/Kbuild
> +++ b/arch/h8300/include/asm/Kbuild
> @@ -76,3 +76,4 @@ generic-y += vga.h
>  generic-y += word-at-a-time.h
>  generic-y += xor.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
> index 37d7bfae7619..af17ee334788 100644
> --- a/arch/hexagon/include/asm/Kbuild
> +++ b/arch/hexagon/include/asm/Kbuild
> @@ -61,3 +61,4 @@ generic-y += vga.h
>  generic-y += word-at-a-time.h
>  generic-y += xor.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
> index 672c6d5da18c..d8f226b35a0a 100644
> --- a/arch/ia64/include/asm/Kbuild
> +++ b/arch/ia64/include/asm/Kbuild
> @@ -10,3 +10,4 @@ generic-y += trace_clock.h
>  generic-y += vtime.h
>  generic-y += word-at-a-time.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
> index 6111e1523750..1c6504d29312 100644
> --- a/arch/m32r/include/asm/Kbuild
> +++ b/arch/m32r/include/asm/Kbuild
> @@ -12,3 +12,4 @@ generic-y += sections.h
>  generic-y += trace_clock.h
>  generic-y += word-at-a-time.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
> index eef72c464c9b..d465f51c2088 100644
> --- a/arch/m68k/include/asm/Kbuild
> +++ b/arch/m68k/include/asm/Kbuild
> @@ -36,3 +36,4 @@ generic-y += types.h
>  generic-y += word-at-a-time.h
>  generic-y += xor.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
> index 50ebd5a30d16..c869b1ebd583 100644
> --- a/arch/metag/include/asm/Kbuild
> +++ b/arch/metag/include/asm/Kbuild
> @@ -57,3 +57,4 @@ generic-y += vga.h
>  generic-y += word-at-a-time.h
>  generic-y += xor.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
> index c6c2cf6edc98..63c083a1f8da 100644
> --- a/arch/microblaze/include/asm/Kbuild
> +++ b/arch/microblaze/include/asm/Kbuild
> @@ -12,3 +12,4 @@ generic-y += syscalls.h
>  generic-y += trace_clock.h
>  generic-y += word-at-a-time.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
> index 12f7c5984c03..ed225600c8a4 100644
> --- a/arch/mips/include/asm/Kbuild
> +++ b/arch/mips/include/asm/Kbuild
> @@ -21,3 +21,4 @@ generic-y += user.h
>  generic-y += word-at-a-time.h
>  generic-y += xor.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
> index f8145bc85835..656af7b69940 100644
> --- a/arch/mn10300/include/asm/Kbuild
> +++ b/arch/mn10300/include/asm/Kbuild
> @@ -11,3 +11,4 @@ generic-y += sections.h
>  generic-y += trace_clock.h
>  generic-y += word-at-a-time.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
> index c9c7cb82b00f..c55880659d67 100644
> --- a/arch/nios2/include/asm/Kbuild
> +++ b/arch/nios2/include/asm/Kbuild
> @@ -64,3 +64,4 @@ generic-y += vga.h
>  generic-y += word-at-a-time.h
>  generic-y += xor.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
> index 86175e701869..7d6a704b808c 100644
> --- a/arch/openrisc/include/asm/Kbuild
> +++ b/arch/openrisc/include/asm/Kbuild
> @@ -72,3 +72,4 @@ generic-y += vga.h
>  generic-y += word-at-a-time.h
>  generic-y += xor.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
> index 6f43f33f0e0f..1a263a7158e2 100644
> --- a/arch/parisc/include/asm/Kbuild
> +++ b/arch/parisc/include/asm/Kbuild
> @@ -30,3 +30,4 @@ generic-y += vga.h
>  generic-y += word-at-a-time.h
>  generic-y += xor.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
> index b49fab7bab2f..065c6e84fb67 100644
> --- a/arch/powerpc/include/asm/Kbuild
> +++ b/arch/powerpc/include/asm/Kbuild
> @@ -8,3 +8,4 @@ generic-y += preempt.h
>  generic-y += rwsem.h
>  generic-y += vtime.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
> index 89e74b59f32d..3e8b95927cb5 100644
> --- a/arch/s390/include/asm/Kbuild
> +++ b/arch/s390/include/asm/Kbuild
> @@ -9,3 +9,4 @@ generic-y += preempt.h
>  generic-y += trace_clock.h
>  generic-y += word-at-a-time.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
> index f089a264cd38..f0cdb2cbca4d 100644
> --- a/arch/score/include/asm/Kbuild
> +++ b/arch/score/include/asm/Kbuild
> @@ -15,3 +15,4 @@ generic-y += xor.h
>  generic-y += serial.h
>  generic-y += word-at-a-time.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
> index 7b0356dca562..c9bb7932a3d1 100644
> --- a/arch/sh/include/asm/Kbuild
> +++ b/arch/sh/include/asm/Kbuild
> @@ -40,3 +40,4 @@ generic-y += trace_clock.h
>  generic-y += ucontext.h
>  generic-y += xor.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
> index d51b84d6b4b7..79664d10e63b 100644
> --- a/arch/sparc/include/asm/Kbuild
> +++ b/arch/sparc/include/asm/Kbuild
> @@ -23,3 +23,4 @@ generic-y += trace_clock.h
>  generic-y += types.h
>  generic-y += word-at-a-time.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
> index 7b8a652e43ae..951fa4be571d 100644
> --- a/arch/tile/include/asm/Kbuild
> +++ b/arch/tile/include/asm/Kbuild
> @@ -42,3 +42,4 @@ generic-y += trace_clock.h
>  generic-y += types.h
>  generic-y += xor.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
> index e9849834d55e..99be54949b99 100644
> --- a/arch/um/include/asm/Kbuild
> +++ b/arch/um/include/asm/Kbuild
> @@ -28,3 +28,4 @@ generic-y += trace_clock.h
>  generic-y += word-at-a-time.h
>  generic-y += xor.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
> index 256c45b3ae34..6c35905fe371 100644
> --- a/arch/unicore32/include/asm/Kbuild
> +++ b/arch/unicore32/include/asm/Kbuild
> @@ -64,3 +64,4 @@ generic-y += user.h
>  generic-y += vga.h
>  generic-y += word-at-a-time.h
>  generic-y += xor.h
> +generic-y += ranges.h
> diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
> index f6914a57bc16..f790756fdb48 100644
> --- a/arch/x86/include/asm/Kbuild
> +++ b/arch/x86/include/asm/Kbuild
> @@ -17,3 +17,4 @@ generic-y += early_ioremap.h
>  generic-y += mcs_spinlock.h
>  generic-y += mm-arch-hooks.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
> index 0c2fae8d929d..c215db049920 100644
> --- a/arch/x86/tools/relocs.c
> +++ b/arch/x86/tools/relocs.c
> @@ -68,6 +68,8 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
>         "__end_rodata|"
>         "__initramfs_start|"
>         "(jiffies|jiffies_64)|"
> +       ".rodata.rng.*|"
> +       ".init.text.rng.*|"
>  #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 81ca6816bd72..221b6b652500 100644
> --- a/arch/xtensa/include/asm/Kbuild
> +++ b/arch/xtensa/include/asm/Kbuild
> @@ -32,3 +32,4 @@ generic-y += trace_clock.h
>  generic-y += word-at-a-time.h
>  generic-y += xor.h
>  generic-y += section-core.h
> +generic-y += ranges.h
> diff --git a/include/asm-generic/ranges.h b/include/asm-generic/ranges.h
> new file mode 100644
> index 000000000000..74cd941aa2f8
> --- /dev/null
> +++ b/include/asm-generic/ranges.h
> @@ -0,0 +1,89 @@
> +#ifndef _ASM_GENERIC_RANGES_H_
> +#define _ASM_GENERIC_RANGES_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/.
> + */
> +#include <asm/section-core.h>
> +
> +#define SECTION_RNG(section, name)                                     \

I would really prefer to avoid shortening "range" to the acronym for
"random number generator". That's very confusing. :P It's only two
letters more...

> +       SECTION_CORE(section, rng, name,                                \
> +                    SECTION_ORDER_ANY)
> +
> +#define SECTION_RNG_LEVEL(section, name, level)                                \
> +       SECTION_CORE(section, rng, name, level)
> +
> +#define SECTION_RNG_ALL(section)                                       \
> +       SECTION_CORE_ALL(section,rng)
> +
> +#ifndef set_section_rng
> +# define set_section_rng(section, name, flags)                         \
> +        set_section_core(section, rng, name,                           \
> +                         SECTION_ORDER_ANY, flags)
> +#endif
> +
> +#ifndef set_section_rng_type
> +# define set_section_rng_type(section, name, flags, type)              \
> +        set_section_core_type(section, rng, name,                      \
> +                              SECTION_ORDER_ANY, flags, type)
> +#endif
> +
> +#ifndef set_section_rng_level
> +# define set_section_rng_level(section, name, level, flags)            \
> +        set_section_core(section, rng, name, level, flags)
> +#endif
> +
> +#ifndef push_section_rng
> +# define push_section_rng(section, name, flags)                                \
> +        push_section_core(section, rng, name,                          \
> +                          SECTION_ORDER_ANY, flags)
> +#endif
> +
> +#ifndef push_section_rng_level
> +# define push_section_rng_level(section, name, level, flags)           \
> +        push_section_core(section, rng, name,                          \
> +                          level, flags)
> +#endif
> +
> +#ifndef __ASSEMBLY__
> +/**
> + * __LINUX_RANGE - short hand association into a section range
> + *
> + * @section: ELF section name to place section range into
> + * @name: section range name
> + *
> + * This helper can be used by subsystems to define their own subsystem
> + * specific helpers to easily associate a piece of code being defined to a
> + * section range.
> + */
> +#define __LINUX_RANGE(section, name)                                   \
> +       __attribute__((__section__(SECTION_RNG(section, name))))
> +
> +/**
> + * __LINUX_RANGE_ORDER - short hand association into a section range of order
> + *
> + * @section: ELF section name to place section range into
> + * @name: section range name
> + * @level: order level, a number. The order level gets tucked into the
> + *     section as a postfix string. Order levels are sorted using
> + *     binutils SORT(), the number is sorted as a string, as such be
> + *     sure to fill with zeroes any empty digits. For instance if you are
> + *     using 3 levels of digits for order levels, use 001 for the first entry,
> + *     0002 for the second, 999 for the last entry. You can use however many
> + *     digits you need.
> + *
> + * This helper can be used by subsystems to define their own subsystem specific
> + * helpers to easily associate a piece of code being defined to a section range
> + * with an associated specific order level. The order level provides the
> + * ability for explicit user ordering of code. Sorting takes place at link
> + * time, after compilation.
> + */
> +#define __LINUX_RANGE_ORDER(section, name, level)                      \
> +       __attribute__((__section__(SECTION_RNG_LEVEL(section, name, level))))
> +
> +#endif /* __ASSEMBLY__ */
> +
> +#endif /* _ASM_GENERIC_RANGES_H_ */
> diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
> index 731087276a32..ad843555e6a4 100644
> --- a/include/asm-generic/vmlinux.lds.h
> +++ b/include/asm-generic/vmlinux.lds.h
> @@ -56,6 +56,7 @@
>
>  #include <linux/export.h>
>  #include <asm/section-core.h>
> +#include <asm/ranges.h>
>
>  /* Align . to a 8 byte boundary equals to maximum function alignment. */
>  #define ALIGN_FUNCTION()  . = ALIGN(8)
> @@ -200,6 +201,7 @@
>  /* .data section */
>  #define DATA_DATA                                                      \
>         *(SECTION_DATA)                                                 \
> +       *(SORT(SECTION_RNG_ALL(SECTION_DATA)))                          \
>         *(SECTION_REF_DATA)                                             \
>         *(.data..shared_aligned) /* percpu related */                   \
>         MEM_KEEP(init.data)                                             \
> @@ -265,7 +267,9 @@
>         . = ALIGN((align));                                             \
>         SECTION_RODATA    : AT(ADDR(SECTION_RODATA) - LOAD_OFFSET) {    \
>                 VMLINUX_SYMBOL(__start_rodata) = .;                     \
> -               *(SECTION_RODATA) *(SECTION_ALL(SECTION_RODATA))        \
> +               *(SECTION_RODATA)                                       \
> +               *(SORT(SECTION_RNG_ALL(SECTION_RODATA)))                \
> +               *(SECTION_ALL(SECTION_RODATA))                          \
>                 RO_AFTER_INIT_DATA      /* Read only after init */      \
>                 *(__vermagic)           /* Kernel version magic */      \
>                 . = ALIGN(8);                                           \
> @@ -433,7 +437,9 @@
>   * during second ld run in second ld pass when generating System.map */
>  #define TEXT_TEXT                                                      \
>                 ALIGN_FUNCTION();                                       \
> -               *(.text.hot SECTION_TEXT .text.fixup .text.unlikely)    \
> +               *(.text.hot SECTION_TEXT)                               \
> +               *(SORT(SECTION_RNG_ALL(SECTION_TEXT)))                  \
> +               *(.text.fixup .text.unlikely)                           \
>                 *(SECTION_REF)                                          \
>         MEM_KEEP(init.text)                                             \
>         MEM_KEEP(exit.text)                                             \
> @@ -529,6 +535,7 @@
>  /* init and exit section handling */
>  #define INIT_DATA                                                      \
>         *(SECTION_INIT_DATA)                                            \
> +       *(SORT(SECTION_RNG_ALL(SECTION_INIT_DATA)))                     \
>         MEM_DISCARD(init.data)                                          \
>         KERNEL_CTORS()                                                  \
>         MCOUNT_REC()                                                    \
> @@ -551,6 +558,7 @@
>
>  #define INIT_TEXT                                                      \
>         *(SECTION_INIT)                                                 \
> +       *(SORT(SECTION_RNG_ALL(SECTION_INIT)))                          \
>         *(.text.startup)                                                \
>         MEM_DISCARD(init.text)
>
> diff --git a/include/linux/ranges.h b/include/linux/ranges.h
> new file mode 100644
> index 000000000000..30b2182bd484
> --- /dev/null
> +++ b/include/linux/ranges.h
> @@ -0,0 +1,128 @@
> +#ifndef _LINUX_RANGES_H
> +#define _LINUX_RANGES_H
> +/*
> + * Linux section ranges
> + *
> + * 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/sections.h>
> +#include <asm/ranges.h>
> +
> +#ifndef __ASSEMBLY__
> +
> +/**
> + * DOC: Introduction
> + *
> + * A section ranges consists of explicitly annotated series executable code

Typo: ranges -> range

and "series of" instead of "series" I think?

> + * stitched together for the purpose of selective placement into standard or
> + * architecture specific ELF sections. What ELF section is used is utility
> + * specific. Linux has historically implicitly used section ranges, however
> + * they were all built in an adhoc manner and typically required linker script
> + * modifications per architecture. The section range API allows adding new
> + * bundles of stiched executable code into custom ELF sections by only
> + * modifying C or asm code in an architecture agnostic form.
> + *
> + * This documents the set of helpers available to declare, and define section
> + * ranges and associate each section range to a specific Linux ELF section.
> + */
> +
> +/**
> + * DOC: Section range module support
> + *
> + * Modules can use section ranges, however the section range definition must be
> + * built-in to the kernel. That is, the code that implements
> + * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
> + * items in to the section range (with __LINUX_RANGE() or
> + * __LINUX_RANGE_ORDER()), 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: Section range helpers
> + *
> + * These are helpers for section ranges.
> + */
> +
> +/**
> + * DECLARE_SECTION_RANGE - Declares a section range
> + *
> + * @name: section range name
> + *
> + * Declares a section range to help code access the range. Typically if
> + * a subsystems needs code to have direct access to the section range the
> + * subsystem's header file would declare the section range. Care should be
> + * taken to only declare the section range in a header file if access to it
> + * is truly needed outside of the code defining it. You typically would
> + * rather instead provide helpers which access the section range with special
> + * code on behalf of the caller.
> + */
> +#define DECLARE_SECTION_RANGE(name)                                    \
> +       DECLARE_LINUX_SECTION_RO(char, name)
> +
> +/**
> + * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
> + *
> + * @name: section range name
> + * @__section: ELF section to place section range into
> + *
> + * Constructs the beginning of a section range. You will typically not need
> + * to use this directly.
> + */
> +#define __SECTION_RANGE_BEGIN(name, __section)                         \
> +       const __typeof__(VMLINUX_SYMBOL(name)[0])                       \
> +             __attribute__((used,                                      \
> +                            weak,                                      \
> +                            __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
> +                            section(SECTION_RNG_LEVEL(__section, name,))))
> +
> +/**
> + * __SECTION_RANGE_END - Constructs the end of a section range
> + *
> + * @name: section range name
> + * @__section: ELF section to place section range into
> + *
> + * Constructs the end of a section range. You will typically not need
> + * to use this directly.
> + */
> +#define __SECTION_RANGE_END(name, __section)                           \
> +       const __typeof__(VMLINUX_SYMBOL(name)[0])                       \
> +             __attribute__((used,                                      \
> +                            __aligned__(LINUX_SECTION_ALIGNMENT(name)),\
> +                            section(SECTION_RNG_LEVEL(__section, name, ~))))
> +
> +/**
> + * DEFINE_SECTION_RANGE - Defines a section range
> + *
> + * @name: section range name
> + * @section: ELF section name to place section range into
> + *
> + * Defines a section range, used for executable code. Section ranges are
> + * defined in the code that takes ownership and makes use of the section
> + * range.
> + */
> +#define DEFINE_SECTION_RANGE(name, section)                            \
> +       DECLARE_LINUX_SECTION_RO(char, name);                           \
> +       __SECTION_RANGE_BEGIN(name, section) VMLINUX_SYMBOL(name)[0] = {};\
> +       __SECTION_RANGE_END(name, section) VMLINUX_SYMBOL(name##__end)[0] = {}
> +
> +/**
> + * SECTION_ADDR_IN_RANGE - returns true if address is in range
> + *
> + * @name: section range name
> + * @addr: address to query for
> + *
> + * Returns true if the address is in the section range.
> + */
> +#define SECTION_ADDR_IN_RANGE(name, addr)                              \
> +        (addr >= (unsigned long) LINUX_SECTION_START(name) &&          \
> +         addr <  (unsigned long) LINUX_SECTION_END(name))
> +
> +#endif /* __ASSEMBLY__ */
> +
> +#endif /* _LINUX_RANGES_H */
> --
> 2.9.2
>

-Kees

-- 
Kees Cook
Nexus Security

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 07/16] tables.h: add linker table support
  2016-08-19 21:32   ` mcgrof
  (?)
  (?)
@ 2016-08-19 22:02   ` Kees Cook
  2016-08-22 23:53     ` Luis R. Rodriguez
  -1 siblings, 1 reply; 480+ messages in thread
From: Kees Cook @ 2016-08-19 22:02 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: gnomes, linux-ia64, Jiri Kosina, benh, Ming Lei, Heiko Carstens,
	platform-driver-x86, James Bottomley, Paul Gortmaker,
	Paul Mackerras, Michael Ellerman, H. Peter Anvin,
	Masami Hiramatsu, Mauro Carvalho Chehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, Russell King - ARM Linux,
	linux-sh, Will Deacon

On Fri, Aug 19, 2016 at 2:32 PM,  <mcgrof@kernel.org> wrote:
> From: "Luis R. Rodriguez" <mcgrof@kernel.org>
>
> 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@ipxe.org>
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  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@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
> 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@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.

Type: waek -> weak

> + *
> + * [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 */
> 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@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_ */
> 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@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 */
> 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@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 08/16] kbuild: enable option to force compile force-obj-y and force-lib-y
  2016-08-19 21:32   ` mcgrof
  (?)
  (?)
@ 2016-08-19 22:10   ` Kees Cook
  2016-08-22 23:59     ` Luis R. Rodriguez
  -1 siblings, 1 reply; 480+ messages in thread
From: Kees Cook @ 2016-08-19 22:10 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: gnomes, linux-ia64, Jiri Kosina, benh, Ming Lei, Heiko Carstens,
	platform-driver-x86, James Bottomley, Paul Gortmaker,
	Paul Mackerras, Michael Ellerman, H. Peter Anvin,
	Masami Hiramatsu, Mauro Carvalho Chehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, Russell King - ARM Linux,
	linux-sh, Will Deacon

On Fri, Aug 19, 2016 at 2:32 PM,  <mcgrof@kernel.org> wrote:
> From: "Luis R. Rodriguez" <mcgrof@kernel.org>
>
> Linux provides a rich array of features, enabling each feature
> however increases the size of the kernel and there are many
> features which users often want disabled. The traditional
> solution to this problem is for each feature to have its own
> Kconfig symbol, followed by a series of #ifdef statements
> in C code and header files, allowing the feature to be compiled
> only when desirable. As the variability of Linux increases build
> tests can and are often done with random kernel configurations,
> allyesconfig, and allmodconfig to help find code issues. This
> however doesn't catch all errors and as a consequence code that
> is typically not enabled often can suffer from bit-rot over time.
>
> An alternative approach for subsystems, which refer to as the 'build-all
> link-selectively philosophy' is to keep the Kconfig symbols, replace
> the #ifdef approach by having each feature implemented it its own C file,
> and force compilation for all features to avoid the code bit-rot problem.
> With this strategy only features that are enabled via Kconfig get
> linked into the kernel, so the forced compilation has no size impact
> on the kernel. The practice of having each feature implemented in its own
> C file is already prevalent in many subsystems, however #ifdefs are still
> typically required during feature initialization. For instance in:
>
>   #ifdef CONFIG_FOO
>   foo_init();
>   #endif
>
> We cannot remove the #ifdef and leave foo_init() as we'd either
> need to always enable the feature or add a respective #ifdef in a
> foo.h which makes foo_init() do nothing when CONFIG_FOO is disabled.
>
> Linker tables enable lifting the requirement to use of #ifdefs during
> initialization. With linker tables initialization sequences can instead
> be aggregated into a custom ELF section at link time, during run time
> the table can be iterated over and each init sequence enabled can be called.
> A feature's init routine is only added to a table when its respective
> Kconfig symbols has been enabled and therefore linked in. Linker tables
> enable subsystems to completely do away with #ifdefs if one is comfortable
> in accepting all subsystem's feature's structural size implications.
>
> Subsystems which want to follow the 'build-all link-selectively
> philosophy' still need a way to easily express and annotate that they
> wish for all code to always be compiled to help avoid code bit rot,
> as such two new targets force-obj-y and force-lib-y are provided to
> help with this. Its not fair to require everyone to force compilation
> of all features of a subsystem though, so as a compromise, the new
> targets only force compilation when CONFIG_BUILD_AVOID_BITROT is
> enabled.
>
> Only built-in features are supported at the moment. Module support
> is expected to be added after a generic solution to add linker
> tables to modules more easily is developed.
>
> v4: this patch was added to this series, it was split off from the
>     linker tables addition due to the confusion over the code bit
>     rot alternatives that are possible with linker tables.
>
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  Documentation/kbuild/makefiles.txt       | 36 ++++++++++++++++
>  Documentation/sections/linker-tables.rst | 15 +++++++
>  include/linux/tables.h                   | 71 ++++++++++++++++++++++++++++++++
>  init/Kconfig                             | 22 ++++++++++
>  scripts/Makefile.build                   |  7 ++--
>  scripts/Makefile.lib                     | 11 +++++
>  6 files changed, 159 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
> index 385a5ef41c17..01c260913f5c 100644
> --- a/Documentation/kbuild/makefiles.txt
> +++ b/Documentation/kbuild/makefiles.txt
> @@ -1089,6 +1089,42 @@ When kbuild executes, the following steps are followed (roughly):
>         In this example, extra-y is used to list object files that
>         shall be built, but shall not be linked as part of built-in.o.
>
> +    force-obj-y force-lib-y
> +
> +       When CONFIG_BUILD_AVOID_BITROT is enabled using these targets for your
> +       kconfig symbols forces compilation of the associated objects if the
> +       kconfig's symbol's dependencies are met, the objects however are only
> +       linked into to the kernel if and only if the kconfig symbol was
> +       enabled. If CONFIG_BUILD_AVOID_BITROT is disabled the force-obj-y and
> +       force-lib-y targets are functionally equilvalent to obj-y and lib-y
> +       respectively.
> +
> +       Using force-obj-y and force-lib-y are part of a code architecture and
> +       build philosophy further enabled by linker tables, for more details
> +       refer to the documention in include/linux/tables.h, refer to the
> +       sections:
> +
> +               o The code bit-rot problem
> +               o The build-all selective-link philosophy
> +               o Avoiding the code bit-rot problem with linker tables
> +               o Linker table module support
> +
> +       Modules support is expected to be enhanced in the future, so for now
> +       only built-in features are supported.
> +
> +       Example use:
> +
> +               force-obj-$(CONFIG_FEATURE_FOO) += foo.o
> +
> +       An alternative to using force-obj-y, is to use extra-y followed by the
> +       respective obj-y:
> +
> +               extra-y += foo.o
> +               obj-$(CONFIG_FEATURE_FOO) += foo.o
> +
> +       Using force-obj-y and force-lib-y can be used to help annotate the
> +       targets follow the 'build-all selective-link philosophy' further
> +       enabled by linker tables.
>
>  --- 6.7 Commands useful for building a boot image
>
> diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
> index df11c632dca7..e425c5cd36d6 100644
> --- a/Documentation/sections/linker-tables.rst
> +++ b/Documentation/sections/linker-tables.rst
> @@ -30,6 +30,21 @@ How linker tables simplify initialization code
>  .. kernel-doc:: include/linux/tables.h
>     :doc: How linker tables simplify initialization code
>
> +The code bit-rot problem
> +------------------------
> +.. kernel-doc:: include/linux/tables.h
> +   :doc: The code bit-rot problem
> +
> +The build-all selective-link philosophy
> +---------------------------------------
> +.. kernel-doc:: include/linux/tables.h
> +   :doc: The build-all selective-link philosophy
> +
> +Avoiding the code bit-rot problem with linker tables
> +----------------------------------------------------
> +.. kernel-doc:: include/linux/tables.h
> +   :doc: Avoiding the code bit-rot problem with linker tables
> +
>  Using linker tables in Linux
>  ============================
>
> diff --git a/include/linux/tables.h b/include/linux/tables.h
> index 423827eafb52..bf8fae7f9246 100644
> --- a/include/linux/tables.h
> +++ b/include/linux/tables.h
> @@ -169,6 +169,77 @@
>   */
>
>  /**
> + * DOC: The code bit-rot problem
> + *
> + * Linux provides a rich array of features, enabling each feature
> + * however increases the size of the kernel and there are many
> + * features which users often want disabled. The traditional
> + * solution to this problem is for each feature to have its own
> + * Kconfig symbol, followed by a series of #ifdef statements
> + * in C code and header files, allowing the feature to be compiled
> + * only when desirable. As the variability of Linux increases build
> + * tests can and are often done with random kernel configurations,
> + * allyesconfig, and allmodconfig to help find code issues. This
> + * however doesn't catch all errors and as a consequence code that
> + * is typically not enabled often can suffer from bit-rot over time.
> + */
> +
> +/**
> + * DOC: The build-all selective-link philosophy
> + *
> + * A code architecture philosophy to help avoid code bit-rot consists
> + * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
> + * by instead having each feature implemented it its own C file, and force
> + * compilation for all features. Only features that are enabled get linked in,
> + * the forced compilation therefore has no size impact on the final result of
> + * the kernel. The practice of having each feature implemented in its own C
> + * file is already prevalent in many subsystems, however #ifdefs are still
> + * typically required during feature initialization. For instance in::
> + *
> + *     #ifdef CONFIG_FOO
> + *     foo_init();
> + *     #endif
> + *
> + * We cannot remove the #ifdef and leave foo_init() as we'd either
> + * need to always enable the feature or add a respective #ifdef in a
> + * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
> + */
> +
> +/**
> + * DOC: Avoiding the code bit-rot problem with linker tables
> + *
> + * Linker tables can be used to further help avoid the code bit-rot problem
> + * when embracing the 'build-all selective-link philosophy' by lifting the
> + * requirement to use of #ifdefs during initialization. With linker tables
> + * initialization sequences can be aggregated into a custom ELF section at
> + * link time, during run time the table can be iterated over and each init
> + * sequence enabled can be called. A feature's init routine is only added to a
> + * table when its respective Kconfig symbols has been enabled and therefore
> + * linked in. Linker tables enable subsystems to completely do away with
> + * #ifdefs if one is comfortable in accepting all subsystem's feature's
> + * structural size implications.
> + *
> + * To further help with this the Linux build system supports two special
> + * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
> + * follow the 'build-all selective-link philosophy' can use these targets for a
> + * feature's kconfig symbol. Using these targets will always require
> + * compilation of the kconfig's objects if the kconfig symbol's dependencies
> + * are met but only link the objects into the kernel, and therefore enable the
> + * feature, if and only if the kconfig symbol has been enabled.
> + *
> + * Not all users or build systems may want to opt-in to compile all objects
> + * following the 'build-all selective-link philosophy', as such the targets
> + * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
> + * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
> + * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
> + * ``obj-y`` and ``lib-y`` respectively.
> + *
> + * Example use::
> + *
> + *     force-obj-$(CONFIG_FEATURE_FOO) += foo.o
> + */
> +
> +/**
>   * DOC: Linker table module support
>   *
>   * Modules can use linker tables, however the linker table definition
> diff --git a/init/Kconfig b/init/Kconfig
> index cac3f096050d..ef09e83b9196 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -53,6 +53,28 @@ config CROSS_COMPILE
>           need to set this unless you want the configured kernel build
>           directory to select the cross-compiler automatically.
>
> +config BUILD_AVOID_BITROT
> +       bool "Enable force building of force-obj-y and force-lib-y"

Sorry to continue the bikeshedding on this, but if I encounter
something in a Makefile named "force-obj-y" I would expect it to
always be built, no matter what. But this is not the case: the
"force-" prefix is tied to this CONFIG_BUILD_AVOID_BITROT. This verb
usage is weird, as I'd expect an adjective, like "forceable-obj-y" or
something that describes that it CAN be built even with the CONFIG for
it is missing, etc.

Regardless, I defer to Michal on this, but I'm not a fan of "force"
being used when it's an optional action. :)

-Kees

> +       default n
> +       help
> +         When enabled objects under the force-obj-y and force-lib-y targets
> +         using a Kconfig symbol will be forced to compile if the Kconfig
> +         symbol's dependencies are met but only linked into the kernel if
> +         the Kconfig symbol is enabled. If a Kconfig symbol on a force-obj-y
> +         or force-lib-y target is disabled, it will be compiled but not linked
> +         into the kernel.
> +
> +         The force-obj-y and force-lib-y targets can be used by subsystems
> +         which wish to want to follow the 'build-all selective-link philosophy'
> +         documented under include/linux/tables.h.
> +
> +         Say Y if you have a decent build machine and would like to help test
> +         building code for more subsystems. Say N if you do you not have a
> +         good build machine or only want to compile what you've enabled for
> +         your kernel.
> +
> +         Enabling this option never increases the size of your kernel.
> +
>  config COMPILE_TEST
>         bool "Compile also drivers which will not load"
>         depends on !UML
> diff --git a/scripts/Makefile.build b/scripts/Makefile.build
> index cd9bf22bb027..cc2c7241d193 100644
> --- a/scripts/Makefile.build
> +++ b/scripts/Makefile.build
> @@ -92,7 +92,8 @@ modorder-target := $(obj)/modules.order
>
>  # We keep a list of all modules in $(MODVERDIR)
>
> -__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
> +__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y) \
> +                               $(force-obj-y)) \
>          $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
>          $(subdir-ym) $(always)
>         @:
> @@ -326,8 +327,8 @@ cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $<
>  $(obj)/%.o: $(src)/%.S $(objtool_obj) FORCE
>         $(call if_changed_rule,as_o_S)
>
> -targets += $(real-objs-y) $(real-objs-m) $(lib-y)
> -targets += $(extra-y) $(MAKECMDGOALS) $(always)
> +targets += $(real-objs-y) $(real-objs-m) $(lib-y) $(force-lib-y)
> +targets += $(extra-y) $(force-obj-y) $(MAKECMDGOALS) $(always)
>
>  # Linker scripts preprocessor (.lds.S -> .lds)
>  # ---------------------------------------------------------------------------
> diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
> index 0a07f9014944..d1cb0cfdf1bf 100644
> --- a/scripts/Makefile.lib
> +++ b/scripts/Makefile.lib
> @@ -12,6 +12,15 @@ export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y)
>  # Figure out what we need to build from the various variables
>  # ===========================================================================
>
> +ifeq ($(CONFIG_BUILD_AVOID_BITROT),y)
> +extra-y += $(force-obj-) $(force-lib-)
> +endif
> +
> +obj-m += $(force-obj-m)
> +obj-y += $(force-obj-y)
> +lib-m += $(force-lib-m)
> +lib-y += $(force-lib-y)
> +
>  # When an object is listed to be built compiled-in and modular,
>  # only build the compiled-in version
>
> @@ -72,6 +81,8 @@ real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)
>  # Add subdir path
>
>  extra-y                := $(addprefix $(obj)/,$(extra-y))
> +force-obj-y            := $(addprefix $(obj)/,$(force-obj-y))
> +force-obj-m            := $(addprefix $(obj)/,$(force-obj-m))
>  always         := $(addprefix $(obj)/,$(always))
>  targets                := $(addprefix $(obj)/,$(targets))
>  modorder       := $(addprefix $(obj)/,$(modorder))
> --
> 2.9.2
>



-- 
Kees Cook
Nexus Security

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 00/16] linux: generalize sections, ranges and linker tables
  2016-08-19 21:32 ` mcgrof
                   ` (12 preceding siblings ...)
  (?)
@ 2016-08-19 22:29 ` Kees Cook
  2016-08-22 23:06   ` Luis R. Rodriguez
  -1 siblings, 1 reply; 480+ messages in thread
From: Kees Cook @ 2016-08-19 22:29 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: gnomes, linux-ia64, Jiri Kosina, benh, Ming Lei, Heiko Carstens,
	platform-driver-x86, James Bottomley, Paul Gortmaker,
	Paul Mackerras, Michael Ellerman, H. Peter Anvin,
	Masami Hiramatsu, Mauro Carvalho Chehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, Russell King - ARM Linux,
	linux-sh, Will Deacon

On Fri, Aug 19, 2016 at 2:32 PM,  <mcgrof@kernel.org> wrote:
> From: "Luis R. Rodriguez" <mcgrof@kernel.org>
>
> This v4 addresses feedback from the previous v3 series [0], and also
> addresses a huge array of additional tests against many architectures
> outside of what 0-day provides. As I mentioned in my last v3 series,
> 0-day had only found one issue with the series, a blackfin architecture
> linker issue with the last series. Guenter Rock was kind enough to give
> my series a test spin on his test bed and he found quite a bit of other
> oddball issues with obscure architectures, and even on x86 with an old
> toolchain. After a lot of work and coordinating with a few maintainers
> I'm happy to report all issues found so far through all possible testing
> I could do are now fixed, this series also addresses all feedback from
> the last series, as such this goes submitted as PATCH form.
>
> In addressing fixing this work on a few architectures some of the previous
> patches are further simplified. The kprobes port to linker tables is made
> much easier now that I've addressed moving out core kprobe declarations
> into asm-generic/kprobes.h. Refer to the patch "kprobes: move kprobe
> declarations to asm-generic/kprobes.h". This makes for a much cleaner
> solution across architectures.
>
> Boris feedback on making the code bit rot feature optional is addressed
> by using a new Kconfig symbol for this, CONFIG_BUILD_AVOID_BITROT,
> but given Greg's concerns over lack of clarity over what this was all about
> I've ripped that functionality out into its own patch with a bit more
> extensive documentation and re-wording. See the patch "kbuild: enable option
> to force compile force-obj-y and force-lib-y". I hope makes it clear how
> linker tables can help with avoiding code bit rot. I've gone with a new
> Kconfig symbol CONFIG_BUILD_AVOID_BITROT given CONFIG_COMPILE_TEST is
> not available on UML, this feature is desirable on all architectures.
>
> The documentation is revamped, now that the DocBook format is deprecated
> I ported the documention into the trendy hipster Sphinx documentation
> format.
>
> AT Boris' request I've adapated the userspace linker table application
> forintegration into the kernel under tools/ to make it easier to keep
> things in sync, however since this requires a bit of changes to some headers
> in tools/ I'll submit that separately.
>
> [0] https://lkml.kernel.org/r/1469222687-1600-1-git-send-email-mcgrof@kernel.org
>
> If you'd like this in git-form, you can get it on the 20160819-linker-table-v4
> branch of my linux-next tree on kernel.org, this also includes the series of
> the linker table userspace sandbox:
>
> https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h=20160819-linker-table-v4
>
> Please let me know if there are any concerns or questions.

Thanks for the documentation and examples on this feature; I appreciate it! :)

While it seems like all the section declarations work in this series
is designed for assembler source, I'm curious if I've missed a way to
do this in .c source too. I'd love to avoid doing the crazy thing I'm
currently doing in lkdtm with section markings. Namely, I want to
write a function in .c and have it moved into the .rodata section. The
linkers get very very angry with me and I don't seem to be able to
override the progbits to lose "x". Right now I'm doing an objcopy in
drivers/misc/Makefile:

OBJCOPYFLAGS_lkdtm_rodata_objcopy.o := \
                        --set-section-flags .text=alloc,readonly \
                        --rename-section .text=.rodata
targets += lkdtm_rodata.o lkdtm_rodata_objcopy.o
$(obj)/lkdtm_rodata_objcopy.o: $(obj)/lkdtm_rodata.o FORCE
        $(call if_changed,objcopy)

Thanks!

-Kees

>
> Luis R. Rodriguez (16):
>   x86: remove LTO_REFERENCE_INITCALL()
>   dell-smo8800: include uaccess.h
>   scripts/module-common.lds: enable generation
>   generic-sections: add section core helpers
>   xtensa: skip adding literal when SORT() is used
>   ranges.h: add helpers to build and identify Linux section ranges
>   tables.h: add linker table support
>   kbuild: enable option to force compile force-obj-y and force-lib-y
>   firmware/Makefile: force recompilation if makefile changes
>   firmware: port built-in section to linker table
>   jump_label: move guard #endif down where it belongs
>   jump_label: port __jump_table to linker tables
>   dynamic_debug: port to use linker tables
>   kprobes: move kprobe declarations to asm-generic/kprobes.h
>   kprobes: port .kprobes.text to section range
>   kprobes: port blacklist kprobes to linker table
>
>  .gitignore                                         |   2 +
>  Documentation/index.rst                            |   1 +
>  Documentation/kbuild/makefiles.txt                 |  36 ++
>  Documentation/sections/conf.py                     |   4 +
>  Documentation/sections/index.rst                   |  13 +
>  Documentation/sections/linker-tables.rst           | 202 +++++++
>  Documentation/sections/ranges.rst                  |  49 ++
>  Documentation/sections/section-core.rst            | 153 +++++
>  MAINTAINERS                                        |  37 ++
>  Makefile                                           |   6 +-
>  arch/alpha/include/asm/Kbuild                      |   4 +
>  arch/arc/include/asm/Kbuild                        |   3 +
>  arch/arc/include/asm/kprobes.h                     |   6 +-
>  arch/arc/kernel/vmlinux.lds.S                      |   1 -
>  arch/arm/include/asm/Kbuild                        |   3 +
>  arch/arm/include/asm/jump_label.h                  |   6 +-
>  arch/arm/include/asm/kprobes.h                     |   4 +
>  arch/arm/kernel/entry-armv.S                       |   3 +-
>  arch/arm/kernel/vmlinux-xip.lds.S                  |   1 -
>  arch/arm/kernel/vmlinux.lds.S                      |   1 -
>  arch/arm/probes/decode.h                           |   1 +
>  arch/arm64/include/asm/Kbuild                      |   3 +
>  arch/arm64/include/asm/jump_label.h                |   6 +-
>  arch/arm64/include/asm/kprobes.h                   |   4 +
>  arch/arm64/kernel/armv8_deprecated.c               |   1 +
>  arch/arm64/kernel/insn.c                           |   1 +
>  arch/arm64/kernel/probes/kprobes.c                 |   4 +-
>  arch/arm64/kernel/vmlinux.lds.S                    |   1 -
>  arch/avr32/include/asm/Kbuild                      |   3 +
>  arch/avr32/include/asm/kprobes.h                   |   4 +
>  arch/avr32/kernel/entry-avr32b.S                   |  13 +-
>  arch/avr32/kernel/vmlinux.lds.S                    |   1 -
>  arch/blackfin/include/asm/Kbuild                   |   4 +
>  arch/blackfin/kernel/vmlinux.lds.S                 |   1 -
>  arch/c6x/include/asm/Kbuild                        |   3 +
>  arch/c6x/include/asm/tables.h                      |  26 +
>  arch/c6x/kernel/vmlinux.lds.S                      |   1 -
>  arch/cris/include/asm/Kbuild                       |   4 +
>  arch/frv/include/asm/Kbuild                        |   4 +
>  arch/h8300/include/asm/Kbuild                      |   4 +
>  arch/hexagon/include/asm/Kbuild                    |   4 +
>  arch/hexagon/kernel/vmlinux.lds.S                  |   1 -
>  arch/ia64/include/asm/Kbuild                       |   3 +
>  arch/ia64/include/asm/kprobes.h                    |   7 +-
>  arch/ia64/kernel/jprobes.S                         |   3 +-
>  arch/ia64/kernel/vmlinux.lds.S                     |   1 -
>  arch/ia64/lib/flush.S                              |   6 +-
>  arch/m32r/include/asm/Kbuild                       |   4 +
>  arch/m68k/include/asm/Kbuild                       |   4 +
>  arch/metag/include/asm/Kbuild                      |   4 +
>  arch/metag/kernel/vmlinux.lds.S                    |   1 -
>  arch/microblaze/include/asm/Kbuild                 |   4 +
>  arch/microblaze/kernel/vmlinux.lds.S               |   1 -
>  arch/mips/include/asm/Kbuild                       |   3 +
>  arch/mips/include/asm/jump_label.h                 |   6 +-
>  arch/mips/include/asm/kprobes.h                    |   6 +-
>  arch/mips/kernel/vmlinux.lds.S                     |   1 -
>  arch/mn10300/include/asm/Kbuild                    |   3 +
>  arch/mn10300/include/asm/kprobes.h                 |   4 +
>  arch/mn10300/kernel/vmlinux.lds.S                  |   1 -
>  arch/nios2/include/asm/Kbuild                      |   4 +
>  arch/nios2/kernel/vmlinux.lds.S                    |   1 -
>  arch/openrisc/include/asm/Kbuild                   |   4 +
>  arch/openrisc/kernel/vmlinux.lds.S                 |   1 -
>  arch/parisc/include/asm/Kbuild                     |   4 +
>  arch/parisc/kernel/vmlinux.lds.S                   |   1 -
>  arch/powerpc/include/asm/Kbuild                    |   3 +
>  arch/powerpc/include/asm/jump_label.h              |   8 +-
>  arch/powerpc/include/asm/kprobes.h                 |   6 +
>  arch/powerpc/include/asm/ppc_asm.h                 |   7 +-
>  arch/powerpc/kernel/vmlinux.lds.S                  |   1 -
>  arch/s390/include/asm/Kbuild                       |   3 +
>  arch/s390/include/asm/jump_label.h                 |   6 +-
>  arch/s390/include/asm/kprobes.h                    |   4 +
>  arch/s390/kernel/entry.S                           |   5 +-
>  arch/s390/kernel/kprobes.c                         |   6 +-
>  arch/s390/kernel/mcount.S                          |   3 +-
>  arch/s390/kernel/vmlinux.lds.S                     |   1 -
>  arch/score/include/asm/Kbuild                      |   4 +
>  arch/score/kernel/vmlinux.lds.S                    |   1 -
>  arch/sh/include/asm/Kbuild                         |   3 +
>  arch/sh/include/asm/kprobes.h                      |   2 +
>  arch/sh/kernel/vmlinux.lds.S                       |   1 -
>  arch/sparc/include/asm/Kbuild                      |   3 +
>  arch/sparc/include/asm/jump_label.h                |   6 +-
>  arch/sparc/include/asm/kprobes.h                   |   5 +
>  arch/sparc/kernel/vmlinux.lds.S                    |   1 -
>  arch/sparc/mm/ultra.S                              |   3 +-
>  arch/tile/include/asm/Kbuild                       |   3 +
>  arch/tile/include/asm/kprobes.h                    |   6 +-
>  arch/tile/kernel/vmlinux.lds.S                     |   1 -
>  arch/um/include/asm/Kbuild                         |   4 +
>  arch/unicore32/include/asm/Kbuild                  |   3 +
>  arch/unicore32/include/asm/section-core.h          |  19 +
>  arch/x86/include/asm/Kbuild                        |   3 +
>  arch/x86/include/asm/jump_label.h                  |  10 +-
>  arch/x86/include/asm/kprobes.h                     |   6 +
>  arch/x86/kernel/cpu/microcode/core.c               |   8 +-
>  arch/x86/kernel/kprobes/core.c                     |  11 +-
>  arch/x86/kernel/vmlinux.lds.S                      |   1 -
>  arch/x86/tools/relocs.c                            |   4 +
>  arch/xtensa/include/asm/Kbuild                     |   4 +
>  arch/xtensa/kernel/Makefile                        |   8 +-
>  drivers/base/firmware_class.c                      |  12 +-
>  drivers/platform/x86/dell-smo8800.c                |   1 +
>  firmware/Makefile                                  |   6 +-
>  include/asm-generic/kprobes.h                      |  26 +
>  include/asm-generic/ranges.h                       | 103 ++++
>  include/asm-generic/section-core.h                 | 341 +++++++++++
>  include/asm-generic/sections.h                     |   4 +-
>  include/asm-generic/tables.h                       |  50 ++
>  include/asm-generic/vmlinux.lds.h                  |  73 +--
>  include/linux/compiler.h                           |   8 -
>  include/linux/dynamic_debug.h                      |   5 +-
>  include/linux/init.h                               |  20 +-
>  include/linux/jump_label.h                         |   8 +-
>  include/linux/kprobes.h                            |  24 +-
>  include/linux/ranges.h                             | 128 +++++
>  include/linux/sections.h                           | 111 ++++
>  include/linux/tables.h                             | 638 +++++++++++++++++++++
>  init/Kconfig                                       |  22 +
>  kernel/jump_label.c                                |  17 +-
>  kernel/kprobes.c                                   |  17 +-
>  lib/dynamic_debug.c                                |  13 +-
>  scripts/Makefile.build                             |   7 +-
>  scripts/Makefile.clean                             |   2 +
>  scripts/Makefile.lib                               |  11 +
>  scripts/Makefile.modpost                           |   2 +-
>  scripts/mod/modpost.c                              |   2 +-
>  scripts/{module-common.lds => module-common.lds.S} |   6 +
>  scripts/recordmcount.c                             |   2 +-
>  scripts/recordmcount.pl                            |   2 +-
>  tools/objtool/special.c                            |   2 +-
>  133 files changed, 2328 insertions(+), 214 deletions(-)
>  create mode 100644 Documentation/sections/conf.py
>  create mode 100644 Documentation/sections/index.rst
>  create mode 100644 Documentation/sections/linker-tables.rst
>  create mode 100644 Documentation/sections/ranges.rst
>  create mode 100644 Documentation/sections/section-core.rst
>  create mode 100644 arch/c6x/include/asm/tables.h
>  create mode 100644 arch/unicore32/include/asm/section-core.h
>  create mode 100644 include/asm-generic/kprobes.h
>  create mode 100644 include/asm-generic/ranges.h
>  create mode 100644 include/asm-generic/section-core.h
>  create mode 100644 include/asm-generic/tables.h
>  create mode 100644 include/linux/ranges.h
>  create mode 100644 include/linux/sections.h
>  create mode 100644 include/linux/tables.h
>  rename scripts/{module-common.lds => module-common.lds.S} (80%)
>
> --
> 2.9.2
>



-- 
Kees Cook
Nexus Security

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 7/7] tools: add userspace linker table sandbox
  2016-08-19 21:41       ` mcgrof
  (?)
@ 2016-08-19 22:31       ` Kees Cook
  2016-08-23  0:07         ` Luis R. Rodriguez
  -1 siblings, 1 reply; 480+ messages in thread
From: Kees Cook @ 2016-08-19 22:31 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: gnomes, linux-ia64, Jiri Kosina, benh, Ming Lei, Heiko Carstens,
	platform-driver-x86, James Bottomley, Paul Gortmaker,
	Paul Mackerras, Michael Ellerman, H. Peter Anvin,
	Masami Hiramatsu, Mauro Carvalho Chehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, Russell King - ARM Linux,
	linux-sh, Will Deacon

On Fri, Aug 19, 2016 at 2:41 PM,  <mcgrof@kernel.org> wrote:
> From: "Luis R. Rodriguez" <mcgrof@kernel.org>
>
> Add a userspace sandbox to allow easy experimentation and
> test extensions with linker tables, section ranges and the
> new section core definitions.
>
> The userspace sandbox tries to mimic the Linux kernel development
> flow as much as possible, it however relies on and uses libc. Support
> is currently only provided to x86_64.
>
> v4: this patch is new in this series -- added to the kenrel as
>     suggested by Boris, as otherwise it'd be really hard to keep
>     an external userspace repository in sync.
>
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  Documentation/sections/linker-tables.rst           |   4 +-
>  MAINTAINERS                                        |   1 +
>  include/linux/tables.h                             |   5 +-
>  tools/Makefile                                     |   3 +-
>  .../arch/x86/include/generated/asm/section-core.h  |   1 +
>  tools/arch/x86/include/generated/ranges.h          |   1 +
>  tools/arch/x86/include/generated/tables.h          |   1 +
>  tools/include/asm-generic/ranges.h                 | 103 ++++
>  tools/include/asm-generic/section-core.h           | 341 +++++++++++
>  tools/include/asm-generic/tables.h                 |  50 ++

Aren't a bunch of these files exact duplicates of the headers in include/linux?

-Kees

-- 
Kees Cook
Nexus Security

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 0/7] tools: add linker table userspace sandbox
  2016-08-19 21:41     ` mcgrof
  (?)
@ 2016-08-20  4:57       ` Rob Landley
  -1 siblings, 0 replies; 480+ messages in thread
From: Rob Landley @ 2016-08-20  4:57 UTC (permalink / raw)
  To: mcgrof, acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

On 08/19/2016 04:41 PM, mcgrof@kernel.org wrote:
> Please let me know if there are any issue or questions.

Only that this has been the majority of the traffic on the linux-sh
mailing list for over a month and I'm still not sure why anyone should care.

I have no idea what problem it solves, despite reading a couple dozen
messages in the thread, and the most recent two 0/x intro messages. Its
purpose seems to be ensuring that lld.llvm.org has more work to do if it
ever wants to build the kernel without binutils?

I also am not certain why every revision of it is cc'd to linux-sh. Is
it generic linker infrastructure change, or is it something that affects
this architecture specifically? As far as I can tell nothing in this
most recent 7-patch series touches arch/sh at all, you just cc'd our
list because you think the work you're doing is _important_, not that
it's specifically relevant to us.

Rob

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 0/7] tools: add linker table userspace sandbox
@ 2016-08-20  4:57       ` Rob Landley
  0 siblings, 0 replies; 480+ messages in thread
From: Rob Landley @ 2016-08-20  4:57 UTC (permalink / raw)
  To: mcgrof, acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, ton

On 08/19/2016 04:41 PM, mcgrof@kernel.org wrote:
> Please let me know if there are any issue or questions.

Only that this has been the majority of the traffic on the linux-sh
mailing list for over a month and I'm still not sure why anyone should care.

I have no idea what problem it solves, despite reading a couple dozen
messages in the thread, and the most recent two 0/x intro messages. Its
purpose seems to be ensuring that lld.llvm.org has more work to do if it
ever wants to build the kernel without binutils?

I also am not certain why every revision of it is cc'd to linux-sh. Is
it generic linker infrastructure change, or is it something that affects
this architecture specifically? As far as I can tell nothing in this
most recent 7-patch series touches arch/sh at all, you just cc'd our
list because you think the work you're doing is _important_, not that
it's specifically relevant to us.

Rob

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 0/7] tools: add linker table userspace sandbox
@ 2016-08-20  4:57       ` Rob Landley
  0 siblings, 0 replies; 480+ messages in thread
From: Rob Landley @ 2016-08-20  4:57 UTC (permalink / raw)
  To: mcgrof, acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6
  Cc: x86, luto, keescook, torvalds, gregkh, rusty, gnomes, alan,
	dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, jolsa,
	msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley

On 08/19/2016 04:41 PM, mcgrof@kernel.org wrote:
> Please let me know if there are any issue or questions.

Only that this has been the majority of the traffic on the linux-sh
mailing list for over a month and I'm still not sure why anyone should care.

I have no idea what problem it solves, despite reading a couple dozen
messages in the thread, and the most recent two 0/x intro messages. Its
purpose seems to be ensuring that lld.llvm.org has more work to do if it
ever wants to build the kernel without binutils?

I also am not certain why every revision of it is cc'd to linux-sh. Is
it generic linker infrastructure change, or is it something that affects
this architecture specifically? As far as I can tell nothing in this
most recent 7-patch series touches arch/sh at all, you just cc'd our
list because you think the work you're doing is _important_, not that
it's specifically relevant to us.

Rob

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 0/7] tools: add linker table userspace sandbox
  2016-08-20  4:57       ` Rob Landley
  (?)
@ 2016-08-21  4:59         ` Rich Felker
  -1 siblings, 0 replies; 480+ messages in thread
From: Rich Felker @ 2016-08-21  4:59 UTC (permalink / raw)
  To: Rob Landley
  Cc: mcgrof, acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jg

On Fri, Aug 19, 2016 at 11:57:18PM -0500, Rob Landley wrote:
> On 08/19/2016 04:41 PM, mcgrof@kernel.org wrote:
> > Please let me know if there are any issue or questions.
> 
> Only that this has been the majority of the traffic on the linux-sh
> mailing list for over a month and I'm still not sure why anyone should care.
> 
> I have no idea what problem it solves, despite reading a couple dozen
> messages in the thread, and the most recent two 0/x intro messages. Its
> purpose seems to be ensuring that lld.llvm.org has more work to do if it
> ever wants to build the kernel without binutils?
> 
> I also am not certain why every revision of it is cc'd to linux-sh. Is
> it generic linker infrastructure change, or is it something that affects
> this architecture specifically? As far as I can tell nothing in this
> most recent 7-patch series touches arch/sh at all, you just cc'd our
> list because you think the work you're doing is _important_, not that
> it's specifically relevant to us.

Incidentally I'm happy to have been CC'd since this infrastructure is
_really_ nice for doing things generically with device tree. The
ability to add new linker-section-based tables without having to
manually hack up linker script templates will make it so we can do
things like adding tables for cache controllers or mmus (that are
needed quite early in init and can't go through the platform device
system).

BTW we kinda lucked out that there was already the linker table
infrastructure for cpu enable methods for smp; this patch series makes
it so future stuff doesn't have to rely on luck or invasive changes.

Rich

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 0/7] tools: add linker table userspace sandbox
@ 2016-08-21  4:59         ` Rich Felker
  0 siblings, 0 replies; 480+ messages in thread
From: Rich Felker @ 2016-08-21  4:59 UTC (permalink / raw)
  To: Rob Landley
  Cc: mcgrof, acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jg

On Fri, Aug 19, 2016 at 11:57:18PM -0500, Rob Landley wrote:
> On 08/19/2016 04:41 PM, mcgrof@kernel.org wrote:
> > Please let me know if there are any issue or questions.
> 
> Only that this has been the majority of the traffic on the linux-sh
> mailing list for over a month and I'm still not sure why anyone should care.
> 
> I have no idea what problem it solves, despite reading a couple dozen
> messages in the thread, and the most recent two 0/x intro messages. Its
> purpose seems to be ensuring that lld.llvm.org has more work to do if it
> ever wants to build the kernel without binutils?
> 
> I also am not certain why every revision of it is cc'd to linux-sh. Is
> it generic linker infrastructure change, or is it something that affects
> this architecture specifically? As far as I can tell nothing in this
> most recent 7-patch series touches arch/sh at all, you just cc'd our
> list because you think the work you're doing is _important_, not that
> it's specifically relevant to us.

Incidentally I'm happy to have been CC'd since this infrastructure is
_really_ nice for doing things generically with device tree. The
ability to add new linker-section-based tables without having to
manually hack up linker script templates will make it so we can do
things like adding tables for cache controllers or mmus (that are
needed quite early in init and can't go through the platform device
system).

BTW we kinda lucked out that there was already the linker table
infrastructure for cpu enable methods for smp; this patch series makes
it so future stuff doesn't have to rely on luck or invasive changes.

Rich

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 0/7] tools: add linker table userspace sandbox
@ 2016-08-21  4:59         ` Rich Felker
  0 siblings, 0 replies; 480+ messages in thread
From: Rich Felker @ 2016-08-21  4:59 UTC (permalink / raw)
  To: Rob Landley
  Cc: mcgrof, acme, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, paulus, mpe, James.Bottomley

On Fri, Aug 19, 2016 at 11:57:18PM -0500, Rob Landley wrote:
> On 08/19/2016 04:41 PM, mcgrof@kernel.org wrote:
> > Please let me know if there are any issue or questions.
> 
> Only that this has been the majority of the traffic on the linux-sh
> mailing list for over a month and I'm still not sure why anyone should care.
> 
> I have no idea what problem it solves, despite reading a couple dozen
> messages in the thread, and the most recent two 0/x intro messages. Its
> purpose seems to be ensuring that lld.llvm.org has more work to do if it
> ever wants to build the kernel without binutils?
> 
> I also am not certain why every revision of it is cc'd to linux-sh. Is
> it generic linker infrastructure change, or is it something that affects
> this architecture specifically? As far as I can tell nothing in this
> most recent 7-patch series touches arch/sh at all, you just cc'd our
> list because you think the work you're doing is _important_, not that
> it's specifically relevant to us.

Incidentally I'm happy to have been CC'd since this infrastructure is
_really_ nice for doing things generically with device tree. The
ability to add new linker-section-based tables without having to
manually hack up linker script templates will make it so we can do
things like adding tables for cache controllers or mmus (that are
needed quite early in init and can't go through the platform device
system).

BTW we kinda lucked out that there was already the linker table
infrastructure for cpu enable methods for smp; this patch series makes
it so future stuff doesn't have to rely on luck or invasive changes.

Rich

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 0/7] tools: add linker table userspace sandbox
  2016-08-21  4:59         ` Rich Felker
@ 2016-08-22  4:04           ` H. Peter Anvin
  -1 siblings, 0 replies; 480+ messages in thread
From: H. Peter Anvin @ 2016-08-22  4:04 UTC (permalink / raw)
  To: Rich Felker, Rob Landley

mcgrof@kernel.org,acme@redhat.com,tglx@linutronix.de,mingo@redhat.com,jpoimboe@redhat.com,bp@alien8.de,linux@arm.linux.org.uk,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,x86@kernel.org,luto@amacapital.net,keescook@chromium.org,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,ananth@in.ibm.com,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@ra!
 smusville
moes.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,paulus@samba.org,mpe@ellerman.id.au,James.Bottomley@HansenPartnership.com
Message-ID: <5150EFE4-3E00-4BD2-AE6F-F99FBBC74273@zytor.com>

On August 20, 2016 9:59:59 PM PDT, Rich Felker <dalias@libc.org> wrote:
>On Fri, Aug 19, 2016 at 11:57:18PM -0500, Rob Landley wrote:
>> On 08/19/2016 04:41 PM, mcgrof@kernel.org wrote:
>> > Please let me know if there are any issue or questions.
>> 
>> Only that this has been the majority of the traffic on the linux-sh
>> mailing list for over a month and I'm still not sure why anyone
>should care.
>> 
>> I have no idea what problem it solves, despite reading a couple dozen
>> messages in the thread, and the most recent two 0/x intro messages.
>Its
>> purpose seems to be ensuring that lld.llvm.org has more work to do if
>it
>> ever wants to build the kernel without binutils?
>> 
>> I also am not certain why every revision of it is cc'd to linux-sh.
>Is
>> it generic linker infrastructure change, or is it something that
>affects
>> this architecture specifically? As far as I can tell nothing in this
>> most recent 7-patch series touches arch/sh at all, you just cc'd our
>> list because you think the work you're doing is _important_, not that
>> it's specifically relevant to us.
>
>Incidentally I'm happy to have been CC'd since this infrastructure is
>_really_ nice for doing things generically with device tree. The
>ability to add new linker-section-based tables without having to
>manually hack up linker script templates will make it so we can do
>things like adding tables for cache controllers or mmus (that are
>needed quite early in init and can't go through the platform device
>system).
>
>BTW we kinda lucked out that there was already the linker table
>infrastructure for cpu enable methods for smp; this patch series makes
>it so future stuff doesn't have to rely on luck or invasive changes.
>
>Rich

Incidentally, I want to use this for the RAID algorithms.
-- 
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 0/7] tools: add linker table userspace sandbox
  2016-08-21  4:59         ` Rich Felker
                           ` (2 preceding siblings ...)
  (?)
@ 2016-08-22  4:04         ` H. Peter Anvin
  -1 siblings, 0 replies; 480+ messages in thread
From: H. Peter Anvin @ 2016-08-22  4:04 UTC (permalink / raw)
  To: Rich Felker, Rob Landley

mcgrof@kernel.org,acme@redhat.com,tglx@linutronix.de,mingo@redhat.com,jpoimboe@redhat.com,bp@alien8.de,linux@arm.linux.org.uk,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,x86@kernel.org,luto@amacapital.net,keescook@chromium.org,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,ananth@in.ibm.com,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.i
 ntel.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@ra!
 smusville
moes.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,paulus@samba.org,mpe@ellerman.id.au,James.Bottomley@HansenPartnership.com
Message-ID: <5150EFE4-3E00-4BD2-AE6F-F99FBBC74273@zytor.com>

On August 20, 2016 9:59:59 PM PDT, Rich Felker <dalias@libc.org> wrote:
>On Fri, Aug 19, 2016 at 11:57:18PM -0500, Rob Landley wrote:
>> On 08/19/2016 04:41 PM, mcgrof@kernel.org wrote:
>> > Please let me know if there are any issue or questions.
>> 
>> Only that this has been the majority of the traffic on the linux-sh
>> mailing list for over a month and I'm still not sure why anyone
>should care.
>> 
>> I have no idea what problem it solves, despite reading a couple dozen
>> messages in the thread, and the most recent two 0/x intro messages.
>Its
>> purpose seems to be ensuring that lld.llvm.org has more work to do if
>it
>> ever wants to build the kernel without binutils?
>> 
>> I also am not certain why every revision of it is cc'd to linux-sh.
>Is
>> it generic linker infrastructure change, or is it something that
>affects
>> this architecture specifically? As far as I can tell nothing in this
>> most recent 7-patch series touches arch/sh at all, you just cc'd our
>> list because you think the work you're doing is _important_, not that
>> it's specifically relevant to us.
>
>Incidentally I'm happy to have been CC'd since this infrastructure is
>_really_ nice for doing things generically with device tree. The
>ability to add new linker-section-based tables without having to
>manually hack up linker script templates will make it so we can do
>things like adding tables for cache controllers or mmus (that are
>needed quite early in init and can't go through the platform device
>system).
>
>BTW we kinda lucked out that there was already the linker table
>infrastructure for cpu enable methods for smp; this patch series makes
>it so future stuff doesn't have to rely on luck or invasive changes.
>
>Rich

Incidentally, I want to use this for the RAID algorithms.
-- 
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 0/7] tools: add linker table userspace sandbox
@ 2016-08-22  4:04           ` H. Peter Anvin
  0 siblings, 0 replies; 480+ messages in thread
From: H. Peter Anvin @ 2016-08-22  4:04 UTC (permalink / raw)
  To: Rich Felker, Rob Landley

mcgrof@kernel.org,acme@redhat.com,tglx@linutronix.de,mingo@redhat.com,jpoimboe@redhat.com,bp@alien8.de,linux@arm.linux.org.uk,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,x86@kernel.org,luto@amacapital.net,keescook@chromium.org,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,ananth@in.ibm.com,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@ra!
 smusville
moes.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,paulus@samba.org,mpe@ellerman.id.au,James.Bottomley@HansenPartnership.com
Message-ID: <5150EFE4-3E00-4BD2-AE6F-F99FBBC74273@zytor.com>

On August 20, 2016 9:59:59 PM PDT, Rich Felker <dalias@libc.org> wrote:
>On Fri, Aug 19, 2016 at 11:57:18PM -0500, Rob Landley wrote:
>> On 08/19/2016 04:41 PM, mcgrof@kernel.org wrote:
>> > Please let me know if there are any issue or questions.
>> 
>> Only that this has been the majority of the traffic on the linux-sh
>> mailing list for over a month and I'm still not sure why anyone
>should care.
>> 
>> I have no idea what problem it solves, despite reading a couple dozen
>> messages in the thread, and the most recent two 0/x intro messages.
>Its
>> purpose seems to be ensuring that lld.llvm.org has more work to do if
>it
>> ever wants to build the kernel without binutils?
>> 
>> I also am not certain why every revision of it is cc'd to linux-sh.
>Is
>> it generic linker infrastructure change, or is it something that
>affects
>> this architecture specifically? As far as I can tell nothing in this
>> most recent 7-patch series touches arch/sh at all, you just cc'd our
>> list because you think the work you're doing is _important_, not that
>> it's specifically relevant to us.
>
>Incidentally I'm happy to have been CC'd since this infrastructure is
>_really_ nice for doing things generically with device tree. The
>ability to add new linker-section-based tables without having to
>manually hack up linker script templates will make it so we can do
>things like adding tables for cache controllers or mmus (that are
>needed quite early in init and can't go through the platform device
>system).
>
>BTW we kinda lucked out that there was already the linker table
>infrastructure for cpu enable methods for smp; this patch series makes
>it so future stuff doesn't have to rely on luck or invasive changes.
>
>Rich

Incidentally, I want to use this for the RAID algorithms.
-- 
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 0/7] tools: add linker table userspace sandbox
  2016-08-21  4:59         ` Rich Felker
                           ` (3 preceding siblings ...)
  (?)
@ 2016-08-22  4:04         ` H. Peter Anvin
  -1 siblings, 0 replies; 480+ messages in thread
From: H. Peter Anvin @ 2016-08-22  4:04 UTC (permalink / raw)
  To: Rich Felker, Rob Landley

mcgrof@kernel.org,acme@redhat.com,tglx@linutronix.de,mingo@redhat.com,jpoimboe@redhat.com,bp@alien8.de,linux@arm.linux.org.uk,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,x86@kernel.org,luto@amacapital.net,keescook@chromium.org,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,ananth@in.ibm.com,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.i
 ntel.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@ra!
 smusville
moes.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,paulus@samba.org,mpe@ellerman.id.au,James.Bottomley@HansenPartnership.com
Message-ID: <5150EFE4-3E00-4BD2-AE6F-F99FBBC74273@zytor.com>

On August 20, 2016 9:59:59 PM PDT, Rich Felker <dalias@libc.org> wrote:
>On Fri, Aug 19, 2016 at 11:57:18PM -0500, Rob Landley wrote:
>> On 08/19/2016 04:41 PM, mcgrof@kernel.org wrote:
>> > Please let me know if there are any issue or questions.
>> 
>> Only that this has been the majority of the traffic on the linux-sh
>> mailing list for over a month and I'm still not sure why anyone
>should care.
>> 
>> I have no idea what problem it solves, despite reading a couple dozen
>> messages in the thread, and the most recent two 0/x intro messages.
>Its
>> purpose seems to be ensuring that lld.llvm.org has more work to do if
>it
>> ever wants to build the kernel without binutils?
>> 
>> I also am not certain why every revision of it is cc'd to linux-sh.
>Is
>> it generic linker infrastructure change, or is it something that
>affects
>> this architecture specifically? As far as I can tell nothing in this
>> most recent 7-patch series touches arch/sh at all, you just cc'd our
>> list because you think the work you're doing is _important_, not that
>> it's specifically relevant to us.
>
>Incidentally I'm happy to have been CC'd since this infrastructure is
>_really_ nice for doing things generically with device tree. The
>ability to add new linker-section-based tables without having to
>manually hack up linker script templates will make it so we can do
>things like adding tables for cache controllers or mmus (that are
>needed quite early in init and can't go through the platform device
>system).
>
>BTW we kinda lucked out that there was already the linker table
>infrastructure for cpu enable methods for smp; this patch series makes
>it so future stuff doesn't have to rely on luck or invasive changes.
>
>Rich

Incidentally, I want to use this for the RAID algorithms.
-- 
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 0/7] tools: add linker table userspace sandbox
  2016-08-21  4:59         ` Rich Felker
                           ` (4 preceding siblings ...)
  (?)
@ 2016-08-22  4:04         ` H. Peter Anvin
  -1 siblings, 0 replies; 480+ messages in thread
From: H. Peter Anvin @ 2016-08-22  4:04 UTC (permalink / raw)
  To: Rich Felker, Rob Landley

mcgrof@kernel.org,acme@redhat.com,tglx@linutronix.de,mingo@redhat.com,jpoimboe@redhat.com,bp@alien8.de,linux@arm.linux.org.uk,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,x86@kernel.org,luto@amacapital.net,keescook@chromium.org,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,ananth@in.ibm.com,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@ra!
 smusville
moes.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,paulus@samba.org,mpe@ellerman.id.au,James.Bottomley@HansenPartnership.com
Message-ID: <5150EFE4-3E00-4BD2-AE6F-F99FBBC74273@zytor.com>

On August 20, 2016 9:59:59 PM PDT, Rich Felker <dalias@libc.org> wrote:
>On Fri, Aug 19, 2016 at 11:57:18PM -0500, Rob Landley wrote:
>> On 08/19/2016 04:41 PM, mcgrof@kernel.org wrote:
>> > Please let me know if there are any issue or questions.
>> 
>> Only that this has been the majority of the traffic on the linux-sh
>> mailing list for over a month and I'm still not sure why anyone
>should care.
>> 
>> I have no idea what problem it solves, despite reading a couple dozen
>> messages in the thread, and the most recent two 0/x intro messages.
>Its
>> purpose seems to be ensuring that lld.llvm.org has more work to do if
>it
>> ever wants to build the kernel without binutils?
>> 
>> I also am not certain why every revision of it is cc'd to linux-sh.
>Is
>> it generic linker infrastructure change, or is it something that
>affects
>> this architecture specifically? As far as I can tell nothing in this
>> most recent 7-patch series touches arch/sh at all, you just cc'd our
>> list because you think the work you're doing is _important_, not that
>> it's specifically relevant to us.
>
>Incidentally I'm happy to have been CC'd since this infrastructure is
>_really_ nice for doing things generically with device tree. The
>ability to add new linker-section-based tables without having to
>manually hack up linker script templates will make it so we can do
>things like adding tables for cache controllers or mmus (that are
>needed quite early in init and can't go through the platform device
>system).
>
>BTW we kinda lucked out that there was already the linker table
>infrastructure for cpu enable methods for smp; this patch series makes
>it so future stuff doesn't have to rely on luck or invasive changes.
>
>Rich

Incidentally, I want to use this for the RAID algorithms.
-- 
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 0/7] tools: add linker table userspace sandbox
  2016-08-19 21:41     ` mcgrof
                       ` (9 preceding siblings ...)
  (?)
@ 2016-08-22  9:59     ` Vegard Nossum
  2016-08-23 15:49       ` Luis R. Rodriguez
  -1 siblings, 1 reply; 480+ messages in thread
From: Vegard Nossum @ 2016-08-22  9:59 UTC (permalink / raw)
  To: Luis R. Rodriguez; +Cc: linux-arch, kbuild, LKML

(trimmed Ccs... jeez)

On 19 August 2016 at 23:41,  <mcgrof@kernel.org> wrote:
> From: "Luis R. Rodriguez" <mcgrof@kernel.org>
>
> The original v3 series for linker tables made reference only to
> an external repository userspace sandbox application, however
> Boris noted it'd be difficult ot keep this in sync with the
> kernel so advised to consider integrate with the kernel. I've
> taken steps in this direction.
[...]
> Please let me know if there are any issue or questions.

+#define __VMLINUX_SYMBOL(x) x

+#define VMLINUX_SYMBOL(x) __VMLINUX_SYMBOL(x)

+#define LINUX_SECTION_START(name)      VMLINUX_SYMBOL(name)

+#define DECLARE_LINUX_SECTION(type, name)                              \
+        extern type VMLINUX_SYMBOL(name)[], \
+                    VMLINUX_SYMBOL(name##__end)[]

+#define DECLARE_LINKTABLE(type, name)                                  \
+       DECLARE_LINUX_SECTION(type, name)

+#define LINKTABLE_FOR_EACH(pointer, tbl)                               \
+       for (pointer = LINUX_SECTION_START(tbl);                        \
+            pointer < LINUX_SECTION_END(tbl);                          \
+            pointer++)

I think this is subject to getting optimised out by newer gccs, since
it sees the START(tbl) and END(tbl) symbols as two completely
different arrays. See the short discussion here:

https://lkml.org/lkml/2016/6/26/73 (the first attempt is wrong, so
don't look at that)

It is possible that < is different from != and always does the right
thing, but I haven't checked.

I have a WIP branch that converts most of the existing tables in the
kernel to use the external_array() macro which makes gcc throw away
any knowledge it had about a pointer being part of an array.


Vegard

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 14/16] kprobes: move kprobe declarations to asm-generic/kprobes.h
  2016-08-19 21:34     ` mcgrof
  (?)
@ 2016-08-22 15:11       ` Masami Hiramatsu
  -1 siblings, 0 replies; 480+ messages in thread
From: Masami Hiramatsu @ 2016-08-22 15:11 UTC (permalink / raw)
  To: mcgrof
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, heiko.carstens,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	mpe, hpa, masami.hiramatsu.pt, mchehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, linux, linux-sh,
	will.deacon, korea.drzix, x86, anil.s.keshavamurthy, fontana,
	torvalds, mingo, linux-arm-kernel, catalin.marinas, dvhart,
	linux-xtensa, pali.rohar, keescook, arnd, realmz6

On Fri, 19 Aug 2016 14:34:12 -0700
mcgrof@kernel.org wrote:

> From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> 
> Often all is needed is these small helpers, instead of compiler.h
> or a full kprobes.h. This is important for asm helpers, in fact even
> some asm/kprobes.h make use of these helpers... instead just keep a
> generic asm file with helpers useful for asm code with the least amount
> of clutter as possible.
> 
> Likewise we need now to also address what to do about this file for both
> when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
> for when architectures have CONFIG_HAVE_KPROBES but have disabled
> CONFIG_KPROBES.
> 
> Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
> this means most architecture code cannot include asm/kprobes.h safely.
> Correct this and add guards for architectures missing them. Additionally
> provide architectures that not have kprobes support with the default
> asm-generic solution. This lets us force asm/kprobes.h on the header
> include/linux/kprobes.h always, but most importantly we can now safely
> include just asm/kprobes.h on architecture code without bringing
> the full kitchen sink of header files.
> 
> Two architectures already provided a guard against CONFIG_KPROBES on
> its kprobes.h: sh, arch. The rest of the architectures needed gaurds
> added. We avoid including any not-needed headers on asm/kprobes.h
> unless kprobes have been enabled.
> 
> In a subsequent atomic change we can try now to remove compiler.h from
> include/linux/kprobes.h.

Hmm, this looks a bit overkill... I rather like move it into linux/table.h.

Thanks,

> 
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  arch/alpha/include/asm/Kbuild      |  1 +
>  arch/arc/include/asm/kprobes.h     |  6 ++++--
>  arch/arm/include/asm/kprobes.h     |  4 ++++
>  arch/arm/probes/decode.h           |  1 +
>  arch/arm64/include/asm/kprobes.h   |  4 ++++
>  arch/arm64/kernel/insn.c           |  1 +
>  arch/avr32/include/asm/kprobes.h   |  4 ++++
>  arch/blackfin/include/asm/Kbuild   |  1 +
>  arch/c6x/include/asm/Kbuild        |  1 +
>  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/kprobes.h    |  7 ++++++-
>  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/kprobes.h    |  6 +++++-
>  arch/mn10300/include/asm/kprobes.h |  4 ++++
>  arch/nios2/include/asm/Kbuild      |  1 +
>  arch/openrisc/include/asm/Kbuild   |  1 +
>  arch/parisc/include/asm/Kbuild     |  1 +
>  arch/powerpc/include/asm/kprobes.h |  6 ++++++
>  arch/s390/include/asm/kprobes.h    |  4 ++++
>  arch/score/include/asm/Kbuild      |  1 +
>  arch/sh/include/asm/kprobes.h      |  2 ++
>  arch/sparc/include/asm/kprobes.h   |  5 +++++
>  arch/tile/include/asm/kprobes.h    |  6 +++++-
>  arch/um/include/asm/Kbuild         |  1 +
>  arch/unicore32/include/asm/Kbuild  |  1 +
>  arch/x86/include/asm/kprobes.h     |  6 ++++++
>  arch/xtensa/include/asm/Kbuild     |  1 +
>  include/asm-generic/kprobes.h      | 25 +++++++++++++++++++++++++
>  include/linux/compiler.h           |  8 --------
>  include/linux/kprobes.h            | 19 +++----------------
>  36 files changed, 107 insertions(+), 29 deletions(-)
>  create mode 100644 include/asm-generic/kprobes.h
> 
> diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
> index f3bdc31d3c97..54d388fd026f 100644
> --- a/arch/alpha/include/asm/Kbuild
> +++ b/arch/alpha/include/asm/Kbuild
> @@ -13,3 +13,4 @@ generic-y += trace_clock.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/arc/include/asm/kprobes.h b/arch/arc/include/asm/kprobes.h
> index 944dbedb38b5..00bdbe167615 100644
> --- a/arch/arc/include/asm/kprobes.h
> +++ b/arch/arc/include/asm/kprobes.h
> @@ -9,6 +9,8 @@
>  #ifndef _ARC_KPROBES_H
>  #define _ARC_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
>  #ifdef CONFIG_KPROBES
>  
>  typedef u16 kprobe_opcode_t;
> @@ -55,6 +57,6 @@ void trap_is_kprobe(unsigned long address, struct pt_regs *regs);
>  static void trap_is_kprobe(unsigned long address, struct pt_regs *regs)
>  {
>  }
> -#endif
> +#endif /* CONFIG_KPROBES */
>  
> -#endif
> +#endif /* _ARC_KPROBES_H */
> diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
> index 3ea9be559726..59655459da59 100644
> --- a/arch/arm/include/asm/kprobes.h
> +++ b/arch/arm/include/asm/kprobes.h
> @@ -16,6 +16,9 @@
>  #ifndef _ARM_KPROBES_H
>  #define _ARM_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/types.h>
>  #include <linux/ptrace.h>
>  #include <linux/notifier.h>
> @@ -83,4 +86,5 @@ struct arch_optimized_insn {
>  	 */
>  };
>  
> +#endif /* CONFIG_KPROBES */
>  #endif /* _ARM_KPROBES_H */
> diff --git a/arch/arm/probes/decode.h b/arch/arm/probes/decode.h
> index f9b08ba7fe73..548d622a3159 100644
> --- a/arch/arm/probes/decode.h
> +++ b/arch/arm/probes/decode.h
> @@ -22,6 +22,7 @@
>  #include <linux/types.h>
>  #include <linux/stddef.h>
>  #include <asm/probes.h>
> +#include <asm/kprobes.h>
>  
>  void __init arm_probes_decode_init(void);
>  
> diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
> index 1737aecfcc5e..6deb8d726041 100644
> --- a/arch/arm64/include/asm/kprobes.h
> +++ b/arch/arm64/include/asm/kprobes.h
> @@ -16,6 +16,9 @@
>  #ifndef _ARM_KPROBES_H
>  #define _ARM_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/types.h>
>  #include <linux/ptrace.h>
>  #include <linux/percpu.h>
> @@ -57,4 +60,5 @@ int kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr);
>  void kretprobe_trampoline(void);
>  void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
>  
> +#endif /* CONFIG_KPROBES */
>  #endif /* _ARM_KPROBES_H */
> diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
> index 63f9432d05e8..cc38f3241927 100644
> --- a/arch/arm64/kernel/insn.c
> +++ b/arch/arm64/kernel/insn.c
> @@ -32,6 +32,7 @@
>  #include <asm/fixmap.h>
>  #include <asm/opcodes.h>
>  #include <asm/insn.h>
> +#include <asm/kprobes.h>
>  
>  #define AARCH64_INSN_SF_BIT	BIT(31)
>  #define AARCH64_INSN_N_BIT	BIT(22)
> diff --git a/arch/avr32/include/asm/kprobes.h b/arch/avr32/include/asm/kprobes.h
> index 45f563ed73fd..09f39d8749ea 100644
> --- a/arch/avr32/include/asm/kprobes.h
> +++ b/arch/avr32/include/asm/kprobes.h
> @@ -11,6 +11,9 @@
>  #ifndef __ASM_AVR32_KPROBES_H
>  #define __ASM_AVR32_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/types.h>
>  
>  typedef u16	kprobe_opcode_t;
> @@ -46,4 +49,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
>  
>  #define flush_insn_slot(p)	do { } while (0)
>  
> +#endif /* CONFIG_KPROBES */
>  #endif /* __ASM_AVR32_KPROBES_H */
> diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
> index b71893b1cd53..f56a68697353 100644
> --- a/arch/blackfin/include/asm/Kbuild
> +++ b/arch/blackfin/include/asm/Kbuild
> @@ -51,3 +51,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
> index cede2a950fbf..c54f7cc1f63e 100644
> --- a/arch/c6x/include/asm/Kbuild
> +++ b/arch/c6x/include/asm/Kbuild
> @@ -64,3 +64,4 @@ generic-y += word-at-a-time.h
>  generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
> +generic-y += kprobes.h
> diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
> index 7062c1be7913..051d355feae3 100644
> --- a/arch/cris/include/asm/Kbuild
> +++ b/arch/cris/include/asm/Kbuild
> @@ -48,3 +48,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
> index 4a59cbda5091..b58b9fc49383 100644
> --- a/arch/frv/include/asm/Kbuild
> +++ b/arch/frv/include/asm/Kbuild
> @@ -11,3 +11,4 @@ generic-y += word-at-a-time.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
> index d79968d93c12..cfca7de52b37 100644
> --- a/arch/h8300/include/asm/Kbuild
> +++ b/arch/h8300/include/asm/Kbuild
> @@ -78,3 +78,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
> index d59ac1c1858b..d7cc35451f30 100644
> --- a/arch/hexagon/include/asm/Kbuild
> +++ b/arch/hexagon/include/asm/Kbuild
> @@ -63,3 +63,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/ia64/include/asm/kprobes.h b/arch/ia64/include/asm/kprobes.h
> index d5505d6f2382..36999c55f3f2 100644
> --- a/arch/ia64/include/asm/kprobes.h
> +++ b/arch/ia64/include/asm/kprobes.h
> @@ -23,6 +23,10 @@
>   * 2005-Apr     Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
>   *              <anil.s.keshavamurthy@intel.com> adapted from i386
>   */
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
> +
>  #include <linux/types.h>
>  #include <linux/ptrace.h>
>  #include <linux/percpu.h>
> @@ -124,4 +128,5 @@ extern void invalidate_stacked_regs(void);
>  extern void flush_register_stack(void);
>  extern void arch_remove_kprobe(struct kprobe *p);
>  
> -#endif				/* _ASM_KPROBES_H */
> +#endif /* CONFIG_KPROBES */
> +#endif /* _ASM_KPROBES_H */
> diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
> index 24088f3c733c..198ad591ab41 100644
> --- a/arch/m32r/include/asm/Kbuild
> +++ b/arch/m32r/include/asm/Kbuild
> @@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
> index 65c0df17f70e..ae86bb91e13b 100644
> --- a/arch/m68k/include/asm/Kbuild
> +++ b/arch/m68k/include/asm/Kbuild
> @@ -38,3 +38,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
> index 2538224899fd..10f36ed301e1 100644
> --- a/arch/metag/include/asm/Kbuild
> +++ b/arch/metag/include/asm/Kbuild
> @@ -59,3 +59,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
> index 01afb1b420f5..865ce3d96443 100644
> --- a/arch/microblaze/include/asm/Kbuild
> +++ b/arch/microblaze/include/asm/Kbuild
> @@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/mips/include/asm/kprobes.h b/arch/mips/include/asm/kprobes.h
> index daba1f9a4f79..291846d9ba83 100644
> --- a/arch/mips/include/asm/kprobes.h
> +++ b/arch/mips/include/asm/kprobes.h
> @@ -22,6 +22,9 @@
>  #ifndef _ASM_KPROBES_H
>  #define _ASM_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/ptrace.h>
>  #include <linux/types.h>
>  
> @@ -94,4 +97,5 @@ struct kprobe_ctlblk {
>  extern int kprobe_exceptions_notify(struct notifier_block *self,
>  				    unsigned long val, void *data);
>  
> -#endif				/* _ASM_KPROBES_H */
> +#endif /* CONFIG_KPROBES */
> +#endif /* _ASM_KPROBES_H */
> diff --git a/arch/mn10300/include/asm/kprobes.h b/arch/mn10300/include/asm/kprobes.h
> index c800b590183a..5729bb5b972a 100644
> --- a/arch/mn10300/include/asm/kprobes.h
> +++ b/arch/mn10300/include/asm/kprobes.h
> @@ -21,6 +21,9 @@
>  #ifndef _ASM_KPROBES_H
>  #define _ASM_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/types.h>
>  #include <linux/ptrace.h>
>  
> @@ -47,4 +50,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
>  
>  extern void arch_remove_kprobe(struct kprobe *p);
>  
> +#endif /* CONFIG_KPROBES */
>  #endif /* _ASM_KPROBES_H */
> diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
> index ee6220dac1e8..d6ce7edee7e0 100644
> --- a/arch/nios2/include/asm/Kbuild
> +++ b/arch/nios2/include/asm/Kbuild
> @@ -66,3 +66,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
> index ceafe458e295..1bf89a67317c 100644
> --- a/arch/openrisc/include/asm/Kbuild
> +++ b/arch/openrisc/include/asm/Kbuild
> @@ -74,3 +74,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
> index 99211477bfb2..982886ba812a 100644
> --- a/arch/parisc/include/asm/Kbuild
> +++ b/arch/parisc/include/asm/Kbuild
> @@ -32,3 +32,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h
> index 2c9759bdb63b..e5d0dc5c6236 100644
> --- a/arch/powerpc/include/asm/kprobes.h
> +++ b/arch/powerpc/include/asm/kprobes.h
> @@ -1,5 +1,9 @@
>  #ifndef _ASM_POWERPC_KPROBES_H
>  #define _ASM_POWERPC_KPROBES_H
> +
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #ifdef __KERNEL__
>  /*
>   *  Kernel Probes (KProbes)
> @@ -127,5 +131,7 @@ struct kprobe_ctlblk {
>  extern int kprobe_exceptions_notify(struct notifier_block *self,
>  					unsigned long val, void *data);
>  extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
> +
>  #endif /* __KERNEL__ */
> +#endif /* CONFIG_KPROBES */
>  #endif	/* _ASM_POWERPC_KPROBES_H */
> diff --git a/arch/s390/include/asm/kprobes.h b/arch/s390/include/asm/kprobes.h
> index 591e5a5279b0..dc12b0135007 100644
> --- a/arch/s390/include/asm/kprobes.h
> +++ b/arch/s390/include/asm/kprobes.h
> @@ -27,6 +27,9 @@
>   * 2005-Dec	Used as a template for s390 by Mike Grundy
>   *		<grundym@us.ibm.com>
>   */
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/types.h>
>  #include <linux/ptrace.h>
>  #include <linux/percpu.h>
> @@ -91,4 +94,5 @@ int probe_is_insn_relative_long(u16 *insn);
>  
>  #define flush_insn_slot(p)	do { } while (0)
>  
> +#endif /* CONFIG_KPROBES */
>  #endif	/* _ASM_S390_KPROBES_H */
> diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
> index 16ea15a3e432..6ac8a7f5c768 100644
> --- a/arch/score/include/asm/Kbuild
> +++ b/arch/score/include/asm/Kbuild
> @@ -17,3 +17,4 @@ generic-y += word-at-a-time.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h
> index 134f3980e44a..0b9a54016eeb 100644
> --- a/arch/sh/include/asm/kprobes.h
> +++ b/arch/sh/include/asm/kprobes.h
> @@ -1,6 +1,8 @@
>  #ifndef __ASM_SH_KPROBES_H
>  #define __ASM_SH_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
>  #ifdef CONFIG_KPROBES
>  
>  #include <linux/types.h>
> diff --git a/arch/sparc/include/asm/kprobes.h b/arch/sparc/include/asm/kprobes.h
> index a145d798e112..8c4cd15395f6 100644
> --- a/arch/sparc/include/asm/kprobes.h
> +++ b/arch/sparc/include/asm/kprobes.h
> @@ -1,6 +1,9 @@
>  #ifndef _SPARC64_KPROBES_H
>  #define _SPARC64_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/types.h>
>  #include <linux/percpu.h>
>  
> @@ -48,4 +51,6 @@ int kprobe_exceptions_notify(struct notifier_block *self,
>  int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
>  asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
>  				      struct pt_regs *regs);
> +
> +#endif /* CONFIG_KPROBES */
>  #endif /* _SPARC64_KPROBES_H */
> diff --git a/arch/tile/include/asm/kprobes.h b/arch/tile/include/asm/kprobes.h
> index d8f9a83943b1..4a8b1cadca24 100644
> --- a/arch/tile/include/asm/kprobes.h
> +++ b/arch/tile/include/asm/kprobes.h
> @@ -17,10 +17,13 @@
>  #ifndef _ASM_TILE_KPROBES_H
>  #define _ASM_TILE_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
> +
>  #include <linux/types.h>
>  #include <linux/ptrace.h>
>  #include <linux/percpu.h>
> -
>  #include <arch/opcode.h>
>  
>  #define __ARCH_WANT_KPROBES_INSN_SLOT
> @@ -76,4 +79,5 @@ void arch_remove_kprobe(struct kprobe *);
>  extern int kprobe_exceptions_notify(struct notifier_block *self,
>  			     unsigned long val, void *data);
>  
> +#endif /* CONFIG_KPROBES */
>  #endif /* _ASM_TILE_KPROBES_H */
> diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
> index eea5dd842992..f0314517090b 100644
> --- a/arch/um/include/asm/Kbuild
> +++ b/arch/um/include/asm/Kbuild
> @@ -30,3 +30,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
> index 5c31eafbf1fd..32321579011b 100644
> --- a/arch/unicore32/include/asm/Kbuild
> +++ b/arch/unicore32/include/asm/Kbuild
> @@ -66,3 +66,4 @@ generic-y += word-at-a-time.h
>  generic-y += xor.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h
> index d1d1e5094c28..95c480dc8570 100644
> --- a/arch/x86/include/asm/kprobes.h
> +++ b/arch/x86/include/asm/kprobes.h
> @@ -21,6 +21,10 @@
>   *
>   * See arch/x86/kernel/kprobes.c for x86 kprobes history.
>   */
> +
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/types.h>
>  #include <linux/ptrace.h>
>  #include <linux/percpu.h>
> @@ -116,4 +120,6 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
>  				    unsigned long val, void *data);
>  extern int kprobe_int3_handler(struct pt_regs *regs);
>  extern int kprobe_debug_handler(struct pt_regs *regs);
> +
> +#endif /* CONFIG_KPROBES */
>  #endif /* _ASM_X86_KPROBES_H */
> diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
> index ae48f8fd9212..bf0e40100fda 100644
> --- a/arch/xtensa/include/asm/Kbuild
> +++ b/arch/xtensa/include/asm/Kbuild
> @@ -34,3 +34,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
> new file mode 100644
> index 000000000000..57af9f21d148
> --- /dev/null
> +++ b/include/asm-generic/kprobes.h
> @@ -0,0 +1,25 @@
> +#ifndef _ASM_GENERIC_KPROBES_H
> +#define _ASM_GENERIC_KPROBES_H
> +
> +#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
> +#ifdef CONFIG_KPROBES
> +/*
> + * Blacklist ganerating macro. Specify functions which is not probed
> + * by using this macro.
> + */
> +# define __NOKPROBE_SYMBOL(fname)				\
> +static unsigned long __used					\
> +	__attribute__((__section__("_kprobe_blacklist")))	\
> +	_kbl_addr_##fname = (unsigned long)fname;
> +# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
> +/* Use this to forbid a kprobes attach on very low level functions */
> +# define __kprobes	__attribute__((__section__(".kprobes.text")))
> +# define nokprobe_inline	__always_inline
> +#else
> +# define NOKPROBE_SYMBOL(fname)
> +# define __kprobes
> +# define nokprobe_inline	inline
> +#endif
> +#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
> +
> +#endif /* _ASM_GENERIC_KPROBES_H */
> diff --git a/include/linux/compiler.h b/include/linux/compiler.h
> index 1eed7f5e137d..4736dc5741e4 100644
> --- a/include/linux/compiler.h
> +++ b/include/linux/compiler.h
> @@ -542,12 +542,4 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
>  	(_________p1); \
>  })
>  
> -/* Ignore/forbid kprobes attach on very low level functions marked by this attribute: */
> -#ifdef CONFIG_KPROBES
> -# define __kprobes	__attribute__((__section__(".kprobes.text")))
> -# define nokprobe_inline	__always_inline
> -#else
> -# define __kprobes
> -# define nokprobe_inline	inline
> -#endif
>  #endif /* __LINUX_COMPILER_H */
> diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
> index 8f6849084248..985ed79ef431 100644
> --- a/include/linux/kprobes.h
> +++ b/include/linux/kprobes.h
> @@ -29,7 +29,7 @@
>   *		<jkenisto@us.ibm.com>  and Prasanna S Panchamukhi
>   *		<prasanna@in.ibm.com> added function-return probes.
>   */
> -#include <linux/compiler.h>	/* for __kprobes */
> +#include <linux/compiler.h>
>  #include <linux/linkage.h>
>  #include <linux/list.h>
>  #include <linux/notifier.h>
> @@ -40,9 +40,9 @@
>  #include <linux/rcupdate.h>
>  #include <linux/mutex.h>
>  #include <linux/ftrace.h>
> +#include <asm/kprobes.h>
>  
>  #ifdef CONFIG_KPROBES
> -#include <asm/kprobes.h>
>  
>  /* kprobe_status settings */
>  #define KPROBE_HIT_ACTIVE	0x00000001
> @@ -51,6 +51,7 @@
>  #define KPROBE_HIT_SSDONE	0x00000008
>  
>  #else /* CONFIG_KPROBES */
> +#include <asm-generic/kprobes.h>
>  typedef int kprobe_opcode_t;
>  struct arch_specific_insn {
>  	int dummy;
> @@ -481,18 +482,4 @@ static inline int enable_jprobe(struct jprobe *jp)
>  	return enable_kprobe(&jp->kp);
>  }
>  
> -#ifdef CONFIG_KPROBES
> -/*
> - * Blacklist ganerating macro. Specify functions which is not probed
> - * by using this macro.
> - */
> -#define __NOKPROBE_SYMBOL(fname)			\
> -static unsigned long __used				\
> -	__attribute__((section("_kprobe_blacklist")))	\
> -	_kbl_addr_##fname = (unsigned long)fname;
> -#define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
> -#else
> -#define NOKPROBE_SYMBOL(fname)
> -#endif
> -
>  #endif /* _LINUX_KPROBES_H */
> -- 
> 2.9.2
> 


-- 
Masami Hiramatsu <mhiramat@kernel.org>

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 14/16] kprobes: move kprobe declarations to asm-generic/kprobes.h
@ 2016-08-22 15:11       ` Masami Hiramatsu
  0 siblings, 0 replies; 480+ messages in thread
From: Masami Hiramatsu @ 2016-08-22 15:11 UTC (permalink / raw)
  To: mcgrof
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, heiko.carstens,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	mpe, hpa, masami.hiramatsu.pt, mchehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, linux, linux-sh,
	will.deacon, korea.drzix, x86, anil.s.keshavamurthy, fontana,
	torvalds, mingo, linux-arm-kernel, catalin.marinas, dvhart,
	linux-xtensa, pali.rohar, keescook, arnd, realmz6

On Fri, 19 Aug 2016 14:34:12 -0700
mcgrof@kernel.org wrote:

> From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> 
> Often all is needed is these small helpers, instead of compiler.h
> or a full kprobes.h. This is important for asm helpers, in fact even
> some asm/kprobes.h make use of these helpers... instead just keep a
> generic asm file with helpers useful for asm code with the least amount
> of clutter as possible.
> 
> Likewise we need now to also address what to do about this file for both
> when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
> for when architectures have CONFIG_HAVE_KPROBES but have disabled
> CONFIG_KPROBES.
> 
> Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
> this means most architecture code cannot include asm/kprobes.h safely.
> Correct this and add guards for architectures missing them. Additionally
> provide architectures that not have kprobes support with the default
> asm-generic solution. This lets us force asm/kprobes.h on the header
> include/linux/kprobes.h always, but most importantly we can now safely
> include just asm/kprobes.h on architecture code without bringing
> the full kitchen sink of header files.
> 
> Two architectures already provided a guard against CONFIG_KPROBES on
> its kprobes.h: sh, arch. The rest of the architectures needed gaurds
> added. We avoid including any not-needed headers on asm/kprobes.h
> unless kprobes have been enabled.
> 
> In a subsequent atomic change we can try now to remove compiler.h from
> include/linux/kprobes.h.

Hmm, this looks a bit overkill... I rather like move it into linux/table.h.

Thanks,

> 
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  arch/alpha/include/asm/Kbuild      |  1 +
>  arch/arc/include/asm/kprobes.h     |  6 ++++--
>  arch/arm/include/asm/kprobes.h     |  4 ++++
>  arch/arm/probes/decode.h           |  1 +
>  arch/arm64/include/asm/kprobes.h   |  4 ++++
>  arch/arm64/kernel/insn.c           |  1 +
>  arch/avr32/include/asm/kprobes.h   |  4 ++++
>  arch/blackfin/include/asm/Kbuild   |  1 +
>  arch/c6x/include/asm/Kbuild        |  1 +
>  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/kprobes.h    |  7 ++++++-
>  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/kprobes.h    |  6 +++++-
>  arch/mn10300/include/asm/kprobes.h |  4 ++++
>  arch/nios2/include/asm/Kbuild      |  1 +
>  arch/openrisc/include/asm/Kbuild   |  1 +
>  arch/parisc/include/asm/Kbuild     |  1 +
>  arch/powerpc/include/asm/kprobes.h |  6 ++++++
>  arch/s390/include/asm/kprobes.h    |  4 ++++
>  arch/score/include/asm/Kbuild      |  1 +
>  arch/sh/include/asm/kprobes.h      |  2 ++
>  arch/sparc/include/asm/kprobes.h   |  5 +++++
>  arch/tile/include/asm/kprobes.h    |  6 +++++-
>  arch/um/include/asm/Kbuild         |  1 +
>  arch/unicore32/include/asm/Kbuild  |  1 +
>  arch/x86/include/asm/kprobes.h     |  6 ++++++
>  arch/xtensa/include/asm/Kbuild     |  1 +
>  include/asm-generic/kprobes.h      | 25 +++++++++++++++++++++++++
>  include/linux/compiler.h           |  8 --------
>  include/linux/kprobes.h            | 19 +++----------------
>  36 files changed, 107 insertions(+), 29 deletions(-)
>  create mode 100644 include/asm-generic/kprobes.h
> 
> diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
> index f3bdc31d3c97..54d388fd026f 100644
> --- a/arch/alpha/include/asm/Kbuild
> +++ b/arch/alpha/include/asm/Kbuild
> @@ -13,3 +13,4 @@ generic-y += trace_clock.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/arc/include/asm/kprobes.h b/arch/arc/include/asm/kprobes.h
> index 944dbedb38b5..00bdbe167615 100644
> --- a/arch/arc/include/asm/kprobes.h
> +++ b/arch/arc/include/asm/kprobes.h
> @@ -9,6 +9,8 @@
>  #ifndef _ARC_KPROBES_H
>  #define _ARC_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
>  #ifdef CONFIG_KPROBES
>  
>  typedef u16 kprobe_opcode_t;
> @@ -55,6 +57,6 @@ void trap_is_kprobe(unsigned long address, struct pt_regs *regs);
>  static void trap_is_kprobe(unsigned long address, struct pt_regs *regs)
>  {
>  }
> -#endif
> +#endif /* CONFIG_KPROBES */
>  
> -#endif
> +#endif /* _ARC_KPROBES_H */
> diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
> index 3ea9be559726..59655459da59 100644
> --- a/arch/arm/include/asm/kprobes.h
> +++ b/arch/arm/include/asm/kprobes.h
> @@ -16,6 +16,9 @@
>  #ifndef _ARM_KPROBES_H
>  #define _ARM_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/types.h>
>  #include <linux/ptrace.h>
>  #include <linux/notifier.h>
> @@ -83,4 +86,5 @@ struct arch_optimized_insn {
>  	 */
>  };
>  
> +#endif /* CONFIG_KPROBES */
>  #endif /* _ARM_KPROBES_H */
> diff --git a/arch/arm/probes/decode.h b/arch/arm/probes/decode.h
> index f9b08ba7fe73..548d622a3159 100644
> --- a/arch/arm/probes/decode.h
> +++ b/arch/arm/probes/decode.h
> @@ -22,6 +22,7 @@
>  #include <linux/types.h>
>  #include <linux/stddef.h>
>  #include <asm/probes.h>
> +#include <asm/kprobes.h>
>  
>  void __init arm_probes_decode_init(void);
>  
> diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
> index 1737aecfcc5e..6deb8d726041 100644
> --- a/arch/arm64/include/asm/kprobes.h
> +++ b/arch/arm64/include/asm/kprobes.h
> @@ -16,6 +16,9 @@
>  #ifndef _ARM_KPROBES_H
>  #define _ARM_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/types.h>
>  #include <linux/ptrace.h>
>  #include <linux/percpu.h>
> @@ -57,4 +60,5 @@ int kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr);
>  void kretprobe_trampoline(void);
>  void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
>  
> +#endif /* CONFIG_KPROBES */
>  #endif /* _ARM_KPROBES_H */
> diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
> index 63f9432d05e8..cc38f3241927 100644
> --- a/arch/arm64/kernel/insn.c
> +++ b/arch/arm64/kernel/insn.c
> @@ -32,6 +32,7 @@
>  #include <asm/fixmap.h>
>  #include <asm/opcodes.h>
>  #include <asm/insn.h>
> +#include <asm/kprobes.h>
>  
>  #define AARCH64_INSN_SF_BIT	BIT(31)
>  #define AARCH64_INSN_N_BIT	BIT(22)
> diff --git a/arch/avr32/include/asm/kprobes.h b/arch/avr32/include/asm/kprobes.h
> index 45f563ed73fd..09f39d8749ea 100644
> --- a/arch/avr32/include/asm/kprobes.h
> +++ b/arch/avr32/include/asm/kprobes.h
> @@ -11,6 +11,9 @@
>  #ifndef __ASM_AVR32_KPROBES_H
>  #define __ASM_AVR32_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/types.h>
>  
>  typedef u16	kprobe_opcode_t;
> @@ -46,4 +49,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
>  
>  #define flush_insn_slot(p)	do { } while (0)
>  
> +#endif /* CONFIG_KPROBES */
>  #endif /* __ASM_AVR32_KPROBES_H */
> diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
> index b71893b1cd53..f56a68697353 100644
> --- a/arch/blackfin/include/asm/Kbuild
> +++ b/arch/blackfin/include/asm/Kbuild
> @@ -51,3 +51,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
> index cede2a950fbf..c54f7cc1f63e 100644
> --- a/arch/c6x/include/asm/Kbuild
> +++ b/arch/c6x/include/asm/Kbuild
> @@ -64,3 +64,4 @@ generic-y += word-at-a-time.h
>  generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
> +generic-y += kprobes.h
> diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
> index 7062c1be7913..051d355feae3 100644
> --- a/arch/cris/include/asm/Kbuild
> +++ b/arch/cris/include/asm/Kbuild
> @@ -48,3 +48,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
> index 4a59cbda5091..b58b9fc49383 100644
> --- a/arch/frv/include/asm/Kbuild
> +++ b/arch/frv/include/asm/Kbuild
> @@ -11,3 +11,4 @@ generic-y += word-at-a-time.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
> index d79968d93c12..cfca7de52b37 100644
> --- a/arch/h8300/include/asm/Kbuild
> +++ b/arch/h8300/include/asm/Kbuild
> @@ -78,3 +78,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
> index d59ac1c1858b..d7cc35451f30 100644
> --- a/arch/hexagon/include/asm/Kbuild
> +++ b/arch/hexagon/include/asm/Kbuild
> @@ -63,3 +63,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/ia64/include/asm/kprobes.h b/arch/ia64/include/asm/kprobes.h
> index d5505d6f2382..36999c55f3f2 100644
> --- a/arch/ia64/include/asm/kprobes.h
> +++ b/arch/ia64/include/asm/kprobes.h
> @@ -23,6 +23,10 @@
>   * 2005-Apr     Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
>   *              <anil.s.keshavamurthy@intel.com> adapted from i386
>   */
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
> +
>  #include <linux/types.h>
>  #include <linux/ptrace.h>
>  #include <linux/percpu.h>
> @@ -124,4 +128,5 @@ extern void invalidate_stacked_regs(void);
>  extern void flush_register_stack(void);
>  extern void arch_remove_kprobe(struct kprobe *p);
>  
> -#endif				/* _ASM_KPROBES_H */
> +#endif /* CONFIG_KPROBES */
> +#endif /* _ASM_KPROBES_H */
> diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
> index 24088f3c733c..198ad591ab41 100644
> --- a/arch/m32r/include/asm/Kbuild
> +++ b/arch/m32r/include/asm/Kbuild
> @@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
> index 65c0df17f70e..ae86bb91e13b 100644
> --- a/arch/m68k/include/asm/Kbuild
> +++ b/arch/m68k/include/asm/Kbuild
> @@ -38,3 +38,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
> index 2538224899fd..10f36ed301e1 100644
> --- a/arch/metag/include/asm/Kbuild
> +++ b/arch/metag/include/asm/Kbuild
> @@ -59,3 +59,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
> index 01afb1b420f5..865ce3d96443 100644
> --- a/arch/microblaze/include/asm/Kbuild
> +++ b/arch/microblaze/include/asm/Kbuild
> @@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/mips/include/asm/kprobes.h b/arch/mips/include/asm/kprobes.h
> index daba1f9a4f79..291846d9ba83 100644
> --- a/arch/mips/include/asm/kprobes.h
> +++ b/arch/mips/include/asm/kprobes.h
> @@ -22,6 +22,9 @@
>  #ifndef _ASM_KPROBES_H
>  #define _ASM_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/ptrace.h>
>  #include <linux/types.h>
>  
> @@ -94,4 +97,5 @@ struct kprobe_ctlblk {
>  extern int kprobe_exceptions_notify(struct notifier_block *self,
>  				    unsigned long val, void *data);
>  
> -#endif				/* _ASM_KPROBES_H */
> +#endif /* CONFIG_KPROBES */
> +#endif /* _ASM_KPROBES_H */
> diff --git a/arch/mn10300/include/asm/kprobes.h b/arch/mn10300/include/asm/kprobes.h
> index c800b590183a..5729bb5b972a 100644
> --- a/arch/mn10300/include/asm/kprobes.h
> +++ b/arch/mn10300/include/asm/kprobes.h
> @@ -21,6 +21,9 @@
>  #ifndef _ASM_KPROBES_H
>  #define _ASM_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/types.h>
>  #include <linux/ptrace.h>
>  
> @@ -47,4 +50,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
>  
>  extern void arch_remove_kprobe(struct kprobe *p);
>  
> +#endif /* CONFIG_KPROBES */
>  #endif /* _ASM_KPROBES_H */
> diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
> index ee6220dac1e8..d6ce7edee7e0 100644
> --- a/arch/nios2/include/asm/Kbuild
> +++ b/arch/nios2/include/asm/Kbuild
> @@ -66,3 +66,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
> index ceafe458e295..1bf89a67317c 100644
> --- a/arch/openrisc/include/asm/Kbuild
> +++ b/arch/openrisc/include/asm/Kbuild
> @@ -74,3 +74,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
> index 99211477bfb2..982886ba812a 100644
> --- a/arch/parisc/include/asm/Kbuild
> +++ b/arch/parisc/include/asm/Kbuild
> @@ -32,3 +32,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h
> index 2c9759bdb63b..e5d0dc5c6236 100644
> --- a/arch/powerpc/include/asm/kprobes.h
> +++ b/arch/powerpc/include/asm/kprobes.h
> @@ -1,5 +1,9 @@
>  #ifndef _ASM_POWERPC_KPROBES_H
>  #define _ASM_POWERPC_KPROBES_H
> +
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #ifdef __KERNEL__
>  /*
>   *  Kernel Probes (KProbes)
> @@ -127,5 +131,7 @@ struct kprobe_ctlblk {
>  extern int kprobe_exceptions_notify(struct notifier_block *self,
>  					unsigned long val, void *data);
>  extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
> +
>  #endif /* __KERNEL__ */
> +#endif /* CONFIG_KPROBES */
>  #endif	/* _ASM_POWERPC_KPROBES_H */
> diff --git a/arch/s390/include/asm/kprobes.h b/arch/s390/include/asm/kprobes.h
> index 591e5a5279b0..dc12b0135007 100644
> --- a/arch/s390/include/asm/kprobes.h
> +++ b/arch/s390/include/asm/kprobes.h
> @@ -27,6 +27,9 @@
>   * 2005-Dec	Used as a template for s390 by Mike Grundy
>   *		<grundym@us.ibm.com>
>   */
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/types.h>
>  #include <linux/ptrace.h>
>  #include <linux/percpu.h>
> @@ -91,4 +94,5 @@ int probe_is_insn_relative_long(u16 *insn);
>  
>  #define flush_insn_slot(p)	do { } while (0)
>  
> +#endif /* CONFIG_KPROBES */
>  #endif	/* _ASM_S390_KPROBES_H */
> diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
> index 16ea15a3e432..6ac8a7f5c768 100644
> --- a/arch/score/include/asm/Kbuild
> +++ b/arch/score/include/asm/Kbuild
> @@ -17,3 +17,4 @@ generic-y += word-at-a-time.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h
> index 134f3980e44a..0b9a54016eeb 100644
> --- a/arch/sh/include/asm/kprobes.h
> +++ b/arch/sh/include/asm/kprobes.h
> @@ -1,6 +1,8 @@
>  #ifndef __ASM_SH_KPROBES_H
>  #define __ASM_SH_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
>  #ifdef CONFIG_KPROBES
>  
>  #include <linux/types.h>
> diff --git a/arch/sparc/include/asm/kprobes.h b/arch/sparc/include/asm/kprobes.h
> index a145d798e112..8c4cd15395f6 100644
> --- a/arch/sparc/include/asm/kprobes.h
> +++ b/arch/sparc/include/asm/kprobes.h
> @@ -1,6 +1,9 @@
>  #ifndef _SPARC64_KPROBES_H
>  #define _SPARC64_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/types.h>
>  #include <linux/percpu.h>
>  
> @@ -48,4 +51,6 @@ int kprobe_exceptions_notify(struct notifier_block *self,
>  int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
>  asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
>  				      struct pt_regs *regs);
> +
> +#endif /* CONFIG_KPROBES */
>  #endif /* _SPARC64_KPROBES_H */
> diff --git a/arch/tile/include/asm/kprobes.h b/arch/tile/include/asm/kprobes.h
> index d8f9a83943b1..4a8b1cadca24 100644
> --- a/arch/tile/include/asm/kprobes.h
> +++ b/arch/tile/include/asm/kprobes.h
> @@ -17,10 +17,13 @@
>  #ifndef _ASM_TILE_KPROBES_H
>  #define _ASM_TILE_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
> +
>  #include <linux/types.h>
>  #include <linux/ptrace.h>
>  #include <linux/percpu.h>
> -
>  #include <arch/opcode.h>
>  
>  #define __ARCH_WANT_KPROBES_INSN_SLOT
> @@ -76,4 +79,5 @@ void arch_remove_kprobe(struct kprobe *);
>  extern int kprobe_exceptions_notify(struct notifier_block *self,
>  			     unsigned long val, void *data);
>  
> +#endif /* CONFIG_KPROBES */
>  #endif /* _ASM_TILE_KPROBES_H */
> diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
> index eea5dd842992..f0314517090b 100644
> --- a/arch/um/include/asm/Kbuild
> +++ b/arch/um/include/asm/Kbuild
> @@ -30,3 +30,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
> index 5c31eafbf1fd..32321579011b 100644
> --- a/arch/unicore32/include/asm/Kbuild
> +++ b/arch/unicore32/include/asm/Kbuild
> @@ -66,3 +66,4 @@ generic-y += word-at-a-time.h
>  generic-y += xor.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h
> index d1d1e5094c28..95c480dc8570 100644
> --- a/arch/x86/include/asm/kprobes.h
> +++ b/arch/x86/include/asm/kprobes.h
> @@ -21,6 +21,10 @@
>   *
>   * See arch/x86/kernel/kprobes.c for x86 kprobes history.
>   */
> +
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/types.h>
>  #include <linux/ptrace.h>
>  #include <linux/percpu.h>
> @@ -116,4 +120,6 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
>  				    unsigned long val, void *data);
>  extern int kprobe_int3_handler(struct pt_regs *regs);
>  extern int kprobe_debug_handler(struct pt_regs *regs);
> +
> +#endif /* CONFIG_KPROBES */
>  #endif /* _ASM_X86_KPROBES_H */
> diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
> index ae48f8fd9212..bf0e40100fda 100644
> --- a/arch/xtensa/include/asm/Kbuild
> +++ b/arch/xtensa/include/asm/Kbuild
> @@ -34,3 +34,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
> new file mode 100644
> index 000000000000..57af9f21d148
> --- /dev/null
> +++ b/include/asm-generic/kprobes.h
> @@ -0,0 +1,25 @@
> +#ifndef _ASM_GENERIC_KPROBES_H
> +#define _ASM_GENERIC_KPROBES_H
> +
> +#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
> +#ifdef CONFIG_KPROBES
> +/*
> + * Blacklist ganerating macro. Specify functions which is not probed
> + * by using this macro.
> + */
> +# define __NOKPROBE_SYMBOL(fname)				\
> +static unsigned long __used					\
> +	__attribute__((__section__("_kprobe_blacklist")))	\
> +	_kbl_addr_##fname = (unsigned long)fname;
> +# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
> +/* Use this to forbid a kprobes attach on very low level functions */
> +# define __kprobes	__attribute__((__section__(".kprobes.text")))
> +# define nokprobe_inline	__always_inline
> +#else
> +# define NOKPROBE_SYMBOL(fname)
> +# define __kprobes
> +# define nokprobe_inline	inline
> +#endif
> +#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
> +
> +#endif /* _ASM_GENERIC_KPROBES_H */
> diff --git a/include/linux/compiler.h b/include/linux/compiler.h
> index 1eed7f5e137d..4736dc5741e4 100644
> --- a/include/linux/compiler.h
> +++ b/include/linux/compiler.h
> @@ -542,12 +542,4 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
>  	(_________p1); \
>  })
>  
> -/* Ignore/forbid kprobes attach on very low level functions marked by this attribute: */
> -#ifdef CONFIG_KPROBES
> -# define __kprobes	__attribute__((__section__(".kprobes.text")))
> -# define nokprobe_inline	__always_inline
> -#else
> -# define __kprobes
> -# define nokprobe_inline	inline
> -#endif
>  #endif /* __LINUX_COMPILER_H */
> diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
> index 8f6849084248..985ed79ef431 100644
> --- a/include/linux/kprobes.h
> +++ b/include/linux/kprobes.h
> @@ -29,7 +29,7 @@
>   *		<jkenisto@us.ibm.com>  and Prasanna S Panchamukhi
>   *		<prasanna@in.ibm.com> added function-return probes.
>   */
> -#include <linux/compiler.h>	/* for __kprobes */
> +#include <linux/compiler.h>
>  #include <linux/linkage.h>
>  #include <linux/list.h>
>  #include <linux/notifier.h>
> @@ -40,9 +40,9 @@
>  #include <linux/rcupdate.h>
>  #include <linux/mutex.h>
>  #include <linux/ftrace.h>
> +#include <asm/kprobes.h>
>  
>  #ifdef CONFIG_KPROBES
> -#include <asm/kprobes.h>
>  
>  /* kprobe_status settings */
>  #define KPROBE_HIT_ACTIVE	0x00000001
> @@ -51,6 +51,7 @@
>  #define KPROBE_HIT_SSDONE	0x00000008
>  
>  #else /* CONFIG_KPROBES */
> +#include <asm-generic/kprobes.h>
>  typedef int kprobe_opcode_t;
>  struct arch_specific_insn {
>  	int dummy;
> @@ -481,18 +482,4 @@ static inline int enable_jprobe(struct jprobe *jp)
>  	return enable_kprobe(&jp->kp);
>  }
>  
> -#ifdef CONFIG_KPROBES
> -/*
> - * Blacklist ganerating macro. Specify functions which is not probed
> - * by using this macro.
> - */
> -#define __NOKPROBE_SYMBOL(fname)			\
> -static unsigned long __used				\
> -	__attribute__((section("_kprobe_blacklist")))	\
> -	_kbl_addr_##fname = (unsigned long)fname;
> -#define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
> -#else
> -#define NOKPROBE_SYMBOL(fname)
> -#endif
> -
>  #endif /* _LINUX_KPROBES_H */
> -- 
> 2.9.2
> 


-- 
Masami Hiramatsu <mhiramat@kernel.org>

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 14/16] kprobes: move kprobe declarations to asm-generic/kprobes.h
@ 2016-08-22 15:11       ` Masami Hiramatsu
  0 siblings, 0 replies; 480+ messages in thread
From: Masami Hiramatsu @ 2016-08-22 15:11 UTC (permalink / raw)
  To: mcgrof
  Cc: hpa, tglx, mingo, jpoimboe, bp, linux, masami.hiramatsu.pt,
	jbaron, heiko.carstens, ananth, anil.s.keshavamurthy, davem,
	realmz6, x86, luto, keescook, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley

On Fri, 19 Aug 2016 14:34:12 -0700
mcgrof@kernel.org wrote:

> From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> 
> Often all is needed is these small helpers, instead of compiler.h
> or a full kprobes.h. This is important for asm helpers, in fact even
> some asm/kprobes.h make use of these helpers... instead just keep a
> generic asm file with helpers useful for asm code with the least amount
> of clutter as possible.
> 
> Likewise we need now to also address what to do about this file for both
> when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
> for when architectures have CONFIG_HAVE_KPROBES but have disabled
> CONFIG_KPROBES.
> 
> Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
> this means most architecture code cannot include asm/kprobes.h safely.
> Correct this and add guards for architectures missing them. Additionally
> provide architectures that not have kprobes support with the default
> asm-generic solution. This lets us force asm/kprobes.h on the header
> include/linux/kprobes.h always, but most importantly we can now safely
> include just asm/kprobes.h on architecture code without bringing
> the full kitchen sink of header files.
> 
> Two architectures already provided a guard against CONFIG_KPROBES on
> its kprobes.h: sh, arch. The rest of the architectures needed gaurds
> added. We avoid including any not-needed headers on asm/kprobes.h
> unless kprobes have been enabled.
> 
> In a subsequent atomic change we can try now to remove compiler.h from
> include/linux/kprobes.h.

Hmm, this looks a bit overkill... I rather like move it into linux/table.h.

Thanks,

> 
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  arch/alpha/include/asm/Kbuild      |  1 +
>  arch/arc/include/asm/kprobes.h     |  6 ++++--
>  arch/arm/include/asm/kprobes.h     |  4 ++++
>  arch/arm/probes/decode.h           |  1 +
>  arch/arm64/include/asm/kprobes.h   |  4 ++++
>  arch/arm64/kernel/insn.c           |  1 +
>  arch/avr32/include/asm/kprobes.h   |  4 ++++
>  arch/blackfin/include/asm/Kbuild   |  1 +
>  arch/c6x/include/asm/Kbuild        |  1 +
>  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/kprobes.h    |  7 ++++++-
>  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/kprobes.h    |  6 +++++-
>  arch/mn10300/include/asm/kprobes.h |  4 ++++
>  arch/nios2/include/asm/Kbuild      |  1 +
>  arch/openrisc/include/asm/Kbuild   |  1 +
>  arch/parisc/include/asm/Kbuild     |  1 +
>  arch/powerpc/include/asm/kprobes.h |  6 ++++++
>  arch/s390/include/asm/kprobes.h    |  4 ++++
>  arch/score/include/asm/Kbuild      |  1 +
>  arch/sh/include/asm/kprobes.h      |  2 ++
>  arch/sparc/include/asm/kprobes.h   |  5 +++++
>  arch/tile/include/asm/kprobes.h    |  6 +++++-
>  arch/um/include/asm/Kbuild         |  1 +
>  arch/unicore32/include/asm/Kbuild  |  1 +
>  arch/x86/include/asm/kprobes.h     |  6 ++++++
>  arch/xtensa/include/asm/Kbuild     |  1 +
>  include/asm-generic/kprobes.h      | 25 +++++++++++++++++++++++++
>  include/linux/compiler.h           |  8 --------
>  include/linux/kprobes.h            | 19 +++----------------
>  36 files changed, 107 insertions(+), 29 deletions(-)
>  create mode 100644 include/asm-generic/kprobes.h
> 
> diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
> index f3bdc31d3c97..54d388fd026f 100644
> --- a/arch/alpha/include/asm/Kbuild
> +++ b/arch/alpha/include/asm/Kbuild
> @@ -13,3 +13,4 @@ generic-y += trace_clock.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/arc/include/asm/kprobes.h b/arch/arc/include/asm/kprobes.h
> index 944dbedb38b5..00bdbe167615 100644
> --- a/arch/arc/include/asm/kprobes.h
> +++ b/arch/arc/include/asm/kprobes.h
> @@ -9,6 +9,8 @@
>  #ifndef _ARC_KPROBES_H
>  #define _ARC_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
>  #ifdef CONFIG_KPROBES
>  
>  typedef u16 kprobe_opcode_t;
> @@ -55,6 +57,6 @@ void trap_is_kprobe(unsigned long address, struct pt_regs *regs);
>  static void trap_is_kprobe(unsigned long address, struct pt_regs *regs)
>  {
>  }
> -#endif
> +#endif /* CONFIG_KPROBES */
>  
> -#endif
> +#endif /* _ARC_KPROBES_H */
> diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
> index 3ea9be559726..59655459da59 100644
> --- a/arch/arm/include/asm/kprobes.h
> +++ b/arch/arm/include/asm/kprobes.h
> @@ -16,6 +16,9 @@
>  #ifndef _ARM_KPROBES_H
>  #define _ARM_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/types.h>
>  #include <linux/ptrace.h>
>  #include <linux/notifier.h>
> @@ -83,4 +86,5 @@ struct arch_optimized_insn {
>  	 */
>  };
>  
> +#endif /* CONFIG_KPROBES */
>  #endif /* _ARM_KPROBES_H */
> diff --git a/arch/arm/probes/decode.h b/arch/arm/probes/decode.h
> index f9b08ba7fe73..548d622a3159 100644
> --- a/arch/arm/probes/decode.h
> +++ b/arch/arm/probes/decode.h
> @@ -22,6 +22,7 @@
>  #include <linux/types.h>
>  #include <linux/stddef.h>
>  #include <asm/probes.h>
> +#include <asm/kprobes.h>
>  
>  void __init arm_probes_decode_init(void);
>  
> diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
> index 1737aecfcc5e..6deb8d726041 100644
> --- a/arch/arm64/include/asm/kprobes.h
> +++ b/arch/arm64/include/asm/kprobes.h
> @@ -16,6 +16,9 @@
>  #ifndef _ARM_KPROBES_H
>  #define _ARM_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/types.h>
>  #include <linux/ptrace.h>
>  #include <linux/percpu.h>
> @@ -57,4 +60,5 @@ int kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr);
>  void kretprobe_trampoline(void);
>  void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
>  
> +#endif /* CONFIG_KPROBES */
>  #endif /* _ARM_KPROBES_H */
> diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
> index 63f9432d05e8..cc38f3241927 100644
> --- a/arch/arm64/kernel/insn.c
> +++ b/arch/arm64/kernel/insn.c
> @@ -32,6 +32,7 @@
>  #include <asm/fixmap.h>
>  #include <asm/opcodes.h>
>  #include <asm/insn.h>
> +#include <asm/kprobes.h>
>  
>  #define AARCH64_INSN_SF_BIT	BIT(31)
>  #define AARCH64_INSN_N_BIT	BIT(22)
> diff --git a/arch/avr32/include/asm/kprobes.h b/arch/avr32/include/asm/kprobes.h
> index 45f563ed73fd..09f39d8749ea 100644
> --- a/arch/avr32/include/asm/kprobes.h
> +++ b/arch/avr32/include/asm/kprobes.h
> @@ -11,6 +11,9 @@
>  #ifndef __ASM_AVR32_KPROBES_H
>  #define __ASM_AVR32_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/types.h>
>  
>  typedef u16	kprobe_opcode_t;
> @@ -46,4 +49,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
>  
>  #define flush_insn_slot(p)	do { } while (0)
>  
> +#endif /* CONFIG_KPROBES */
>  #endif /* __ASM_AVR32_KPROBES_H */
> diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
> index b71893b1cd53..f56a68697353 100644
> --- a/arch/blackfin/include/asm/Kbuild
> +++ b/arch/blackfin/include/asm/Kbuild
> @@ -51,3 +51,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
> index cede2a950fbf..c54f7cc1f63e 100644
> --- a/arch/c6x/include/asm/Kbuild
> +++ b/arch/c6x/include/asm/Kbuild
> @@ -64,3 +64,4 @@ generic-y += word-at-a-time.h
>  generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
> +generic-y += kprobes.h
> diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
> index 7062c1be7913..051d355feae3 100644
> --- a/arch/cris/include/asm/Kbuild
> +++ b/arch/cris/include/asm/Kbuild
> @@ -48,3 +48,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
> index 4a59cbda5091..b58b9fc49383 100644
> --- a/arch/frv/include/asm/Kbuild
> +++ b/arch/frv/include/asm/Kbuild
> @@ -11,3 +11,4 @@ generic-y += word-at-a-time.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
> index d79968d93c12..cfca7de52b37 100644
> --- a/arch/h8300/include/asm/Kbuild
> +++ b/arch/h8300/include/asm/Kbuild
> @@ -78,3 +78,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
> index d59ac1c1858b..d7cc35451f30 100644
> --- a/arch/hexagon/include/asm/Kbuild
> +++ b/arch/hexagon/include/asm/Kbuild
> @@ -63,3 +63,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/ia64/include/asm/kprobes.h b/arch/ia64/include/asm/kprobes.h
> index d5505d6f2382..36999c55f3f2 100644
> --- a/arch/ia64/include/asm/kprobes.h
> +++ b/arch/ia64/include/asm/kprobes.h
> @@ -23,6 +23,10 @@
>   * 2005-Apr     Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
>   *              <anil.s.keshavamurthy@intel.com> adapted from i386
>   */
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
> +
>  #include <linux/types.h>
>  #include <linux/ptrace.h>
>  #include <linux/percpu.h>
> @@ -124,4 +128,5 @@ extern void invalidate_stacked_regs(void);
>  extern void flush_register_stack(void);
>  extern void arch_remove_kprobe(struct kprobe *p);
>  
> -#endif				/* _ASM_KPROBES_H */
> +#endif /* CONFIG_KPROBES */
> +#endif /* _ASM_KPROBES_H */
> diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
> index 24088f3c733c..198ad591ab41 100644
> --- a/arch/m32r/include/asm/Kbuild
> +++ b/arch/m32r/include/asm/Kbuild
> @@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
> index 65c0df17f70e..ae86bb91e13b 100644
> --- a/arch/m68k/include/asm/Kbuild
> +++ b/arch/m68k/include/asm/Kbuild
> @@ -38,3 +38,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
> index 2538224899fd..10f36ed301e1 100644
> --- a/arch/metag/include/asm/Kbuild
> +++ b/arch/metag/include/asm/Kbuild
> @@ -59,3 +59,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
> index 01afb1b420f5..865ce3d96443 100644
> --- a/arch/microblaze/include/asm/Kbuild
> +++ b/arch/microblaze/include/asm/Kbuild
> @@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/mips/include/asm/kprobes.h b/arch/mips/include/asm/kprobes.h
> index daba1f9a4f79..291846d9ba83 100644
> --- a/arch/mips/include/asm/kprobes.h
> +++ b/arch/mips/include/asm/kprobes.h
> @@ -22,6 +22,9 @@
>  #ifndef _ASM_KPROBES_H
>  #define _ASM_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/ptrace.h>
>  #include <linux/types.h>
>  
> @@ -94,4 +97,5 @@ struct kprobe_ctlblk {
>  extern int kprobe_exceptions_notify(struct notifier_block *self,
>  				    unsigned long val, void *data);
>  
> -#endif				/* _ASM_KPROBES_H */
> +#endif /* CONFIG_KPROBES */
> +#endif /* _ASM_KPROBES_H */
> diff --git a/arch/mn10300/include/asm/kprobes.h b/arch/mn10300/include/asm/kprobes.h
> index c800b590183a..5729bb5b972a 100644
> --- a/arch/mn10300/include/asm/kprobes.h
> +++ b/arch/mn10300/include/asm/kprobes.h
> @@ -21,6 +21,9 @@
>  #ifndef _ASM_KPROBES_H
>  #define _ASM_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/types.h>
>  #include <linux/ptrace.h>
>  
> @@ -47,4 +50,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
>  
>  extern void arch_remove_kprobe(struct kprobe *p);
>  
> +#endif /* CONFIG_KPROBES */
>  #endif /* _ASM_KPROBES_H */
> diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
> index ee6220dac1e8..d6ce7edee7e0 100644
> --- a/arch/nios2/include/asm/Kbuild
> +++ b/arch/nios2/include/asm/Kbuild
> @@ -66,3 +66,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
> index ceafe458e295..1bf89a67317c 100644
> --- a/arch/openrisc/include/asm/Kbuild
> +++ b/arch/openrisc/include/asm/Kbuild
> @@ -74,3 +74,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
> index 99211477bfb2..982886ba812a 100644
> --- a/arch/parisc/include/asm/Kbuild
> +++ b/arch/parisc/include/asm/Kbuild
> @@ -32,3 +32,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h
> index 2c9759bdb63b..e5d0dc5c6236 100644
> --- a/arch/powerpc/include/asm/kprobes.h
> +++ b/arch/powerpc/include/asm/kprobes.h
> @@ -1,5 +1,9 @@
>  #ifndef _ASM_POWERPC_KPROBES_H
>  #define _ASM_POWERPC_KPROBES_H
> +
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #ifdef __KERNEL__
>  /*
>   *  Kernel Probes (KProbes)
> @@ -127,5 +131,7 @@ struct kprobe_ctlblk {
>  extern int kprobe_exceptions_notify(struct notifier_block *self,
>  					unsigned long val, void *data);
>  extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
> +
>  #endif /* __KERNEL__ */
> +#endif /* CONFIG_KPROBES */
>  #endif	/* _ASM_POWERPC_KPROBES_H */
> diff --git a/arch/s390/include/asm/kprobes.h b/arch/s390/include/asm/kprobes.h
> index 591e5a5279b0..dc12b0135007 100644
> --- a/arch/s390/include/asm/kprobes.h
> +++ b/arch/s390/include/asm/kprobes.h
> @@ -27,6 +27,9 @@
>   * 2005-Dec	Used as a template for s390 by Mike Grundy
>   *		<grundym@us.ibm.com>
>   */
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/types.h>
>  #include <linux/ptrace.h>
>  #include <linux/percpu.h>
> @@ -91,4 +94,5 @@ int probe_is_insn_relative_long(u16 *insn);
>  
>  #define flush_insn_slot(p)	do { } while (0)
>  
> +#endif /* CONFIG_KPROBES */
>  #endif	/* _ASM_S390_KPROBES_H */
> diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
> index 16ea15a3e432..6ac8a7f5c768 100644
> --- a/arch/score/include/asm/Kbuild
> +++ b/arch/score/include/asm/Kbuild
> @@ -17,3 +17,4 @@ generic-y += word-at-a-time.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h
> index 134f3980e44a..0b9a54016eeb 100644
> --- a/arch/sh/include/asm/kprobes.h
> +++ b/arch/sh/include/asm/kprobes.h
> @@ -1,6 +1,8 @@
>  #ifndef __ASM_SH_KPROBES_H
>  #define __ASM_SH_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
>  #ifdef CONFIG_KPROBES
>  
>  #include <linux/types.h>
> diff --git a/arch/sparc/include/asm/kprobes.h b/arch/sparc/include/asm/kprobes.h
> index a145d798e112..8c4cd15395f6 100644
> --- a/arch/sparc/include/asm/kprobes.h
> +++ b/arch/sparc/include/asm/kprobes.h
> @@ -1,6 +1,9 @@
>  #ifndef _SPARC64_KPROBES_H
>  #define _SPARC64_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/types.h>
>  #include <linux/percpu.h>
>  
> @@ -48,4 +51,6 @@ int kprobe_exceptions_notify(struct notifier_block *self,
>  int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
>  asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
>  				      struct pt_regs *regs);
> +
> +#endif /* CONFIG_KPROBES */
>  #endif /* _SPARC64_KPROBES_H */
> diff --git a/arch/tile/include/asm/kprobes.h b/arch/tile/include/asm/kprobes.h
> index d8f9a83943b1..4a8b1cadca24 100644
> --- a/arch/tile/include/asm/kprobes.h
> +++ b/arch/tile/include/asm/kprobes.h
> @@ -17,10 +17,13 @@
>  #ifndef _ASM_TILE_KPROBES_H
>  #define _ASM_TILE_KPROBES_H
>  
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
> +
>  #include <linux/types.h>
>  #include <linux/ptrace.h>
>  #include <linux/percpu.h>
> -
>  #include <arch/opcode.h>
>  
>  #define __ARCH_WANT_KPROBES_INSN_SLOT
> @@ -76,4 +79,5 @@ void arch_remove_kprobe(struct kprobe *);
>  extern int kprobe_exceptions_notify(struct notifier_block *self,
>  			     unsigned long val, void *data);
>  
> +#endif /* CONFIG_KPROBES */
>  #endif /* _ASM_TILE_KPROBES_H */
> diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
> index eea5dd842992..f0314517090b 100644
> --- a/arch/um/include/asm/Kbuild
> +++ b/arch/um/include/asm/Kbuild
> @@ -30,3 +30,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
> index 5c31eafbf1fd..32321579011b 100644
> --- a/arch/unicore32/include/asm/Kbuild
> +++ b/arch/unicore32/include/asm/Kbuild
> @@ -66,3 +66,4 @@ generic-y += word-at-a-time.h
>  generic-y += xor.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h
> index d1d1e5094c28..95c480dc8570 100644
> --- a/arch/x86/include/asm/kprobes.h
> +++ b/arch/x86/include/asm/kprobes.h
> @@ -21,6 +21,10 @@
>   *
>   * See arch/x86/kernel/kprobes.c for x86 kprobes history.
>   */
> +
> +#include <asm-generic/kprobes.h>
> +
> +#ifdef CONFIG_KPROBES
>  #include <linux/types.h>
>  #include <linux/ptrace.h>
>  #include <linux/percpu.h>
> @@ -116,4 +120,6 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
>  				    unsigned long val, void *data);
>  extern int kprobe_int3_handler(struct pt_regs *regs);
>  extern int kprobe_debug_handler(struct pt_regs *regs);
> +
> +#endif /* CONFIG_KPROBES */
>  #endif /* _ASM_X86_KPROBES_H */
> diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
> index ae48f8fd9212..bf0e40100fda 100644
> --- a/arch/xtensa/include/asm/Kbuild
> +++ b/arch/xtensa/include/asm/Kbuild
> @@ -34,3 +34,4 @@ generic-y += xor.h
>  generic-y += section-core.h
>  generic-y += ranges.h
>  generic-y += tables.h
> +generic-y += kprobes.h
> diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
> new file mode 100644
> index 000000000000..57af9f21d148
> --- /dev/null
> +++ b/include/asm-generic/kprobes.h
> @@ -0,0 +1,25 @@
> +#ifndef _ASM_GENERIC_KPROBES_H
> +#define _ASM_GENERIC_KPROBES_H
> +
> +#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
> +#ifdef CONFIG_KPROBES
> +/*
> + * Blacklist ganerating macro. Specify functions which is not probed
> + * by using this macro.
> + */
> +# define __NOKPROBE_SYMBOL(fname)				\
> +static unsigned long __used					\
> +	__attribute__((__section__("_kprobe_blacklist")))	\
> +	_kbl_addr_##fname = (unsigned long)fname;
> +# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
> +/* Use this to forbid a kprobes attach on very low level functions */
> +# define __kprobes	__attribute__((__section__(".kprobes.text")))
> +# define nokprobe_inline	__always_inline
> +#else
> +# define NOKPROBE_SYMBOL(fname)
> +# define __kprobes
> +# define nokprobe_inline	inline
> +#endif
> +#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
> +
> +#endif /* _ASM_GENERIC_KPROBES_H */
> diff --git a/include/linux/compiler.h b/include/linux/compiler.h
> index 1eed7f5e137d..4736dc5741e4 100644
> --- a/include/linux/compiler.h
> +++ b/include/linux/compiler.h
> @@ -542,12 +542,4 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
>  	(_________p1); \
>  })
>  
> -/* Ignore/forbid kprobes attach on very low level functions marked by this attribute: */
> -#ifdef CONFIG_KPROBES
> -# define __kprobes	__attribute__((__section__(".kprobes.text")))
> -# define nokprobe_inline	__always_inline
> -#else
> -# define __kprobes
> -# define nokprobe_inline	inline
> -#endif
>  #endif /* __LINUX_COMPILER_H */
> diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
> index 8f6849084248..985ed79ef431 100644
> --- a/include/linux/kprobes.h
> +++ b/include/linux/kprobes.h
> @@ -29,7 +29,7 @@
>   *		<jkenisto@us.ibm.com>  and Prasanna S Panchamukhi
>   *		<prasanna@in.ibm.com> added function-return probes.
>   */
> -#include <linux/compiler.h>	/* for __kprobes */
> +#include <linux/compiler.h>
>  #include <linux/linkage.h>
>  #include <linux/list.h>
>  #include <linux/notifier.h>
> @@ -40,9 +40,9 @@
>  #include <linux/rcupdate.h>
>  #include <linux/mutex.h>
>  #include <linux/ftrace.h>
> +#include <asm/kprobes.h>
>  
>  #ifdef CONFIG_KPROBES
> -#include <asm/kprobes.h>
>  
>  /* kprobe_status settings */
>  #define KPROBE_HIT_ACTIVE	0x00000001
> @@ -51,6 +51,7 @@
>  #define KPROBE_HIT_SSDONE	0x00000008
>  
>  #else /* CONFIG_KPROBES */
> +#include <asm-generic/kprobes.h>
>  typedef int kprobe_opcode_t;
>  struct arch_specific_insn {
>  	int dummy;
> @@ -481,18 +482,4 @@ static inline int enable_jprobe(struct jprobe *jp)
>  	return enable_kprobe(&jp->kp);
>  }
>  
> -#ifdef CONFIG_KPROBES
> -/*
> - * Blacklist ganerating macro. Specify functions which is not probed
> - * by using this macro.
> - */
> -#define __NOKPROBE_SYMBOL(fname)			\
> -static unsigned long __used				\
> -	__attribute__((section("_kprobe_blacklist")))	\
> -	_kbl_addr_##fname = (unsigned long)fname;
> -#define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
> -#else
> -#define NOKPROBE_SYMBOL(fname)
> -#endif
> -
>  #endif /* _LINUX_KPROBES_H */
> -- 
> 2.9.2
> 


-- 
Masami Hiramatsu <mhiramat@kernel.org>

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 00/16] linux: generalize sections, ranges and linker tables
  2016-08-19 22:29 ` [PATCH v4 00/16] linux: generalize sections, ranges and linker tables Kees Cook
@ 2016-08-22 23:06   ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-22 23:06 UTC (permalink / raw)
  To: Kees Cook
  Cc: gnomes, linux-ia64, Jiri Kosina, benh, Ming Lei, Heiko Carstens,
	platform-driver-x86, James Bottomley, Paul Gortmaker,
	Paul Mackerras, Michael Ellerman, H. Peter Anvin,
	Masami Hiramatsu, Mauro Carvalho Chehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, Russell King - ARM Linux,
	linux-sh, Will Deacon

On Fri, Aug 19, 2016 at 03:29:24PM -0700, Kees Cook wrote:
> On Fri, Aug 19, 2016 at 2:32 PM,  <mcgrof@kernel.org> wrote:
> > From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> >
> > This v4 addresses feedback from the previous v3 series [0], and also
> > addresses a huge array of additional tests against many architectures
> > outside of what 0-day provides. As I mentioned in my last v3 series,
> > 0-day had only found one issue with the series, a blackfin architecture
> > linker issue with the last series. Guenter Rock was kind enough to give
> > my series a test spin on his test bed and he found quite a bit of other
> > oddball issues with obscure architectures, and even on x86 with an old
> > toolchain. After a lot of work and coordinating with a few maintainers
> > I'm happy to report all issues found so far through all possible testing
> > I could do are now fixed, this series also addresses all feedback from
> > the last series, as such this goes submitted as PATCH form.
> >
> > In addressing fixing this work on a few architectures some of the previous
> > patches are further simplified. The kprobes port to linker tables is made
> > much easier now that I've addressed moving out core kprobe declarations
> > into asm-generic/kprobes.h. Refer to the patch "kprobes: move kprobe
> > declarations to asm-generic/kprobes.h". This makes for a much cleaner
> > solution across architectures.
> >
> > Boris feedback on making the code bit rot feature optional is addressed
> > by using a new Kconfig symbol for this, CONFIG_BUILD_AVOID_BITROT,
> > but given Greg's concerns over lack of clarity over what this was all about
> > I've ripped that functionality out into its own patch with a bit more
> > extensive documentation and re-wording. See the patch "kbuild: enable option
> > to force compile force-obj-y and force-lib-y". I hope makes it clear how
> > linker tables can help with avoiding code bit rot. I've gone with a new
> > Kconfig symbol CONFIG_BUILD_AVOID_BITROT given CONFIG_COMPILE_TEST is
> > not available on UML, this feature is desirable on all architectures.
> >
> > The documentation is revamped, now that the DocBook format is deprecated
> > I ported the documention into the trendy hipster Sphinx documentation
> > format.
> >
> > AT Boris' request I've adapated the userspace linker table application
> > forintegration into the kernel under tools/ to make it easier to keep
> > things in sync, however since this requires a bit of changes to some headers
> > in tools/ I'll submit that separately.
> >
> > [0] https://lkml.kernel.org/r/1469222687-1600-1-git-send-email-mcgrof@kernel.org
> >
> > If you'd like this in git-form, you can get it on the 20160819-linker-table-v4
> > branch of my linux-next tree on kernel.org, this also includes the series of
> > the linker table userspace sandbox:
> >
> > https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h=20160819-linker-table-v4
> >
> > Please let me know if there are any concerns or questions.
> 
> Thanks for the documentation and examples on this feature; I appreciate it! :)
> 
> While it seems like all the section declarations work in this series
> is designed for assembler source, I'm curious if I've missed a way to
> do this in .c source too.

Actually, the whole point to this originally was to provide helpers to
only do this in .c source code -- the fact that there are a few asm helpers
now is an after thought to provide parity of functionality to asm code to do
the exact same thing. The same macros provide the same functionality in
both C and asm code then and if there is some functionality lacking it may
for now just be on the asm side.

So for instance we have DECLARE_SECTION_RANGE() and that exist for C and
asm, but DECLARE_LINKTABLE() is currently only implemented for C code,
when and if we want it we can add it. DECLARE_SECTION_RANGE() has a demo
use in the userspace linker table sandbox.

> I'd love to avoid doing the crazy thing I'm currently doing in lkdtm 
> with section markings. Namely, I want to write a function in .c and have it
> moved into the .rodata section. The linkers get very very angry with me and I
> don't seem to be able to override the progbits to lose "x". Right now I'm
> doing an objcopy in
> drivers/misc/Makefile:
> 
> OBJCOPYFLAGS_lkdtm_rodata_objcopy.o := \
>                         --set-section-flags .text=alloc,readonly \
>                         --rename-section .text=.rodata
> targets += lkdtm_rodata.o lkdtm_rodata_objcopy.o
> $(obj)/lkdtm_rodata_objcopy.o: $(obj)/lkdtm_rodata.o FORCE
>         $(call if_changed,objcopy)
> 
> Thanks!

I'd have to take a closer look but from what you describe indeed this is
something that linker tables and section ranges is supposed to help with -- a
generic API to set sections in an architecture-agnostic way.  If you can
classify your functions with section ranges or linker tables then you should be
set. They flags used is whatever the architecture has decided to use for the
section as per the linker script and where each section falls under. If you
need more special tweaking (see flags in push_section_tbl()) then indeed some
newer APIs might be needed in C, as these flags tweaks are only provided for
asm right now but it'd be good to know if just using the existing APIs with
defaults for the section you needs for C code would not suffice.

If all you have is functions you can stick to section ranges, if these
functions are instead part of a larger data structure you need linker
tables. It sounds like you just have functions, and even if you needed
something outside of what is provided, say the flags, then adding a new
__LINUX_RANGE_FLAGS() could be added easily that also lets you specify
the flags you need.

For an example of section range us kprobes was ported over so we have
for instance:

# define __kprobes      __LINUX_RANGE(SECTION_TEXT, kprobes)

If you had something that needed custom flags you could see if
adding a __LINUX_RANGE_FLAGS() would suffice, but I'd be very
interested to know if the defaults used by the specified section
does not suffice.

Also  your use case seems to require a full file set to a section with specific
attributes. Although first instinct might be to use section ranges, if the
section range accessed some global variable or data structure in the file there
may be an issue, or you'd have to the also peg the data into a section. If this
is done it occurs to me an alternative is to just use a large data structure
to represent the full of functions and data, so to use a linker table that way
the association is done in one full swing with the definition of the table.

This of course is just at a cursory review.

  Luis

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
  2016-08-19 21:47   ` Kees Cook
@ 2016-08-22 23:13     ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-22 23:13 UTC (permalink / raw)
  To: Kees Cook
  Cc: gnomes, linux-ia64, Jiri Kosina, benh, Ming Lei, Heiko Carstens,
	platform-driver-x86, James Bottomley, Paul Gortmaker,
	Paul Mackerras, Michael Ellerman, H. Peter Anvin,
	Masami Hiramatsu, Mauro Carvalho Chehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, Russell King - ARM Linux,
	linux-sh, Will Deacon

On Fri, Aug 19, 2016 at 02:47:48PM -0700, Kees Cook wrote:
> On Fri, Aug 19, 2016 at 2:32 PM,  <mcgrof@kernel.org> wrote:
> > From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> >
> > +SECTION_RODATA
> > +--------------
> > +.. kernel-doc:: include/asm-generic/section-core.h
> > +   :doc: SECTION_RODATA
> > +
> > +SECTION_RODATA
> 
> Typo: should this be called SECTION_TEXT instead?

Fixed thanks.

> > +--------------
> > +.. kernel-doc:: include/asm-generic/section-core.h
> > +   :doc: SECTION_TEXT
> > +
> > +SECTION_DATA
> > +------------
> > +.. kernel-doc:: include/asm-generic/section-core.h
> > +   :doc: SECTION_DATA
> 
> Missing from this list are things like the __read_mostly
> (".data..read_mostly") and __ro_after_init (".data..ro_after_init")
> sections. Should those be included too, or are you only doing the "top
> level" sections?

I'm doing top level right now just to start off and get the
bikeshedding out of the way. We can add more with more time
or as we port more things or as the need arises.

  Luis

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 06/16] ranges.h: add helpers to build and identify Linux section ranges
  2016-08-19 21:55   ` Kees Cook
@ 2016-08-22 23:48     ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-22 23:48 UTC (permalink / raw)
  To: Kees Cook
  Cc: gnomes, linux-ia64, Jiri Kosina, benh, Ming Lei, Heiko Carstens,
	platform-driver-x86, James Bottomley, Paul Gortmaker,
	Paul Mackerras, Michael Ellerman, H. Peter Anvin,
	Masami Hiramatsu, Mauro Carvalho Chehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, Russell King - ARM Linux,
	linux-sh, Will Deacon

On Fri, Aug 19, 2016 at 02:55:43PM -0700, Kees Cook wrote:
> On Fri, Aug 19, 2016 at 2:32 PM,  <mcgrof@kernel.org> wrote:
> > From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> >
> > Section ranges are on one of the types of custom sections
> > types used in Linux. This provides a series of helpers for
> > defining them and using them. Most importantly this also
> > enables us to avoid modifying the linker script when we
> > add a new section range.
> >
> > It turns out a lot of custom sections are actually section ranges,
> > and these are typically spelled out in their architecture specific
> > asm/sections.h file -- we anable architectures to override what asm
> 
> Typo: anable -> enable

Fixed.

> > is used for section ranges but start by default trusting the
> > asm-generic version all around.
> 
> Can you explain the addition of the SORT() stuff in this patch? Its
> purpose isn't clear to me and doesn't appear to be mentioned in the
> commit log.

Indeed, let me explain and I'll also add this to the commit log.
We need to use SORT() in vmlinux.lds.S for section ranges for two
reasons:

a) By using SORT() and using "any" for cases where order does not
   matter we're able to extend section ranges without modifying the
   linker script. The special annotation used for the "order" for
   the first element of a section range is the empty string (see
   __SECTION_RANGE_BEGIN(), the ending element uses the character
   "~", see __SECTION_RANGE_END(). By default anything added in between
   uses the "any" order, when you use SORT() on this you end up stuffing
   all elements with the "any" order in between, and allowing you to have
   a beginning and end reference -- without modifying the linker script.

b) Although explicit order is typically not required for section ranges
   there is one use case brought to my attention we wanted to support
   where order was desired -- to build synthetic functions. An example
   is provided in asm in tools in the last patch where the linker tables
   sandbox is provided. Refer to tools/linker-tables/drivers/synth/or.S

> > diff --git a/include/asm-generic/ranges.h b/include/asm-generic/ranges.h
> > new file mode 100644
> > index 000000000000..74cd941aa2f8
> > --- /dev/null
> > +++ b/include/asm-generic/ranges.h
> > @@ -0,0 +1,89 @@
> > +#ifndef _ASM_GENERIC_RANGES_H_
> > +#define _ASM_GENERIC_RANGES_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/.
> > + */
> > +#include <asm/section-core.h>
> > +
> > +#define SECTION_RNG(section, name)                                     \
> 
> I would really prefer to avoid shortening "range" to the acronym for
> "random number generator". That's very confusing. :P It's only two
> letters more...

Speaking of, it'd be great if you could trim your reply to the hunks of
interest :) but yes sure, more bike shedding -- I'm happy to go with that
if that is the consensus.

  Luis

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 07/16] tables.h: add linker table support
  2016-08-19 22:02   ` Kees Cook
@ 2016-08-22 23:53     ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-22 23:53 UTC (permalink / raw)
  To: Kees Cook
  Cc: gnomes, linux-ia64, Jiri Kosina, benh, Ming Lei, Heiko Carstens,
	platform-driver-x86, James Bottomley, Paul Gortmaker,
	Paul Mackerras, Michael Ellerman, H. Peter Anvin,
	Masami Hiramatsu, Mauro Carvalho Chehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, Russell King - ARM Linux,
	linux-sh, Will Deacon

On Fri, Aug 19, 2016 at 03:02:07PM -0700, Kees Cook wrote:
> On Fri, Aug 19, 2016 at 2:32 PM,  <mcgrof@kernel.org> wrote:
> > 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@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.
> 
> Type: waek -> weak

Thanks, fixed.

  Luis

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 08/16] kbuild: enable option to force compile force-obj-y and force-lib-y
  2016-08-19 22:10   ` Kees Cook
@ 2016-08-22 23:59     ` Luis R. Rodriguez
  2016-08-30 20:15       ` Luis R. Rodriguez
  0 siblings, 1 reply; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-22 23:59 UTC (permalink / raw)
  To: Kees Cook, Michal Marek
  Cc: gnomes, linux-ia64, Jiri Kosina, benh, Ming Lei, Heiko Carstens,
	platform-driver-x86, James Bottomley, Paul Gortmaker,
	Paul Mackerras, Michael Ellerman, H. Peter Anvin,
	Masami Hiramatsu, Mauro Carvalho Chehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, Russell King - ARM Linux,
	linux-sh, Will Deacon

On Fri, Aug 19, 2016 at 03:10:33PM -0700, Kees Cook wrote:
> On Fri, Aug 19, 2016 at 2:32 PM,  <mcgrof@kernel.org> wrote:
> > diff --git a/init/Kconfig b/init/Kconfig
> > index cac3f096050d..ef09e83b9196 100644
> > --- a/init/Kconfig
> > +++ b/init/Kconfig
> > @@ -53,6 +53,28 @@ config CROSS_COMPILE
> >           need to set this unless you want the configured kernel build
> >           directory to select the cross-compiler automatically.
> >
> > +config BUILD_AVOID_BITROT
> > +       bool "Enable force building of force-obj-y and force-lib-y"
> 
> Sorry to continue the bikeshedding on this, but if I encounter
> something in a Makefile named "force-obj-y" I would expect it to
> always be built, no matter what. But this is not the case: the
> "force-" prefix is tied to this CONFIG_BUILD_AVOID_BITROT. This verb
> usage is weird, as I'd expect an adjective, like "forceable-obj-y" or
> something that describes that it CAN be built even with the CONFIG for
> it is missing, etc.
> 
> Regardless, I defer to Michal on this, but I'm not a fan of "force"
> being used when it's an optional action. :)

Sure, Michal let me know if forceable-obj-y and forceable-lib-y is the
way to go.

  Luis

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 7/7] tools: add userspace linker table sandbox
  2016-08-19 22:31       ` Kees Cook
@ 2016-08-23  0:07         ` Luis R. Rodriguez
  2016-08-23  0:28             ` H. Peter Anvin
                             ` (2 more replies)
  0 siblings, 3 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-23  0:07 UTC (permalink / raw)
  To: Kees Cook, Josh Poimboeuf, Arnaldo Carvalho de Melo
  Cc: gnomes, linux-ia64, Jiri Kosina, benh, Ming Lei, Heiko Carstens,
	platform-driver-x86, James Bottomley, Paul Gortmaker,
	Paul Mackerras, Michael Ellerman, H. Peter Anvin,
	Masami Hiramatsu, Mauro Carvalho Chehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, Russell King - ARM Linux,
	linux-sh, Will Deacon

On Fri, Aug 19, 2016 at 03:31:47PM -0700, Kees Cook wrote:
> On Fri, Aug 19, 2016 at 2:41 PM,  <mcgrof@kernel.org> wrote:
> > From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> >
> > Add a userspace sandbox to allow easy experimentation and
> > test extensions with linker tables, section ranges and the
> > new section core definitions.
> >
> > The userspace sandbox tries to mimic the Linux kernel development
> > flow as much as possible, it however relies on and uses libc. Support
> > is currently only provided to x86_64.
> >
> > v4: this patch is new in this series -- added to the kenrel as
> >     suggested by Boris, as otherwise it'd be really hard to keep
> >     an external userspace repository in sync.
> >
> > Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> > ---
> >  Documentation/sections/linker-tables.rst           |   4 +-
> >  MAINTAINERS                                        |   1 +
> >  include/linux/tables.h                             |   5 +-
> >  tools/Makefile                                     |   3 +-
> >  .../arch/x86/include/generated/asm/section-core.h  |   1 +
> >  tools/arch/x86/include/generated/ranges.h          |   1 +
> >  tools/arch/x86/include/generated/tables.h          |   1 +
> >  tools/include/asm-generic/ranges.h                 | 103 ++++
> >  tools/include/asm-generic/section-core.h           | 341 +++++++++++
> >  tools/include/asm-generic/tables.h                 |  50 ++
> 
> Aren't a bunch of these files exact duplicates of the headers in include/linux?

Indeed... This a userspace tools/ architecture decision that was made long ago,
so its not up to me, I am just following the strategy devised and picked up.
Refer to 7d7d1bf1d1dabe435ef50efb051724b8664749cb ("perf bench: Copy kernel
files needed to build mem{cpy,set} x86_64 benchmarks") for an example of
previous similar work. By sharing header files this enable more tools/
to be hacked on.

  Luis

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 7/7] tools: add userspace linker table sandbox
  2016-08-23  0:07         ` Luis R. Rodriguez
  2016-08-23  0:28             ` H. Peter Anvin
@ 2016-08-23  0:28             ` H. Peter Anvin
  2016-08-23  0:28           ` H. Peter Anvin
  2 siblings, 0 replies; 480+ messages in thread
From: H. Peter Anvin @ 2016-08-23  0:28 UTC (permalink / raw)
  To: Luis R. Rodriguez, Kees Cook, Josh Poimboeuf, Arnaldo Carvalho de Melo
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Russell King - ARM Linux, mhiramat, Masami Hiramatsu, jbaron,
	Heiko Carstens, ananth, anil.s.keshavamurthy, David S. Miller,
	Miao Steven, x86, Andy Lutomirski, Linus Torvalds, Greg KH,
	Rusty Russell, gnomes, Alan Cox, David Woodhouse, Arnd

Vrabel <david.vrabel@citrix.com>,Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>,Michael Brown <mcb30@ipxe.org>,Juergen Gross <jgross@suse.com>,Andrew Cooper <andrew.cooper3@citrix.com>,Andy Shevchenko <andriy.shevchenko@linux.intel.com>,Paul Gortmaker <paul.gortmaker@windriver.com>,"xen-devel@lists.xensource.com" <xen-devel@lists.xensource.com>,Andi Kleen <ak@linux.intel.com>,pali.rohar@gmail.com,dvhart@infradead.org,platform-driver-x86@vger.kernel.org,Michal Marek <mmarek@suse.com>,Rasmus Villemoes <linux@rasmusvillemoes.dk>,Jiri Kosina <jkosina@suse.cz>,=?UTF-8?B?7KGw6rK966+8?= <korea.drzix@gmail.com>,linux-kbuild <linux-kbuild@vger.kernel.org>,Tony Luck <tony.luck@intel.com>,Andrew Morton <akpm@linux-foundation.org>,linux-ia64@vger.kernel.org,"linux-arm-kernel@lists.infradead.org" <linux-arm-kernel@lists.infradead.org>,linux-sh <linux-sh@vger.kernel.org>,sparclinux <sparclinux@vger.kernel.org>,Catalin Marinas <catalin.marinas@arm.com>,Will Deacon <will.deacon@arm.com>,Ste!
 ven
Rostedt <rostedt@goodmis.org>,Jani Nikula <jani.nikula@intel.com>,Mauro Carvalho Chehab <mchehab@osg.samsung.com>,markus.heiser@darmarit.de,jolsa@kernel.org,Mark Salter <msalter@redhat.com>,Chris Zankel <chris@zankel.net>,Max Filippov <jcmvbkbc@gmail.com>,linux-xtensa@linux-xtensa.org,Paul Mackerras <paulus@samba.org>,Michael Ellerman <mpe@ellerman.id.au>,James Bottomley <James.Bottomley@hansenpartnership.com>
Message-ID: <58F06CEA-AEB3-4ED7-8211-95F402C9D3D3@zytor.com>

On August 22, 2016 5:07:39 PM PDT, "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
>On Fri, Aug 19, 2016 at 03:31:47PM -0700, Kees Cook wrote:
>> On Fri, Aug 19, 2016 at 2:41 PM,  <mcgrof@kernel.org> wrote:
>> > From: "Luis R. Rodriguez" <mcgrof@kernel.org>
>> >
>> > Add a userspace sandbox to allow easy experimentation and
>> > test extensions with linker tables, section ranges and the
>> > new section core definitions.
>> >
>> > The userspace sandbox tries to mimic the Linux kernel development
>> > flow as much as possible, it however relies on and uses libc.
>Support
>> > is currently only provided to x86_64.
>> >
>> > v4: this patch is new in this series -- added to the kenrel as
>> >     suggested by Boris, as otherwise it'd be really hard to keep
>> >     an external userspace repository in sync.
>> >
>> > Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
>> > ---
>> >  Documentation/sections/linker-tables.rst           |   4 +-
>> >  MAINTAINERS                                        |   1 +
>> >  include/linux/tables.h                             |   5 +-
>> >  tools/Makefile                                     |   3 +-
>> >  .../arch/x86/include/generated/asm/section-core.h  |   1 +
>> >  tools/arch/x86/include/generated/ranges.h          |   1 +
>> >  tools/arch/x86/include/generated/tables.h          |   1 +
>> >  tools/include/asm-generic/ranges.h                 | 103 ++++
>> >  tools/include/asm-generic/section-core.h           | 341
>+++++++++++
>> >  tools/include/asm-generic/tables.h                 |  50 ++
>> 
>> Aren't a bunch of these files exact duplicates of the headers in
>include/linux?
>
>Indeed... This a userspace tools/ architecture decision that was made
>long ago,
>so its not up to me, I am just following the strategy devised and
>picked up.
>Refer to 7d7d1bf1d1dabe435ef50efb051724b8664749cb ("perf bench: Copy
>kernel
>files needed to build mem{cpy,set} x86_64 benchmarks") for an example
>of
>previous similar work. By sharing header files this enable more tools/
>to be hacked on.
>
>  Luis

I think this is a legacy from before the uapi change that should really be fixed.  If we need to export additional kernel structures for the tools, we could define a third level of we really need it.
-- 
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 7/7] tools: add userspace linker table sandbox
  2016-08-23  0:07         ` Luis R. Rodriguez
  2016-08-23  0:28             ` H. Peter Anvin
  2016-08-23  0:28           ` H. Peter Anvin
@ 2016-08-23  0:28           ` H. Peter Anvin
  2 siblings, 0 replies; 480+ messages in thread
From: H. Peter Anvin @ 2016-08-23  0:28 UTC (permalink / raw)
  To: Luis R. Rodriguez, Kees Cook, Josh Poimboeuf, Arnaldo Carvalho de Melo
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Russell King - ARM Linux, mhiramat, Masami Hiramatsu, jbaron,
	Heiko Carstens, ananth, anil.s.keshavamurthy, David S. Miller,
	Miao Steven, x86, Andy Lutomirski, Linus Torvalds, Greg KH,
	Rusty Russell, gnomes, Alan Cox, David Woodhouse, Arnd

Vrabel <david.vrabel@citrix.com>,Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>,Michael Brown <mcb30@ipxe.org>,Juergen Gross <jgross@suse.com>,Andrew Cooper <andrew.cooper3@citrix.com>,Andy Shevchenko <andriy.shevchenko@linux.intel.com>,Paul Gortmaker <paul.gortmaker@windriver.com>,"xen-devel@lists.xensource.com" <xen-devel@lists.xensource.com>,Andi Kleen <ak@linux.intel.com>,pali.rohar@gmail.com,dvhart@infradead.org,platform-driver-x86@vger.kernel.org,Michal Marek <mmarek@suse.com>,Rasmus Villemoes <linux@rasmusvillemoes.dk>,Jiri Kosina <jkosina@suse.cz>,=?UTF-8?B?7KGw6rK966+8?= <korea.drzix@gmail.com>,linux-kbuild <linux-kbuild@vger.kernel.org>,Tony Luck <tony.luck@intel.com>,Andrew Morton <akpm@linux-foundation.org>,linux-ia64@vger.kernel.org,"linux-arm-kernel@lists.infradead.org" <linu
 x-arm-kernel@lists.infradead.org>,linux-sh <linux-sh@vger.kernel.org>,sparclinux <sparclinux@vger.kernel.org>,Catalin Marinas <catalin.marinas@arm.com>,Will Deacon <will.deacon@arm.com>,Ste!
 ven
Rostedt <rostedt@goodmis.org>,Jani Nikula <jani.nikula@intel.com>,Mauro Carvalho Chehab <mchehab@osg.samsung.com>,markus.heiser@darmarit.de,jolsa@kernel.org,Mark Salter <msalter@redhat.com>,Chris Zankel <chris@zankel.net>,Max Filippov <jcmvbkbc@gmail.com>,linux-xtensa@linux-xtensa.org,Paul Mackerras <paulus@samba.org>,Michael Ellerman <mpe@ellerman.id.au>,James Bottomley <James.Bottomley@hansenpartnership.com>
Message-ID: <58F06CEA-AEB3-4ED7-8211-95F402C9D3D3@zytor.com>

On August 22, 2016 5:07:39 PM PDT, "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
>On Fri, Aug 19, 2016 at 03:31:47PM -0700, Kees Cook wrote:
>> On Fri, Aug 19, 2016 at 2:41 PM,  <mcgrof@kernel.org> wrote:
>> > From: "Luis R. Rodriguez" <mcgrof@kernel.org>
>> >
>> > Add a userspace sandbox to allow easy experimentation and
>> > test extensions with linker tables, section ranges and the
>> > new section core definitions.
>> >
>> > The userspace sandbox tries to mimic the Linux kernel development
>> > flow as much as possible, it however relies on and uses libc.
>Support
>> > is currently only provided to x86_64.
>> >
>> > v4: this patch is new in this series -- added to the kenrel as
>> >     suggested by Boris, as otherwise it'd be really hard to keep
>> >     an external userspace repository in sync.
>> >
>> > Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
>> > ---
>> >  Documentation/sections/linker-tables.rst           |   4 +-
>> >  MAINTAINERS                                        |   1 +
>> >  include/linux/tables.h                             |   5 +-
>> >  tools/Makefile                                     |   3 +-
>> >  .../arch/x86/include/generated/asm/section-core.h  |   1 +
>> >  tools/arch/x86/include/generated/ranges.h          |   1 +
>> >  tools/arch/x86/include/generated/tables.h          |   1 +
>> >  tools/include/asm-generic/ranges.h                 | 103 ++++
>> >  tools/include/asm-generic/section-core.h           | 341
>+++++++++++
>> >  tools/include/asm-generic/tables.h                 |  50 ++
>> 
>> Aren't a bunch of these files exact duplicates of the headers in
>include/linux?
>
>Indeed... This a userspace tools/ architecture decision that was made
>long ago,
>so its not up to me, I am just following the strategy devised and
>picked up.
>Refer to 7d7d1bf1d1dabe435ef50efb051724b8664749cb ("perf bench: Copy
>kernel
>files needed to build mem{cpy,set} x86_64 benchmarks") for an example
>of
>previous similar work. By sharing header files this enable more tools/
>to be hacked on.
>
>  Luis

I think this is a legacy from before the uapi change that should really be fixed.  If we need to export additional kernel structures for the tools, we could define a third level of we really need it.
-- 
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 7/7] tools: add userspace linker table sandbox
@ 2016-08-23  0:28             ` H. Peter Anvin
  0 siblings, 0 replies; 480+ messages in thread
From: H. Peter Anvin @ 2016-08-23  0:28 UTC (permalink / raw)
  To: Luis R. Rodriguez, Kees Cook, Josh Poimboeuf, Arnaldo Carvalho de Melo
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Russell King - ARM Linux, mhiramat, Masami Hiramatsu, jbaron,
	Heiko Carstens, ananth, anil.s.keshavamurthy, David S. Miller,
	Miao Steven, x86, Andy Lutomirski, Linus Torvalds, Greg KH,
	Rusty Russell, gnomes, Alan Cox, David Woodhouse, Arnd Bergmann,
	Ming Lei, linux-arch, benh, ananth, Paul Bolle, fontana, David

Vrabel <david.vrabel@citrix.com>,Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>,Michael Brown <mcb30@ipxe.org>,Juergen Gross <jgross@suse.com>,Andrew Cooper <andrew.cooper3@citrix.com>,Andy Shevchenko <andriy.shevchenko@linux.intel.com>,Paul Gortmaker <paul.gortmaker@windriver.com>,"xen-devel@lists.xensource.com" <xen-devel@lists.xensource.com>,Andi Kleen <ak@linux.intel.com>,pali.rohar@gmail.com,dvhart@infradead.org,platform-driver-x86@vger.kernel.org,Michal Marek <mmarek@suse.com>,Rasmus Villemoes <linux@rasmusvillemoes.dk>,Jiri Kosina <jkosina@suse.cz>,=?UTF-8?B?7KGw6rK966+8?= <korea.drzix@gmail.com>,linux-kbuild <linux-kbuild@vger.kernel.org>,Tony Luck <tony.luck@intel.com>,Andrew Morton <akpm@linux-foundation.org>,linux-ia64@vger.kernel.org,"linux-arm-kernel@lists.infradead.org" <linux-arm-kernel@lists.infradead.org>,linux-sh <linux-sh@vger.kernel.org>,sparclinux <sparclinux@vger.kernel.org>,Catalin Marinas <catalin.marinas@arm.com>,Will Deacon <will.deacon@arm.com>,Ste!
 ven
Rostedt <rostedt@goodmis.org>,Jani Nikula <jani.nikula@intel.com>,Mauro Carvalho Chehab <mchehab@osg.samsung.com>,markus.heiser@darmarit.de,jolsa@kernel.org,Mark Salter <msalter@redhat.com>,Chris Zankel <chris@zankel.net>,Max Filippov <jcmvbkbc@gmail.com>,linux-xtensa@linux-xtensa.org,Paul Mackerras <paulus@samba.org>,Michael Ellerman <mpe@ellerman.id.au>,James Bottomley <James.Bottomley@hansenpartnership.com>
Message-ID: <58F06CEA-AEB3-4ED7-8211-95F402C9D3D3@zytor.com>

On August 22, 2016 5:07:39 PM PDT, "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
>On Fri, Aug 19, 2016 at 03:31:47PM -0700, Kees Cook wrote:
>> On Fri, Aug 19, 2016 at 2:41 PM,  <mcgrof@kernel.org> wrote:
>> > From: "Luis R. Rodriguez" <mcgrof@kernel.org>
>> >
>> > Add a userspace sandbox to allow easy experimentation and
>> > test extensions with linker tables, section ranges and the
>> > new section core definitions.
>> >
>> > The userspace sandbox tries to mimic the Linux kernel development
>> > flow as much as possible, it however relies on and uses libc.
>Support
>> > is currently only provided to x86_64.
>> >
>> > v4: this patch is new in this series -- added to the kenrel as
>> >     suggested by Boris, as otherwise it'd be really hard to keep
>> >     an external userspace repository in sync.
>> >
>> > Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
>> > ---
>> >  Documentation/sections/linker-tables.rst           |   4 +-
>> >  MAINTAINERS                                        |   1 +
>> >  include/linux/tables.h                             |   5 +-
>> >  tools/Makefile                                     |   3 +-
>> >  .../arch/x86/include/generated/asm/section-core.h  |   1 +
>> >  tools/arch/x86/include/generated/ranges.h          |   1 +
>> >  tools/arch/x86/include/generated/tables.h          |   1 +
>> >  tools/include/asm-generic/ranges.h                 | 103 ++++
>> >  tools/include/asm-generic/section-core.h           | 341
>+++++++++++
>> >  tools/include/asm-generic/tables.h                 |  50 ++
>> 
>> Aren't a bunch of these files exact duplicates of the headers in
>include/linux?
>
>Indeed... This a userspace tools/ architecture decision that was made
>long ago,
>so its not up to me, I am just following the strategy devised and
>picked up.
>Refer to 7d7d1bf1d1dabe435ef50efb051724b8664749cb ("perf bench: Copy
>kernel
>files needed to build mem{cpy,set} x86_64 benchmarks") for an example
>of
>previous similar work. By sharing header files this enable more tools/
>to be hacked on.
>
>  Luis

I think this is a legacy from before the uapi change that should really be fixed.  If we need to export additional kernel structures for the tools, we could define a third level of we really need it.
-- 
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 7/7] tools: add userspace linker table sandbox
@ 2016-08-23  0:28             ` H. Peter Anvin
  0 siblings, 0 replies; 480+ messages in thread
From: H. Peter Anvin @ 2016-08-23  0:28 UTC (permalink / raw)
  To: Luis R. Rodriguez, Kees Cook, Josh Poimboeuf, Arnaldo Carvalho de Melo
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Russell King - ARM Linux, mhiramat, Masami Hiramatsu, jbaron,
	Heiko Carstens, ananth, anil.s.keshavamurthy, David S. Miller,
	Miao Steven, x86, Andy Lutomirski, Linus Torvalds, Greg KH,
	Rusty Russell, gnomes, Alan Cox, David Woodhouse, Arnd

Vrabel <david.vrabel@citrix.com>,Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>,Michael Brown <mcb30@ipxe.org>,Juergen Gross <jgross@suse.com>,Andrew Cooper <andrew.cooper3@citrix.com>,Andy Shevchenko <andriy.shevchenko@linux.intel.com>,Paul Gortmaker <paul.gortmaker@windriver.com>,"xen-devel@lists.xensource.com" <xen-devel@lists.xensource.com>,Andi Kleen <ak@linux.intel.com>,pali.rohar@gmail.com,dvhart@infradead.org,platform-driver-x86@vger.kernel.org,Michal Marek <mmarek@suse.com>,Rasmus Villemoes <linux@rasmusvillemoes.dk>,Jiri Kosina <jkosina@suse.cz>,=?UTF-8?B?7KGw6rK966+8?= <korea.drzix@gmail.com>,linux-kbuild <linux-kbuild@vger.kernel.org>,Tony Luck <tony.luck@intel.com>,Andrew Morton <akpm@linux-foundation.org>,linux-ia64@vger.kernel.org,"linux-arm-kernel@lists.infradead.org" <linu
 x-arm-kernel@lists.infradead.org>,linux-sh <linux-sh@vger.kernel.org>,sparclinux <sparclinux@vger.kernel.org>,Catalin Marinas <catalin.marinas@arm.com>,Will Deacon <will.deacon@arm.com>,Ste!
 ven
Rostedt <rostedt@goodmis.org>,Jani Nikula <jani.nikula@intel.com>,Mauro Carvalho Chehab <mchehab@osg.samsung.com>,markus.heiser@darmarit.de,jolsa@kernel.org,Mark Salter <msalter@redhat.com>,Chris Zankel <chris@zankel.net>,Max Filippov <jcmvbkbc@gmail.com>,linux-xtensa@linux-xtensa.org,Paul Mackerras <paulus@samba.org>,Michael Ellerman <mpe@ellerman.id.au>,James Bottomley <James.Bottomley@hansenpartnership.com>
Message-ID: <58F06CEA-AEB3-4ED7-8211-95F402C9D3D3@zytor.com>

On August 22, 2016 5:07:39 PM PDT, "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
>On Fri, Aug 19, 2016 at 03:31:47PM -0700, Kees Cook wrote:
>> On Fri, Aug 19, 2016 at 2:41 PM,  <mcgrof@kernel.org> wrote:
>> > From: "Luis R. Rodriguez" <mcgrof@kernel.org>
>> >
>> > Add a userspace sandbox to allow easy experimentation and
>> > test extensions with linker tables, section ranges and the
>> > new section core definitions.
>> >
>> > The userspace sandbox tries to mimic the Linux kernel development
>> > flow as much as possible, it however relies on and uses libc.
>Support
>> > is currently only provided to x86_64.
>> >
>> > v4: this patch is new in this series -- added to the kenrel as
>> >     suggested by Boris, as otherwise it'd be really hard to keep
>> >     an external userspace repository in sync.
>> >
>> > Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
>> > ---
>> >  Documentation/sections/linker-tables.rst           |   4 +-
>> >  MAINTAINERS                                        |   1 +
>> >  include/linux/tables.h                             |   5 +-
>> >  tools/Makefile                                     |   3 +-
>> >  .../arch/x86/include/generated/asm/section-core.h  |   1 +
>> >  tools/arch/x86/include/generated/ranges.h          |   1 +
>> >  tools/arch/x86/include/generated/tables.h          |   1 +
>> >  tools/include/asm-generic/ranges.h                 | 103 ++++
>> >  tools/include/asm-generic/section-core.h           | 341
>+++++++++++
>> >  tools/include/asm-generic/tables.h                 |  50 ++
>> 
>> Aren't a bunch of these files exact duplicates of the headers in
>include/linux?
>
>Indeed... This a userspace tools/ architecture decision that was made
>long ago,
>so its not up to me, I am just following the strategy devised and
>picked up.
>Refer to 7d7d1bf1d1dabe435ef50efb051724b8664749cb ("perf bench: Copy
>kernel
>files needed to build mem{cpy,set} x86_64 benchmarks") for an example
>of
>previous similar work. By sharing header files this enable more tools/
>to be hacked on.
>
>  Luis

I think this is a legacy from before the uapi change that should really be fixed.  If we need to export additional kernel structures for the tools, we could define a third level of we really need it.
-- 
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 7/7] tools: add userspace linker table sandbox
  2016-08-23  0:07         ` Luis R. Rodriguez
  2016-08-23  0:28             ` H. Peter Anvin
@ 2016-08-23  0:28           ` H. Peter Anvin
  2016-08-23  0:28           ` H. Peter Anvin
  2 siblings, 0 replies; 480+ messages in thread
From: H. Peter Anvin @ 2016-08-23  0:28 UTC (permalink / raw)
  To: Luis R. Rodriguez, Kees Cook, Josh Poimboeuf, Arnaldo Carvalho de Melo
  Cc: gnomes, benh, Ming Lei, Heiko Carstens, Masami Hiramatsu,
	linux-arch, Russell King - ARM Linux, x86, anil.s.keshavamurthy,
	fontana, Linus Torvalds, Ingo Molnar, Arnd Bergmann, Miao Steven,
	Rusty Russell, David, jbaron, ananth, Borislav Petkov,
	Thomas Gleixner, Alan Cox, Paul Bolle, ananth, Greg KH

Vrabel <david.vrabel@citrix.com>,Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>,Michael Brown <mcb30@ipxe.org>,Juergen Gross <jgross@suse.com>,Andrew Cooper <andrew.cooper3@citrix.com>,Andy Shevchenko <andriy.shevchenko@linux.intel.com>,Paul Gortmaker <paul.gortmaker@windriver.com>,"xen-devel@lists.xensource.com" <xen-devel@lists.xensource.com>,Andi Kleen <ak@linux.intel.com>,pali.rohar@gmail.com,dvhart@infradead.org,platform-driver-x86@vger.kernel.org,Michal Marek <mmarek@suse.com>,Rasmus Villemoes <linux@rasmusvillemoes.dk>,Jiri Kosina <jkosina@suse.cz>,=?UTF-8?B?7KGw6rK966+8?= <korea.drzix@gmail.com>,linux-kbuild <linux-kbuild@vger.kernel.org>,Tony Luck <tony.luck@intel.com>,Andrew Morton <akpm@linux-foundation.org>,linux-ia64@vger.kernel.org,"linux-arm-kernel@lists.infradead.org" <linux-arm-kernel@lists.infradead.org>,linux-sh <linux-sh@vger.kernel.org>,sparclinux <sparclinux@vger.kernel.org>,Catalin Marinas <catalin.marinas@arm.com>,Will Deacon <will.deacon@arm.com>,Ste!
 ven
Rostedt <rostedt@goodmis.org>,Jani Nikula <jani.nikula@intel.com>,Mauro Carvalho Chehab <mchehab@osg.samsung.com>,markus.heiser@darmarit.de,jolsa@kernel.org,Mark Salter <msalter@redhat.com>,Chris Zankel <chris@zankel.net>,Max Filippov <jcmvbkbc@gmail.com>,linux-xtensa@linux-xtensa.org,Paul Mackerras <paulus@samba.org>,Michael Ellerman <mpe@ellerman.id.au>,James Bottomley <James.Bottomley@hansenpartnership.com>
Message-ID: <58F06CEA-AEB3-4ED7-8211-95F402C9D3D3@zytor.com>

On August 22, 2016 5:07:39 PM PDT, "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
>On Fri, Aug 19, 2016 at 03:31:47PM -0700, Kees Cook wrote:
>> On Fri, Aug 19, 2016 at 2:41 PM,  <mcgrof@kernel.org> wrote:
>> > From: "Luis R. Rodriguez" <mcgrof@kernel.org>
>> >
>> > Add a userspace sandbox to allow easy experimentation and
>> > test extensions with linker tables, section ranges and the
>> > new section core definitions.
>> >
>> > The userspace sandbox tries to mimic the Linux kernel development
>> > flow as much as possible, it however relies on and uses libc.
>Support
>> > is currently only provided to x86_64.
>> >
>> > v4: this patch is new in this series -- added to the kenrel as
>> >     suggested by Boris, as otherwise it'd be really hard to keep
>> >     an external userspace repository in sync.
>> >
>> > Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
>> > ---
>> >  Documentation/sections/linker-tables.rst           |   4 +-
>> >  MAINTAINERS                                        |   1 +
>> >  include/linux/tables.h                             |   5 +-
>> >  tools/Makefile                                     |   3 +-
>> >  .../arch/x86/include/generated/asm/section-core.h  |   1 +
>> >  tools/arch/x86/include/generated/ranges.h          |   1 +
>> >  tools/arch/x86/include/generated/tables.h          |   1 +
>> >  tools/include/asm-generic/ranges.h                 | 103 ++++
>> >  tools/include/asm-generic/section-core.h           | 341
>+++++++++++
>> >  tools/include/asm-generic/tables.h                 |  50 ++
>> 
>> Aren't a bunch of these files exact duplicates of the headers in
>include/linux?
>
>Indeed... This a userspace tools/ architecture decision that was made
>long ago,
>so its not up to me, I am just following the strategy devised and
>picked up.
>Refer to 7d7d1bf1d1dabe435ef50efb051724b8664749cb ("perf bench: Copy
>kernel
>files needed to build mem{cpy,set} x86_64 benchmarks") for an example
>of
>previous similar work. By sharing header files this enable more tools/
>to be hacked on.
>
>  Luis

I think this is a legacy from before the uapi change that should really be fixed.  If we need to export additional kernel structures for the tools, we could define a third level of we really need it.
-- 
Sent from my Android device with K-9 Mail. Please excuse brevity and formatting.

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
  2016-08-19 21:34     ` mcgrof
  (?)
@ 2016-08-23  1:26       ` Nicholas Piggin
  -1 siblings, 0 replies; 480+ messages in thread
From: Nicholas Piggin @ 2016-08-23  1:26 UTC (permalink / raw)
  To: mcgrof
  Cc: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3

On Fri, 19 Aug 2016 14:34:02 -0700
mcgrof@kernel.org wrote:

> From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> 
> Linux makes extensive use of custom ELF header sections,
> documentation for these are well scatterred. Unify this
> documentation in a central place and provide helpers to
> build custom Linux sections.
> 
> This also generalizes sections code to enable avoiding
> modifying the linker scripts when we want to add new
> custom Linux sections. In order to make this generally
> useful we need to ensure all architectures can make use of
> core section helpers but that they can also override should
> this be needed. Instead of relying on section.h this adds
> a sections-core.h since this will be targetted to be safe
> to be used on asm code, linker scripts and C code.

Hi Luis,

The linker stuff in the kernel definitely needs someone to take care
of it, so it's good to see some effort to clean up and generalize some
of it.

Not all your patches seem to depend on each other, so it might be good
to push some of the cleanups through first. And some of these core
patches could go in bit by bit if necessary.

On this specific patch: while the as and ld sections syntax and
semantics are pretty ugly and esoteric, I question how much of this is
actually an improvement. Some of it seems to just be wrapping one name
with another, or hiding some behaviour in a maybe not intuitive way.


> +/**
> + * DOC: Standard ELF section use in Linux
> + *
> + * Linux makes use of the standard ELF sections, this sections documents
> + * these.
> + */
> +
> +/**
> + * DOC: SECTION_RODATA
> + *
> + * Macro name for code which must be protected from write access, read only
> + * data.
> + */
> +#define SECTION_RODATA			.rodata

These, for example. The exact name of the section is important in linker
scripts and asm, so I can't see the benefit of hiding it. I could be
missing the bigger picture.


> +/**
> + * DOC: SECTION_TEXT
> + *
> + * Macro name used to annotate code (functions) used during regular
> + * kernel run time. This is combined with `SECTION_RODATA`, only this
> + * section also allows for execution.
> + *
> + */
> +#define SECTION_TEXT			.text

I can't see how these comments are right. .rodata doesn't seem like it
should be combined with .text, and is not currently on powerpc. I think
it's for data, not code.


> +/*
> + * These section _ALL() helpers are for use on linker scripts and helpers
> + */
> +#define SECTION_ALL(__section)						\
> +	__section##.*

This is another example. We know what .text.* does in the linker scripts
-- it's self documenting. But SECTION_ALL(.text)? I'm not sure that's an
improvement. Actually I saw it in the linker script changes and had to
come find the definition because I was a bit mislead:

SECTION_ALL(.text)

Initially I would expect this to be

.text*

Not

.text.*

The latter does not grab the .text section!


> +/*
> + * As per gcc's documentation a common asm separator is a new line followed
> + * by tab [0], it however seems possible to also just use a newline as its
> + * the most commonly empirically observed semantic and folks seem to agree
> + * this even works on S390. In case your architecture disagrees you may
> + * override this and define your own and keep the rest of the macros.
> + *
> + * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
> + */
> +# ifndef ASM_CMD_SEP
> +#  define ASM_CMD_SEP	"\n"
> +# endif

This does not seem like it belongs here. The name is fairly ugly too.
I guess something might be needed like this when dealing with generic
as directives common to all architectures, though. I would say
include/asm-generic/asm.h should be a better place.


> diff --git a/include/linux/sections.h b/include/linux/sections.h
> new file mode 100644
> index 000000000000..f21c6ee88ded
> --- /dev/null
> +++ b/include/linux/sections.h
> @@ -0,0 +1,111 @@
> +#ifndef _LINUX_SECTIONS_H
> +#define _LINUX_SECTIONS_H
> +/*
> + * Linux de-facto sections
> + *
> + * 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>
> +#include <linux/export.h>
> +
> +#ifndef __ASSEMBLY__
> +
> +/**
> + * DOC: Introduction
> + *
> + * Linux defines a set of common helpers which can be used to against its use
> + * of standard or custom Linux sections, this section is dedicated to these
> + * helpers.

I'm still not quite sure what a Linux de-facto/standard/common section is
after this. Are they output sections?

I think it would be reasonable to drop the LINUX_ prefix and references to
Linux.

Thanks,
Nick

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-23  1:26       ` Nicholas Piggin
  0 siblings, 0 replies; 480+ messages in thread
From: Nicholas Piggin @ 2016-08-23  1:26 UTC (permalink / raw)
  To: mcgrof
  Cc: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3

On Fri, 19 Aug 2016 14:34:02 -0700
mcgrof@kernel.org wrote:

> From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> 
> Linux makes extensive use of custom ELF header sections,
> documentation for these are well scatterred. Unify this
> documentation in a central place and provide helpers to
> build custom Linux sections.
> 
> This also generalizes sections code to enable avoiding
> modifying the linker scripts when we want to add new
> custom Linux sections. In order to make this generally
> useful we need to ensure all architectures can make use of
> core section helpers but that they can also override should
> this be needed. Instead of relying on section.h this adds
> a sections-core.h since this will be targetted to be safe
> to be used on asm code, linker scripts and C code.

Hi Luis,

The linker stuff in the kernel definitely needs someone to take care
of it, so it's good to see some effort to clean up and generalize some
of it.

Not all your patches seem to depend on each other, so it might be good
to push some of the cleanups through first. And some of these core
patches could go in bit by bit if necessary.

On this specific patch: while the as and ld sections syntax and
semantics are pretty ugly and esoteric, I question how much of this is
actually an improvement. Some of it seems to just be wrapping one name
with another, or hiding some behaviour in a maybe not intuitive way.


> +/**
> + * DOC: Standard ELF section use in Linux
> + *
> + * Linux makes use of the standard ELF sections, this sections documents
> + * these.
> + */
> +
> +/**
> + * DOC: SECTION_RODATA
> + *
> + * Macro name for code which must be protected from write access, read only
> + * data.
> + */
> +#define SECTION_RODATA			.rodata

These, for example. The exact name of the section is important in linker
scripts and asm, so I can't see the benefit of hiding it. I could be
missing the bigger picture.


> +/**
> + * DOC: SECTION_TEXT
> + *
> + * Macro name used to annotate code (functions) used during regular
> + * kernel run time. This is combined with `SECTION_RODATA`, only this
> + * section also allows for execution.
> + *
> + */
> +#define SECTION_TEXT			.text

I can't see how these comments are right. .rodata doesn't seem like it
should be combined with .text, and is not currently on powerpc. I think
it's for data, not code.


> +/*
> + * These section _ALL() helpers are for use on linker scripts and helpers
> + */
> +#define SECTION_ALL(__section)						\
> +	__section##.*

This is another example. We know what .text.* does in the linker scripts
-- it's self documenting. But SECTION_ALL(.text)? I'm not sure that's an
improvement. Actually I saw it in the linker script changes and had to
come find the definition because I was a bit mislead:

SECTION_ALL(.text)

Initially I would expect this to be

.text*

Not

.text.*

The latter does not grab the .text section!


> +/*
> + * As per gcc's documentation a common asm separator is a new line followed
> + * by tab [0], it however seems possible to also just use a newline as its
> + * the most commonly empirically observed semantic and folks seem to agree
> + * this even works on S390. In case your architecture disagrees you may
> + * override this and define your own and keep the rest of the macros.
> + *
> + * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
> + */
> +# ifndef ASM_CMD_SEP
> +#  define ASM_CMD_SEP	"\n"
> +# endif

This does not seem like it belongs here. The name is fairly ugly too.
I guess something might be needed like this when dealing with generic
as directives common to all architectures, though. I would say
include/asm-generic/asm.h should be a better place.


> diff --git a/include/linux/sections.h b/include/linux/sections.h
> new file mode 100644
> index 000000000000..f21c6ee88ded
> --- /dev/null
> +++ b/include/linux/sections.h
> @@ -0,0 +1,111 @@
> +#ifndef _LINUX_SECTIONS_H
> +#define _LINUX_SECTIONS_H
> +/*
> + * Linux de-facto sections
> + *
> + * 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>
> +#include <linux/export.h>
> +
> +#ifndef __ASSEMBLY__
> +
> +/**
> + * DOC: Introduction
> + *
> + * Linux defines a set of common helpers which can be used to against its use
> + * of standard or custom Linux sections, this section is dedicated to these
> + * helpers.

I'm still not quite sure what a Linux de-facto/standard/common section is
after this. Are they output sections?

I think it would be reasonable to drop the LINUX_ prefix and references to
Linux.

Thanks,
Nick

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-23  1:26       ` Nicholas Piggin
  0 siblings, 0 replies; 480+ messages in thread
From: Nicholas Piggin @ 2016-08-23  1:26 UTC (permalink / raw)
  To: mcgrof
  Cc: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, acme, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, paulus, mpe, James.Bottomley

On Fri, 19 Aug 2016 14:34:02 -0700
mcgrof@kernel.org wrote:

> From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> 
> Linux makes extensive use of custom ELF header sections,
> documentation for these are well scatterred. Unify this
> documentation in a central place and provide helpers to
> build custom Linux sections.
> 
> This also generalizes sections code to enable avoiding
> modifying the linker scripts when we want to add new
> custom Linux sections. In order to make this generally
> useful we need to ensure all architectures can make use of
> core section helpers but that they can also override should
> this be needed. Instead of relying on section.h this adds
> a sections-core.h since this will be targetted to be safe
> to be used on asm code, linker scripts and C code.

Hi Luis,

The linker stuff in the kernel definitely needs someone to take care
of it, so it's good to see some effort to clean up and generalize some
of it.

Not all your patches seem to depend on each other, so it might be good
to push some of the cleanups through first. And some of these core
patches could go in bit by bit if necessary.

On this specific patch: while the as and ld sections syntax and
semantics are pretty ugly and esoteric, I question how much of this is
actually an improvement. Some of it seems to just be wrapping one name
with another, or hiding some behaviour in a maybe not intuitive way.


> +/**
> + * DOC: Standard ELF section use in Linux
> + *
> + * Linux makes use of the standard ELF sections, this sections documents
> + * these.
> + */
> +
> +/**
> + * DOC: SECTION_RODATA
> + *
> + * Macro name for code which must be protected from write access, read only
> + * data.
> + */
> +#define SECTION_RODATA			.rodata

These, for example. The exact name of the section is important in linker
scripts and asm, so I can't see the benefit of hiding it. I could be
missing the bigger picture.


> +/**
> + * DOC: SECTION_TEXT
> + *
> + * Macro name used to annotate code (functions) used during regular
> + * kernel run time. This is combined with `SECTION_RODATA`, only this
> + * section also allows for execution.
> + *
> + */
> +#define SECTION_TEXT			.text

I can't see how these comments are right. .rodata doesn't seem like it
should be combined with .text, and is not currently on powerpc. I think
it's for data, not code.


> +/*
> + * These section _ALL() helpers are for use on linker scripts and helpers
> + */
> +#define SECTION_ALL(__section)						\
> +	__section##.*

This is another example. We know what .text.* does in the linker scripts
-- it's self documenting. But SECTION_ALL(.text)? I'm not sure that's an
improvement. Actually I saw it in the linker script changes and had to
come find the definition because I was a bit mislead:

SECTION_ALL(.text)

Initially I would expect this to be

.text*

Not

.text.*

The latter does not grab the .text section!


> +/*
> + * As per gcc's documentation a common asm separator is a new line followed
> + * by tab [0], it however seems possible to also just use a newline as its
> + * the most commonly empirically observed semantic and folks seem to agree
> + * this even works on S390. In case your architecture disagrees you may
> + * override this and define your own and keep the rest of the macros.
> + *
> + * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
> + */
> +# ifndef ASM_CMD_SEP
> +#  define ASM_CMD_SEP	"\n"
> +# endif

This does not seem like it belongs here. The name is fairly ugly too.
I guess something might be needed like this when dealing with generic
as directives common to all architectures, though. I would say
include/asm-generic/asm.h should be a better place.


> diff --git a/include/linux/sections.h b/include/linux/sections.h
> new file mode 100644
> index 000000000000..f21c6ee88ded
> --- /dev/null
> +++ b/include/linux/sections.h
> @@ -0,0 +1,111 @@
> +#ifndef _LINUX_SECTIONS_H
> +#define _LINUX_SECTIONS_H
> +/*
> + * Linux de-facto sections
> + *
> + * 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>
> +#include <linux/export.h>
> +
> +#ifndef __ASSEMBLY__
> +
> +/**
> + * DOC: Introduction
> + *
> + * Linux defines a set of common helpers which can be used to against its use
> + * of standard or custom Linux sections, this section is dedicated to these
> + * helpers.

I'm still not quite sure what a Linux de-facto/standard/common section is
after this. Are they output sections?

I think it would be reasonable to drop the LINUX_ prefix and references to
Linux.

Thanks,
Nick

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 7/7] tools: add userspace linker table sandbox
@ 2016-08-23 14:30               ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 480+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-08-23 14:30 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Luis R. Rodriguez, Kees Cook, Josh Poimboeuf, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Russell King - ARM Linux, mhiramat,
	Masami Hiramatsu, jbaron, Heiko Carstens, ananth,
	anil.s.keshavamurthy, David S. Miller, Miao Steven, x86,
	Andy Lutomirski, Linus Torvalds, Greg KH, Rusty Russell, gnomes

Em Mon, Aug 22, 2016 at 05:28:42PM -0700, H. Peter Anvin escreveu:
> On August 22, 2016 5:07:39 PM PDT, "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> >On Fri, Aug 19, 2016 at 03:31:47PM -0700, Kees Cook wrote:
> >> On Fri, Aug 19, 2016 at 2:41 PM,  <mcgrof@kernel.org> wrote:
> >> >  tools/Makefile                                     |   3 +-
> >> >  .../arch/x86/include/generated/asm/section-core.h  |   1 +
> >> >  tools/arch/x86/include/generated/ranges.h          |   1 +
> >> >  tools/arch/x86/include/generated/tables.h          |   1 +
> >> >  tools/include/asm-generic/ranges.h                 | 103 ++++
> >> >  tools/include/asm-generic/section-core.h           | 341

> >> >  tools/include/asm-generic/tables.h                 |  50 ++

> >> Aren't a bunch of these files exact duplicates of the headers in
> >include/linux?

> >Indeed... This a userspace tools/ architecture decision that was made
> >long ago, so its not up to me, I am just following the strategy
> >devised and picked up.  Refer to
> >7d7d1bf1d1dabe435ef50efb051724b8664749cb ("perf bench: Copy kernel
> >files needed to build mem{cpy,set} x86_64 benchmarks") for an example
> >of previous similar work. By sharing header files this enable more
> >tools/ to be hacked on.
 
> I think this is a legacy from before the uapi change that should
> really be fixed.  If we need to export additional kernel structures
> for the tools, we could define a third level of we really need it.

No, it is something recent, its just that from time to time files that
tools/ included from outside, i.e. from the kernel sources, made tools/
break, so after discussion with Linus and Ingo[1], it was decided we would
grab copies and never more access anything outside tools/ directly.

Instead we would check for changes and warn the tools/ developers about
it, so that they could check what has changed, that could mean changes
should/could be done to tools/ using those headers.

- Arnaldo

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 7/7] tools: add userspace linker table sandbox
@ 2016-08-23 14:30               ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 480+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-08-23 14:30 UTC (permalink / raw)
  To: H. Peter Anvin
  Cc: Luis R. Rodriguez, Kees Cook, Josh Poimboeuf, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Russell King - ARM Linux, mhiramat,
	Masami Hiramatsu, jbaron, Heiko Carstens, ananth,
	anil.s.keshavamurthy, David S. Miller, Miao Steven, x86,
	Andy Lutomirski, Linus Torvalds, Greg KH, Rusty Russell, gnomes,
	Alan Cox, David Woodhouse, Arnd Bergmann, Ming Lei, linux-arch,
	benh, ananth, Paul Bolle, fontana, David, acme

Em Mon, Aug 22, 2016 at 05:28:42PM -0700, H. Peter Anvin escreveu:
> On August 22, 2016 5:07:39 PM PDT, "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> >On Fri, Aug 19, 2016 at 03:31:47PM -0700, Kees Cook wrote:
> >> On Fri, Aug 19, 2016 at 2:41 PM,  <mcgrof@kernel.org> wrote:
> >> >  tools/Makefile                                     |   3 +-
> >> >  .../arch/x86/include/generated/asm/section-core.h  |   1 +
> >> >  tools/arch/x86/include/generated/ranges.h          |   1 +
> >> >  tools/arch/x86/include/generated/tables.h          |   1 +
> >> >  tools/include/asm-generic/ranges.h                 | 103 ++++
> >> >  tools/include/asm-generic/section-core.h           | 341

> >> >  tools/include/asm-generic/tables.h                 |  50 ++

> >> Aren't a bunch of these files exact duplicates of the headers in
> >include/linux?

> >Indeed... This a userspace tools/ architecture decision that was made
> >long ago, so its not up to me, I am just following the strategy
> >devised and picked up.  Refer to
> >7d7d1bf1d1dabe435ef50efb051724b8664749cb ("perf bench: Copy kernel
> >files needed to build mem{cpy,set} x86_64 benchmarks") for an example
> >of previous similar work. By sharing header files this enable more
> >tools/ to be hacked on.
 
> I think this is a legacy from before the uapi change that should
> really be fixed.  If we need to export additional kernel structures
> for the tools, we could define a third level of we really need it.

No, it is something recent, its just that from time to time files that
tools/ included from outside, i.e. from the kernel sources, made tools/
break, so after discussion with Linus and Ingo[1], it was decided we would
grab copies and never more access anything outside tools/ directly.

Instead we would check for changes and warn the tools/ developers about
it, so that they could check what has changed, that could mean changes
should/could be done to tools/ using those headers.

- Arnaldo

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 0/7] tools: add linker table userspace sandbox
  2016-08-22  9:59     ` Vegard Nossum
@ 2016-08-23 15:49       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-23 15:49 UTC (permalink / raw)
  To: Vegard Nossum; +Cc: Luis R. Rodriguez, linux-arch, kbuild, LKML

On Mon, Aug 22, 2016 at 11:59:46AM +0200, Vegard Nossum wrote:
> On 19 August 2016 at 23:41,  <mcgrof@kernel.org> wrote:
> > From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> >
> > The original v3 series for linker tables made reference only to
> > an external repository userspace sandbox application, however
> > Boris noted it'd be difficult ot keep this in sync with the
> > kernel so advised to consider integrate with the kernel. I've
> > taken steps in this direction.
> [...]
> > Please let me know if there are any issue or questions.
> 
> +#define __VMLINUX_SYMBOL(x) x
> 
> +#define VMLINUX_SYMBOL(x) __VMLINUX_SYMBOL(x)
> 
> +#define LINUX_SECTION_START(name)      VMLINUX_SYMBOL(name)
> 
> +#define DECLARE_LINUX_SECTION(type, name)                              \
> +        extern type VMLINUX_SYMBOL(name)[], \
> +                    VMLINUX_SYMBOL(name##__end)[]
> 
> +#define DECLARE_LINKTABLE(type, name)                                  \
> +       DECLARE_LINUX_SECTION(type, name)
> 
> +#define LINKTABLE_FOR_EACH(pointer, tbl)                               \
> +       for (pointer = LINUX_SECTION_START(tbl);                        \
> +            pointer < LINUX_SECTION_END(tbl);                          \
> +            pointer++)
> 
> I think this is subject to getting optimised out by newer gccs, since
> it sees the START(tbl) and END(tbl) symbols as two completely
> different arrays. See the short discussion here:
> 
> https://lkml.org/lkml/2016/6/26/73 (the first attempt is wrong, so
> don't look at that)
> 
> It is possible that < is different from != and always does the right
> thing, but I haven't checked.
> 
> I have a WIP branch that converts most of the existing tables in the
> kernel to use the external_array() macro which makes gcc throw away
> any knowledge it had about a pointer being part of an array.

Was there no compiler option to disable the optimization ?

Please do Cc me on your patches, either way we can coordinate changes depending
on which series gets merged. If your external_array() change lands upstream
first I'll see it on linux-next shortly can rebase and adjust code then as
that is what I base my patches on.

Do we know if there exceptions to the optimization issue for this and if so what
patterns follow ? We can test with simple userspace code if this will be an 
issue with gcc 7 by trying the demo in tools/linker-tables/ using this git tree
and branch 20160819-linker-table-v4 :

https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h=20160819-linker-table-v4

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 14/16] kprobes: move kprobe declarations to asm-generic/kprobes.h
  2016-08-22 15:11       ` Masami Hiramatsu
  (?)
@ 2016-08-23 16:31         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-23 16:31 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: mcgrof, hpa, tglx, mingo, jpoimboe, bp, linux,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3

On Tue, Aug 23, 2016 at 12:11:40AM +0900, Masami Hiramatsu wrote:
> On Fri, 19 Aug 2016 14:34:12 -0700
> mcgrof@kernel.org wrote:
> 
> > From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> > 
> > Often all is needed is these small helpers, instead of compiler.h
> > or a full kprobes.h. This is important for asm helpers, in fact even
> > some asm/kprobes.h make use of these helpers... instead just keep a
> > generic asm file with helpers useful for asm code with the least amount
> > of clutter as possible.
> > 
> > Likewise we need now to also address what to do about this file for both
> > when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
> > for when architectures have CONFIG_HAVE_KPROBES but have disabled
> > CONFIG_KPROBES.
> > 
> > Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
> > this means most architecture code cannot include asm/kprobes.h safely.
> > Correct this and add guards for architectures missing them. Additionally
> > provide architectures that not have kprobes support with the default
> > asm-generic solution. This lets us force asm/kprobes.h on the header
> > include/linux/kprobes.h always, but most importantly we can now safely
> > include just asm/kprobes.h on architecture code without bringing
> > the full kitchen sink of header files.
> > 
> > Two architectures already provided a guard against CONFIG_KPROBES on
> > its kprobes.h: sh, arch. The rest of the architectures needed gaurds
> > added. We avoid including any not-needed headers on asm/kprobes.h
> > unless kprobes have been enabled.
> > 
> > In a subsequent atomic change we can try now to remove compiler.h from
> > include/linux/kprobes.h.
> 
> Hmm, this looks a bit overkill... I rather like move it into linux/table.h.

That's the thing, we can't reasonably expect every table to add an entry into
table.h, this should be up to each user. Moving it to tables.h just prolongs
what needs to be done. In this case the change is justifiable given kprobe
annotations are required for some architectures early in architecture code, and
including compiler.h on early architecture code blows up. There is no easy fix
to this, and this this was *actually* the cleanest solution I could devise
without much changes.

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 14/16] kprobes: move kprobe declarations to asm-generic/kprobes.h
@ 2016-08-23 16:31         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-23 16:31 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: mcgrof, hpa, tglx, mingo, jpoimboe, bp, linux,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3

On Tue, Aug 23, 2016 at 12:11:40AM +0900, Masami Hiramatsu wrote:
> On Fri, 19 Aug 2016 14:34:12 -0700
> mcgrof@kernel.org wrote:
> 
> > From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> > 
> > Often all is needed is these small helpers, instead of compiler.h
> > or a full kprobes.h. This is important for asm helpers, in fact even
> > some asm/kprobes.h make use of these helpers... instead just keep a
> > generic asm file with helpers useful for asm code with the least amount
> > of clutter as possible.
> > 
> > Likewise we need now to also address what to do about this file for both
> > when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
> > for when architectures have CONFIG_HAVE_KPROBES but have disabled
> > CONFIG_KPROBES.
> > 
> > Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
> > this means most architecture code cannot include asm/kprobes.h safely.
> > Correct this and add guards for architectures missing them. Additionally
> > provide architectures that not have kprobes support with the default
> > asm-generic solution. This lets us force asm/kprobes.h on the header
> > include/linux/kprobes.h always, but most importantly we can now safely
> > include just asm/kprobes.h on architecture code without bringing
> > the full kitchen sink of header files.
> > 
> > Two architectures already provided a guard against CONFIG_KPROBES on
> > its kprobes.h: sh, arch. The rest of the architectures needed gaurds
> > added. We avoid including any not-needed headers on asm/kprobes.h
> > unless kprobes have been enabled.
> > 
> > In a subsequent atomic change we can try now to remove compiler.h from
> > include/linux/kprobes.h.
> 
> Hmm, this looks a bit overkill... I rather like move it into linux/table.h.

That's the thing, we can't reasonably expect every table to add an entry into
table.h, this should be up to each user. Moving it to tables.h just prolongs
what needs to be done. In this case the change is justifiable given kprobe
annotations are required for some architectures early in architecture code, and
including compiler.h on early architecture code blows up. There is no easy fix
to this, and this this was *actually* the cleanest solution I could devise
without much changes.

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 14/16] kprobes: move kprobe declarations to asm-generic/kprobes.h
@ 2016-08-23 16:31         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-23 16:31 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: mcgrof, hpa, tglx, mingo, jpoimboe, bp, linux,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, acme, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, paulus, mpe, James.Bottomley

On Tue, Aug 23, 2016 at 12:11:40AM +0900, Masami Hiramatsu wrote:
> On Fri, 19 Aug 2016 14:34:12 -0700
> mcgrof@kernel.org wrote:
> 
> > From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> > 
> > Often all is needed is these small helpers, instead of compiler.h
> > or a full kprobes.h. This is important for asm helpers, in fact even
> > some asm/kprobes.h make use of these helpers... instead just keep a
> > generic asm file with helpers useful for asm code with the least amount
> > of clutter as possible.
> > 
> > Likewise we need now to also address what to do about this file for both
> > when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
> > for when architectures have CONFIG_HAVE_KPROBES but have disabled
> > CONFIG_KPROBES.
> > 
> > Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
> > this means most architecture code cannot include asm/kprobes.h safely.
> > Correct this and add guards for architectures missing them. Additionally
> > provide architectures that not have kprobes support with the default
> > asm-generic solution. This lets us force asm/kprobes.h on the header
> > include/linux/kprobes.h always, but most importantly we can now safely
> > include just asm/kprobes.h on architecture code without bringing
> > the full kitchen sink of header files.
> > 
> > Two architectures already provided a guard against CONFIG_KPROBES on
> > its kprobes.h: sh, arch. The rest of the architectures needed gaurds
> > added. We avoid including any not-needed headers on asm/kprobes.h
> > unless kprobes have been enabled.
> > 
> > In a subsequent atomic change we can try now to remove compiler.h from
> > include/linux/kprobes.h.
> 
> Hmm, this looks a bit overkill... I rather like move it into linux/table.h.

That's the thing, we can't reasonably expect every table to add an entry into
table.h, this should be up to each user. Moving it to tables.h just prolongs
what needs to be done. In this case the change is justifiable given kprobe
annotations are required for some architectures early in architecture code, and
including compiler.h on early architecture code blows up. There is no easy fix
to this, and this this was *actually* the cleanest solution I could devise
without much changes.

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
  2016-08-23  1:26       ` Nicholas Piggin
  (?)
@ 2016-08-23 17:33         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-23 17:33 UTC (permalink / raw)
  To: Nicholas Piggin
  Cc: mcgrof, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross

On Tue, Aug 23, 2016 at 11:26:33AM +1000, Nicholas Piggin wrote:
> On Fri, 19 Aug 2016 14:34:02 -0700
> mcgrof@kernel.org wrote:
> > +/**
> > + * DOC: Standard ELF section use in Linux
> > + *
> > + * Linux makes use of the standard ELF sections, this sections documents
> > + * these.
> > + */
> > +
> > +/**
> > + * DOC: SECTION_RODATA
> > + *
> > + * Macro name for code which must be protected from write access, read only
> > + * data.
> > + */
> > +#define SECTION_RODATA			.rodata
> 
> These, for example. The exact name of the section is important in linker
> scripts and asm, so I can't see the benefit of hiding it. I could be
> missing the bigger picture.

There's two goals by using a macro for these core names. One is to allow us
to easily aggregate documentation in central place for each, the second is
to then provide more easily grep'able helpers so we can use them when devising
extensions or using them in extensions which further customize the sections
in the kernel.

> > +/**
> > + * DOC: SECTION_TEXT
> > + *
> > + * Macro name used to annotate code (functions) used during regular
> > + * kernel run time. This is combined with `SECTION_RODATA`, only this
> > + * section also allows for execution.
> > + *
> > + */
> > +#define SECTION_TEXT			.text
> 
> I can't see how these comments are right. .rodata doesn't seem like it
> should be combined with .text, and is not currently on powerpc. I think
> it's for data, not code.

On x86 and powerpc .rodata follows .text. On power currently the comment
above in .rodata is:

/* Text, read only data and other permanent read-only sections */

When this was introduced however read commit 14cf11af6cf60 ("powerpc: Merge
enough to start building in arch/powerpc.")

/* Read-only sections, merged into text segment: */

The format and style of putting rodata after text is kept from the older
commits.

This begs the question. What the hell is this thing talking about?

On Linux this is done via mark_rodata_ro() on init/main.c when CONFIG_DEBUG_RODATA
on architectures that support it. Architectures that implement this typically use
issues set_memory_ro() -- on x86 a start address used is PFN_ALIGN(_text) with
an end address of &__end_rodata_hpage_align.

When architectures do not have CONFIG_DEBUG_RODATA() you end up with:

static inline void mark_readonly(void)                                          
{                                                                               
        pr_warn("This architecture does not have kernel memory protection.\n"); 
}

So -- I should I clarify then in Linux we strive to have helpers adjust text and
rodata set to ro with memory protection implemented via mark_readonly(). Architectures
that do not support memory protection will lack a mark_readonly() implementation.

For now I figured a less controversial introduction to the documentation as
bland as it was above in my original patch would suffice, we can then expand on
it with something like the above. Thoughts?

> > +/*
> > + * These section _ALL() helpers are for use on linker scripts and helpers
> > + */
> > +#define SECTION_ALL(__section)						\
> > +	__section##.*
> 
> This is another example. We know what .text.* does in the linker scripts
> -- it's self documenting. But SECTION_ALL(.text)? I'm not sure that's an
> improvement. Actually I saw it in the linker script changes and had to
> come find the definition because I was a bit mislead:
> 
> SECTION_ALL(.text)
> 
> Initially I would expect this to be
> 
> .text*
> 
> Not
> 
> .text.*
> 
> The latter does not grab the .text section!

Its not intended to grab .text but rather its for helpers that provide customizations
based on a core section as base, in this case given your example it would be used by
section ranges and linker tables for .text. Both section ranges and linker tables
use postfix .something for their customizations. The SECTION_ALL() macro then is
a helper for customizations on a core section.

If the name is misleading would SECTION_CORE_ALL() be better with some documentation
explaining this and the above goal ?

> > +/*
> > + * As per gcc's documentation a common asm separator is a new line followed
> > + * by tab [0], it however seems possible to also just use a newline as its
> > + * the most commonly empirically observed semantic and folks seem to agree
> > + * this even works on S390. In case your architecture disagrees you may
> > + * override this and define your own and keep the rest of the macros.
> > + *
> > + * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
> > + */
> > +# ifndef ASM_CMD_SEP
> > +#  define ASM_CMD_SEP	"\n"
> > +# endif
> 
> This does not seem like it belongs here. The name is fairly ugly too.

Help me bikeshed, any name suggestions?

> I guess something might be needed like this when dealing with generic
> as directives common to all architectures, though.

Indeed, it actually seems we don't have much in this area, so this is small
baby step in that direction.

> I would say include/asm-generic/asm.h should be a better place.

I thought about this -- I'd be adding a new asm-generic/asm.h -- are folks OK
with that right now? Or should we do that as a secondary step ? I preferred to
do this as a secondary step as this series is long enough already and there is
quite a bit that can be dumped in a common asm-generic/asm.h, a few thoughts
on this already:

 o x86's asm/asm.h's use of __ASM_FORM() and include/linux/stringify.h share
   some traits which deserve possible consideration / rebranding.
 o Since C asm() just wrap things in strings defining a core set of
   helpers for a task seems justifiable, so for example we have
   __set_section_core_type(). Raw asm code then would use __set_section_core_type()
   directly and C asm() would just __stringify() it.

I figured a bit of bikeshedding would be possible here, so I decided to leave
this for a later set of patches. But indeed, I agree with you. If we want
this meshed out now.. let me know and lets bikeshed away...

> > diff --git a/include/linux/sections.h b/include/linux/sections.h
> > new file mode 100644
> > index 000000000000..f21c6ee88ded
> > --- /dev/null
> > +++ b/include/linux/sections.h
> > @@ -0,0 +1,111 @@
> > +#ifndef _LINUX_SECTIONS_H
> > +#define _LINUX_SECTIONS_H
> > +/*
> > + * Linux de-facto sections
> > + *
> > + * 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>
> > +#include <linux/export.h>
> > +
> > +#ifndef __ASSEMBLY__
> > +
> > +/**
> > + * DOC: Introduction
> > + *
> > + * Linux defines a set of common helpers which can be used to against its use
> > + * of standard or custom Linux sections, this section is dedicated to these
> > + * helpers.
> 
> I'm still not quite sure what a Linux de-facto/standard/common section is
> after this. Are they output sections?

We have ELF standard sections, and we have then sections which Linux has introduced
over the years which are now just known to be expected part of Linux, such as init
stuff which we free after boot. The combination of the ELF standard sections and
series of expected sections in Linux across all architectures is what this refers
to as Linux de-facto/standard/common sections. The header file is intended to
document these, step by step, and also provide helpers which allow further
customizations based on these sections.

> 
> I think it would be reasonable to drop the LINUX_ prefix and references to
> Linux.

I'm not so sure about this for section stuff -- are we certain we won't ever
clash with some built in compiler things? I'm fine to drop the prefix --
bikeshedding -- will drop it for the next series unless I hear otherwise...

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-23 17:33         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-23 17:33 UTC (permalink / raw)
  To: Nicholas Piggin
  Cc: mcgrof, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross

On Tue, Aug 23, 2016 at 11:26:33AM +1000, Nicholas Piggin wrote:
> On Fri, 19 Aug 2016 14:34:02 -0700
> mcgrof@kernel.org wrote:
> > +/**
> > + * DOC: Standard ELF section use in Linux
> > + *
> > + * Linux makes use of the standard ELF sections, this sections documents
> > + * these.
> > + */
> > +
> > +/**
> > + * DOC: SECTION_RODATA
> > + *
> > + * Macro name for code which must be protected from write access, read only
> > + * data.
> > + */
> > +#define SECTION_RODATA			.rodata
> 
> These, for example. The exact name of the section is important in linker
> scripts and asm, so I can't see the benefit of hiding it. I could be
> missing the bigger picture.

There's two goals by using a macro for these core names. One is to allow us
to easily aggregate documentation in central place for each, the second is
to then provide more easily grep'able helpers so we can use them when devising
extensions or using them in extensions which further customize the sections
in the kernel.

> > +/**
> > + * DOC: SECTION_TEXT
> > + *
> > + * Macro name used to annotate code (functions) used during regular
> > + * kernel run time. This is combined with `SECTION_RODATA`, only this
> > + * section also allows for execution.
> > + *
> > + */
> > +#define SECTION_TEXT			.text
> 
> I can't see how these comments are right. .rodata doesn't seem like it
> should be combined with .text, and is not currently on powerpc. I think
> it's for data, not code.

On x86 and powerpc .rodata follows .text. On power currently the comment
above in .rodata is:

/* Text, read only data and other permanent read-only sections */

When this was introduced however read commit 14cf11af6cf60 ("powerpc: Merge
enough to start building in arch/powerpc.")

/* Read-only sections, merged into text segment: */

The format and style of putting rodata after text is kept from the older
commits.

This begs the question. What the hell is this thing talking about?

On Linux this is done via mark_rodata_ro() on init/main.c when CONFIG_DEBUG_RODATA
on architectures that support it. Architectures that implement this typically use
issues set_memory_ro() -- on x86 a start address used is PFN_ALIGN(_text) with
an end address of &__end_rodata_hpage_align.

When architectures do not have CONFIG_DEBUG_RODATA() you end up with:

static inline void mark_readonly(void)                                          
{                                                                               
        pr_warn("This architecture does not have kernel memory protection.\n"); 
}

So -- I should I clarify then in Linux we strive to have helpers adjust text and
rodata set to ro with memory protection implemented via mark_readonly(). Architectures
that do not support memory protection will lack a mark_readonly() implementation.

For now I figured a less controversial introduction to the documentation as
bland as it was above in my original patch would suffice, we can then expand on
it with something like the above. Thoughts?

> > +/*
> > + * These section _ALL() helpers are for use on linker scripts and helpers
> > + */
> > +#define SECTION_ALL(__section)						\
> > +	__section##.*
> 
> This is another example. We know what .text.* does in the linker scripts
> -- it's self documenting. But SECTION_ALL(.text)? I'm not sure that's an
> improvement. Actually I saw it in the linker script changes and had to
> come find the definition because I was a bit mislead:
> 
> SECTION_ALL(.text)
> 
> Initially I would expect this to be
> 
> .text*
> 
> Not
> 
> .text.*
> 
> The latter does not grab the .text section!

Its not intended to grab .text but rather its for helpers that provide customizations
based on a core section as base, in this case given your example it would be used by
section ranges and linker tables for .text. Both section ranges and linker tables
use postfix .something for their customizations. The SECTION_ALL() macro then is
a helper for customizations on a core section.

If the name is misleading would SECTION_CORE_ALL() be better with some documentation
explaining this and the above goal ?

> > +/*
> > + * As per gcc's documentation a common asm separator is a new line followed
> > + * by tab [0], it however seems possible to also just use a newline as its
> > + * the most commonly empirically observed semantic and folks seem to agree
> > + * this even works on S390. In case your architecture disagrees you may
> > + * override this and define your own and keep the rest of the macros.
> > + *
> > + * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
> > + */
> > +# ifndef ASM_CMD_SEP
> > +#  define ASM_CMD_SEP	"\n"
> > +# endif
> 
> This does not seem like it belongs here. The name is fairly ugly too.

Help me bikeshed, any name suggestions?

> I guess something might be needed like this when dealing with generic
> as directives common to all architectures, though.

Indeed, it actually seems we don't have much in this area, so this is small
baby step in that direction.

> I would say include/asm-generic/asm.h should be a better place.

I thought about this -- I'd be adding a new asm-generic/asm.h -- are folks OK
with that right now? Or should we do that as a secondary step ? I preferred to
do this as a secondary step as this series is long enough already and there is
quite a bit that can be dumped in a common asm-generic/asm.h, a few thoughts
on this already:

 o x86's asm/asm.h's use of __ASM_FORM() and include/linux/stringify.h share
   some traits which deserve possible consideration / rebranding.
 o Since C asm() just wrap things in strings defining a core set of
   helpers for a task seems justifiable, so for example we have
   __set_section_core_type(). Raw asm code then would use __set_section_core_type()
   directly and C asm() would just __stringify() it.

I figured a bit of bikeshedding would be possible here, so I decided to leave
this for a later set of patches. But indeed, I agree with you. If we want
this meshed out now.. let me know and lets bikeshed away...

> > diff --git a/include/linux/sections.h b/include/linux/sections.h
> > new file mode 100644
> > index 000000000000..f21c6ee88ded
> > --- /dev/null
> > +++ b/include/linux/sections.h
> > @@ -0,0 +1,111 @@
> > +#ifndef _LINUX_SECTIONS_H
> > +#define _LINUX_SECTIONS_H
> > +/*
> > + * Linux de-facto sections
> > + *
> > + * 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>
> > +#include <linux/export.h>
> > +
> > +#ifndef __ASSEMBLY__
> > +
> > +/**
> > + * DOC: Introduction
> > + *
> > + * Linux defines a set of common helpers which can be used to against its use
> > + * of standard or custom Linux sections, this section is dedicated to these
> > + * helpers.
> 
> I'm still not quite sure what a Linux de-facto/standard/common section is
> after this. Are they output sections?

We have ELF standard sections, and we have then sections which Linux has introduced
over the years which are now just known to be expected part of Linux, such as init
stuff which we free after boot. The combination of the ELF standard sections and
series of expected sections in Linux across all architectures is what this refers
to as Linux de-facto/standard/common sections. The header file is intended to
document these, step by step, and also provide helpers which allow further
customizations based on these sections.

> 
> I think it would be reasonable to drop the LINUX_ prefix and references to
> Linux.

I'm not so sure about this for section stuff -- are we certain we won't ever
clash with some built in compiler things? I'm fine to drop the prefix --
bikeshedding -- will drop it for the next series unless I hear otherwise...

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-23 17:33         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-23 17:33 UTC (permalink / raw)
  To: Nicholas Piggin
  Cc: mcgrof, hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, acme, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, paulus, mpe, James.Bottomley

On Tue, Aug 23, 2016 at 11:26:33AM +1000, Nicholas Piggin wrote:
> On Fri, 19 Aug 2016 14:34:02 -0700
> mcgrof@kernel.org wrote:
> > +/**
> > + * DOC: Standard ELF section use in Linux
> > + *
> > + * Linux makes use of the standard ELF sections, this sections documents
> > + * these.
> > + */
> > +
> > +/**
> > + * DOC: SECTION_RODATA
> > + *
> > + * Macro name for code which must be protected from write access, read only
> > + * data.
> > + */
> > +#define SECTION_RODATA			.rodata
> 
> These, for example. The exact name of the section is important in linker
> scripts and asm, so I can't see the benefit of hiding it. I could be
> missing the bigger picture.

There's two goals by using a macro for these core names. One is to allow us
to easily aggregate documentation in central place for each, the second is
to then provide more easily grep'able helpers so we can use them when devising
extensions or using them in extensions which further customize the sections
in the kernel.

> > +/**
> > + * DOC: SECTION_TEXT
> > + *
> > + * Macro name used to annotate code (functions) used during regular
> > + * kernel run time. This is combined with `SECTION_RODATA`, only this
> > + * section also allows for execution.
> > + *
> > + */
> > +#define SECTION_TEXT			.text
> 
> I can't see how these comments are right. .rodata doesn't seem like it
> should be combined with .text, and is not currently on powerpc. I think
> it's for data, not code.

On x86 and powerpc .rodata follows .text. On power currently the comment
above in .rodata is:

/* Text, read only data and other permanent read-only sections */

When this was introduced however read commit 14cf11af6cf60 ("powerpc: Merge
enough to start building in arch/powerpc.")

/* Read-only sections, merged into text segment: */

The format and style of putting rodata after text is kept from the older
commits.

This begs the question. What the hell is this thing talking about?

On Linux this is done via mark_rodata_ro() on init/main.c when CONFIG_DEBUG_RODATA
on architectures that support it. Architectures that implement this typically use
issues set_memory_ro() -- on x86 a start address used is PFN_ALIGN(_text) with
an end address of &__end_rodata_hpage_align.

When architectures do not have CONFIG_DEBUG_RODATA() you end up with:

static inline void mark_readonly(void)                                          
{                                                                               
        pr_warn("This architecture does not have kernel memory protection.\n"); 
}

So -- I should I clarify then in Linux we strive to have helpers adjust text and
rodata set to ro with memory protection implemented via mark_readonly(). Architectures
that do not support memory protection will lack a mark_readonly() implementation.

For now I figured a less controversial introduction to the documentation as
bland as it was above in my original patch would suffice, we can then expand on
it with something like the above. Thoughts?

> > +/*
> > + * These section _ALL() helpers are for use on linker scripts and helpers
> > + */
> > +#define SECTION_ALL(__section)						\
> > +	__section##.*
> 
> This is another example. We know what .text.* does in the linker scripts
> -- it's self documenting. But SECTION_ALL(.text)? I'm not sure that's an
> improvement. Actually I saw it in the linker script changes and had to
> come find the definition because I was a bit mislead:
> 
> SECTION_ALL(.text)
> 
> Initially I would expect this to be
> 
> .text*
> 
> Not
> 
> .text.*
> 
> The latter does not grab the .text section!

Its not intended to grab .text but rather its for helpers that provide customizations
based on a core section as base, in this case given your example it would be used by
section ranges and linker tables for .text. Both section ranges and linker tables
use postfix .something for their customizations. The SECTION_ALL() macro then is
a helper for customizations on a core section.

If the name is misleading would SECTION_CORE_ALL() be better with some documentation
explaining this and the above goal ?

> > +/*
> > + * As per gcc's documentation a common asm separator is a new line followed
> > + * by tab [0], it however seems possible to also just use a newline as its
> > + * the most commonly empirically observed semantic and folks seem to agree
> > + * this even works on S390. In case your architecture disagrees you may
> > + * override this and define your own and keep the rest of the macros.
> > + *
> > + * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
> > + */
> > +# ifndef ASM_CMD_SEP
> > +#  define ASM_CMD_SEP	"\n"
> > +# endif
> 
> This does not seem like it belongs here. The name is fairly ugly too.

Help me bikeshed, any name suggestions?

> I guess something might be needed like this when dealing with generic
> as directives common to all architectures, though.

Indeed, it actually seems we don't have much in this area, so this is small
baby step in that direction.

> I would say include/asm-generic/asm.h should be a better place.

I thought about this -- I'd be adding a new asm-generic/asm.h -- are folks OK
with that right now? Or should we do that as a secondary step ? I preferred to
do this as a secondary step as this series is long enough already and there is
quite a bit that can be dumped in a common asm-generic/asm.h, a few thoughts
on this already:

 o x86's asm/asm.h's use of __ASM_FORM() and include/linux/stringify.h share
   some traits which deserve possible consideration / rebranding.
 o Since C asm() just wrap things in strings defining a core set of
   helpers for a task seems justifiable, so for example we have
   __set_section_core_type(). Raw asm code then would use __set_section_core_type()
   directly and C asm() would just __stringify() it.

I figured a bit of bikeshedding would be possible here, so I decided to leave
this for a later set of patches. But indeed, I agree with you. If we want
this meshed out now.. let me know and lets bikeshed away...

> > diff --git a/include/linux/sections.h b/include/linux/sections.h
> > new file mode 100644
> > index 000000000000..f21c6ee88ded
> > --- /dev/null
> > +++ b/include/linux/sections.h
> > @@ -0,0 +1,111 @@
> > +#ifndef _LINUX_SECTIONS_H
> > +#define _LINUX_SECTIONS_H
> > +/*
> > + * Linux de-facto sections
> > + *
> > + * 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>
> > +#include <linux/export.h>
> > +
> > +#ifndef __ASSEMBLY__
> > +
> > +/**
> > + * DOC: Introduction
> > + *
> > + * Linux defines a set of common helpers which can be used to against its use
> > + * of standard or custom Linux sections, this section is dedicated to these
> > + * helpers.
> 
> I'm still not quite sure what a Linux de-facto/standard/common section is
> after this. Are they output sections?

We have ELF standard sections, and we have then sections which Linux has introduced
over the years which are now just known to be expected part of Linux, such as init
stuff which we free after boot. The combination of the ELF standard sections and
series of expected sections in Linux across all architectures is what this refers
to as Linux de-facto/standard/common sections. The header file is intended to
document these, step by step, and also provide helpers which allow further
customizations based on these sections.

> 
> I think it would be reasonable to drop the LINUX_ prefix and references to
> Linux.

I'm not so sure about this for section stuff -- are we certain we won't ever
clash with some built in compiler things? I'm fine to drop the prefix --
bikeshedding -- will drop it for the next series unless I hear otherwise...

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 7/7] tools: add userspace linker table sandbox
@ 2016-08-24  2:28                 ` Kees Cook
  0 siblings, 0 replies; 480+ messages in thread
From: Kees Cook @ 2016-08-24  2:28 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: H. Peter Anvin, Luis R. Rodriguez, Josh Poimboeuf,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Russell King - ARM Linux, mhiramat, Masami Hiramatsu, jbaron,
	Heiko Carstens, ananth, anil.s.keshavamurthy, David S. Miller,
	Miao Steven, x86, Andy Lutomirski, Linus Torvalds, Greg KH,
	Rusty Russell, gnomes

On Tue, Aug 23, 2016 at 10:30 AM, Arnaldo Carvalho de Melo
<acme@redhat.com> wrote:
> Em Mon, Aug 22, 2016 at 05:28:42PM -0700, H. Peter Anvin escreveu:
>> On August 22, 2016 5:07:39 PM PDT, "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
>> >On Fri, Aug 19, 2016 at 03:31:47PM -0700, Kees Cook wrote:
>> >> On Fri, Aug 19, 2016 at 2:41 PM,  <mcgrof@kernel.org> wrote:
>> >> >  tools/Makefile                                     |   3 +-
>> >> >  .../arch/x86/include/generated/asm/section-core.h  |   1 +
>> >> >  tools/arch/x86/include/generated/ranges.h          |   1 +
>> >> >  tools/arch/x86/include/generated/tables.h          |   1 +
>> >> >  tools/include/asm-generic/ranges.h                 | 103 ++++
>> >> >  tools/include/asm-generic/section-core.h           | 341
>
>> >> >  tools/include/asm-generic/tables.h                 |  50 ++
>
>> >> Aren't a bunch of these files exact duplicates of the headers in
>> >include/linux?
>
>> >Indeed... This a userspace tools/ architecture decision that was made
>> >long ago, so its not up to me, I am just following the strategy
>> >devised and picked up.  Refer to
>> >7d7d1bf1d1dabe435ef50efb051724b8664749cb ("perf bench: Copy kernel
>> >files needed to build mem{cpy,set} x86_64 benchmarks") for an example
>> >of previous similar work. By sharing header files this enable more
>> >tools/ to be hacked on.
>
>> I think this is a legacy from before the uapi change that should
>> really be fixed.  If we need to export additional kernel structures
>> for the tools, we could define a third level of we really need it.
>
> No, it is something recent, its just that from time to time files that
> tools/ included from outside, i.e. from the kernel sources, made tools/
> break, so after discussion with Linus and Ingo[1], it was decided we would

This [1] reference seems missing. I'm curious to see the thread. I
wonder if something could be done to just generate the needed headers
from the canonical locations into the tools/ locations?

> grab copies and never more access anything outside tools/ directly.
>
> Instead we would check for changes and warn the tools/ developers about
> it, so that they could check what has changed, that could mean changes
> should/could be done to tools/ using those headers.

Is there anything automated in place to notice when these changes happen?

-Kees

-- 
Kees Cook
Nexus Security

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 7/7] tools: add userspace linker table sandbox
@ 2016-08-24  2:28                 ` Kees Cook
  0 siblings, 0 replies; 480+ messages in thread
From: Kees Cook @ 2016-08-24  2:28 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: H. Peter Anvin, Luis R. Rodriguez, Josh Poimboeuf,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Russell King - ARM Linux, mhiramat, Masami Hiramatsu, jbaron,
	Heiko Carstens, ananth, anil.s.keshavamurthy, David S. Miller,
	Miao Steven, x86, Andy Lutomirski, Linus Torvalds, Greg KH,
	Rusty Russell, gnomes, Alan Cox, David Woodhouse, Arnd Bergmann,
	Ming Lei, linux-arch, benh, ananth, Paul Bolle, fontana, David,
	Arnaldo Carvalho de Melo

On Tue, Aug 23, 2016 at 10:30 AM, Arnaldo Carvalho de Melo
<acme@redhat.com> wrote:
> Em Mon, Aug 22, 2016 at 05:28:42PM -0700, H. Peter Anvin escreveu:
>> On August 22, 2016 5:07:39 PM PDT, "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
>> >On Fri, Aug 19, 2016 at 03:31:47PM -0700, Kees Cook wrote:
>> >> On Fri, Aug 19, 2016 at 2:41 PM,  <mcgrof@kernel.org> wrote:
>> >> >  tools/Makefile                                     |   3 +-
>> >> >  .../arch/x86/include/generated/asm/section-core.h  |   1 +
>> >> >  tools/arch/x86/include/generated/ranges.h          |   1 +
>> >> >  tools/arch/x86/include/generated/tables.h          |   1 +
>> >> >  tools/include/asm-generic/ranges.h                 | 103 ++++
>> >> >  tools/include/asm-generic/section-core.h           | 341
>
>> >> >  tools/include/asm-generic/tables.h                 |  50 ++
>
>> >> Aren't a bunch of these files exact duplicates of the headers in
>> >include/linux?
>
>> >Indeed... This a userspace tools/ architecture decision that was made
>> >long ago, so its not up to me, I am just following the strategy
>> >devised and picked up.  Refer to
>> >7d7d1bf1d1dabe435ef50efb051724b8664749cb ("perf bench: Copy kernel
>> >files needed to build mem{cpy,set} x86_64 benchmarks") for an example
>> >of previous similar work. By sharing header files this enable more
>> >tools/ to be hacked on.
>
>> I think this is a legacy from before the uapi change that should
>> really be fixed.  If we need to export additional kernel structures
>> for the tools, we could define a third level of we really need it.
>
> No, it is something recent, its just that from time to time files that
> tools/ included from outside, i.e. from the kernel sources, made tools/
> break, so after discussion with Linus and Ingo[1], it was decided we would

This [1] reference seems missing. I'm curious to see the thread. I
wonder if something could be done to just generate the needed headers
from the canonical locations into the tools/ locations?

> grab copies and never more access anything outside tools/ directly.
>
> Instead we would check for changes and warn the tools/ developers about
> it, so that they could check what has changed, that could mean changes
> should/could be done to tools/ using those headers.

Is there anything automated in place to notice when these changes happen?

-Kees

-- 
Kees Cook
Nexus Security

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
  2016-08-23 17:33         ` Luis R. Rodriguez
  (?)
@ 2016-08-24  3:51           ` Nicholas Piggin
  -1 siblings, 0 replies; 480+ messages in thread
From: Nicholas Piggin @ 2016-08-24  3:51 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3

On Tue, 23 Aug 2016 19:33:06 +0200
"Luis R. Rodriguez" <mcgrof@kernel.org> wrote:

> On Tue, Aug 23, 2016 at 11:26:33AM +1000, Nicholas Piggin wrote:
> > On Fri, 19 Aug 2016 14:34:02 -0700
> > mcgrof@kernel.org wrote:  
> > > +/**
> > > + * DOC: Standard ELF section use in Linux
> > > + *
> > > + * Linux makes use of the standard ELF sections, this sections documents
> > > + * these.
> > > + */
> > > +
> > > +/**
> > > + * DOC: SECTION_RODATA
> > > + *
> > > + * Macro name for code which must be protected from write access, read only
> > > + * data.
> > > + */
> > > +#define SECTION_RODATA			.rodata  
> > 
> > These, for example. The exact name of the section is important in linker
> > scripts and asm, so I can't see the benefit of hiding it. I could be
> > missing the bigger picture.  
> 
> There's two goals by using a macro for these core names. One is to allow us
> to easily aggregate documentation in central place for each, the second is
> to then provide more easily grep'able helpers so we can use them when devising
> extensions or using them in extensions which further customize the sections
> in the kernel.

Documentation is good, but not necessary to have the extra name indirection.
Sections tend (not always, but it would be nice if they did) to follow the
.name convention, which makes them reasonably easy to grep for. They are also
the names you'll be grepping for when you look at disassembly.


> > > +/**
> > > + * DOC: SECTION_TEXT
> > > + *
> > > + * Macro name used to annotate code (functions) used during regular
> > > + * kernel run time. This is combined with `SECTION_RODATA`, only this
> > > + * section also allows for execution.
> > > + *
> > > + */
> > > +#define SECTION_TEXT			.text  
> > 
> > I can't see how these comments are right. .rodata doesn't seem like it
> > should be combined with .text, and is not currently on powerpc. I think
> > it's for data, not code.  
> 
> On x86 and powerpc .rodata follows .text.

But follows is not the same as combined. And together with the comment that
RODATA is for code (which is wrong, it's data), it make it seem like it
is actually combined.


> On power currently the comment
> above in .rodata is:
> 
> /* Text, read only data and other permanent read-only sections */
> 
> When this was introduced however read commit 14cf11af6cf60 ("powerpc: Merge
> enough to start building in arch/powerpc.")
> 
> /* Read-only sections, merged into text segment: */
> 
> The format and style of putting rodata after text is kept from the older
> commits.
> 
> This begs the question. What the hell is this thing talking about?
> 
> On Linux this is done via mark_rodata_ro() on init/main.c when CONFIG_DEBUG_RODATA
> on architectures that support it. Architectures that implement this typically use
> issues set_memory_ro() -- on x86 a start address used is PFN_ALIGN(_text) with
> an end address of &__end_rodata_hpage_align.
> 
> When architectures do not have CONFIG_DEBUG_RODATA() you end up with:
> 
> static inline void mark_readonly(void)                                          
> {                                                                               
>         pr_warn("This architecture does not have kernel memory protection.\n"); 
> }
> 
> So -- I should I clarify then in Linux we strive to have helpers adjust text and
> rodata set to ro with memory protection implemented via mark_readonly(). Architectures
> that do not support memory protection will lack a mark_readonly() implementation.

Right, I wasn't talking about arch implementation of how the ro
protection is done, so much as just the comments being a bit misleading.


> For now I figured a less controversial introduction to the documentation as
> bland as it was above in my original patch would suffice, we can then expand on
> it with something like the above. Thoughts?

I think comments are one of the key features of this patch series (or at
least this patch, I've not looked through the others so much yet). I'm no
expert on linker stuff, but I think a lot of arch maintainers aren't
necessarily either so you tend to get a lot of copy and paste without
always people knowing what exactly is happening. It would be really good
to have some longer explanations and justifications/examples IMO. So I
don't think that would be controversial if you wanted to expand on it.


> > > +/*
> > > + * These section _ALL() helpers are for use on linker scripts and helpers
> > > + */
> > > +#define SECTION_ALL(__section)						\
> > > +	__section##.*  
> > 
> > This is another example. We know what .text.* does in the linker scripts
> > -- it's self documenting. But SECTION_ALL(.text)? I'm not sure that's an
> > improvement. Actually I saw it in the linker script changes and had to
> > come find the definition because I was a bit mislead:
> > 
> > SECTION_ALL(.text)
> > 
> > Initially I would expect this to be
> > 
> > .text*
> > 
> > Not
> > 
> > .text.*
> > 
> > The latter does not grab the .text section!  
> 
> Its not intended to grab .text but rather its for helpers that provide customizations
> based on a core section as base, in this case given your example it would be used by
> section ranges and linker tables for .text. Both section ranges and linker tables
> use postfix .something for their customizations. The SECTION_ALL() macro then is
> a helper for customizations on a core section.

Right, it's just that .text.* is *immediately* obvious. SECTION_ALL() is not.


> If the name is misleading would SECTION_CORE_ALL() be better with some documentation
> explaining this and the above goal ?

I don't know... not to be glib, but .section.* would be better and not require
documentation.

CORE does not really add anything as far as I can see. Other types of .text including
ones which are automatically generated by the compiler, for better or worse, are
.text.x sections too.

I would like to see more standardisation of naming convention -- some sections start
with .., some start with no dots, some use . to separate logical "subsections", others
use underscores or something else. I just don't see it would be a problem to simply
use the raw names and linker wildcards for it.


> > > +/*
> > > + * As per gcc's documentation a common asm separator is a new line followed
> > > + * by tab [0], it however seems possible to also just use a newline as its
> > > + * the most commonly empirically observed semantic and folks seem to agree
> > > + * this even works on S390. In case your architecture disagrees you may
> > > + * override this and define your own and keep the rest of the macros.
> > > + *
> > > + * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
> > > + */
> > > +# ifndef ASM_CMD_SEP
> > > +#  define ASM_CMD_SEP	"\n"
> > > +# endif  
> > 
> > This does not seem like it belongs here. The name is fairly ugly too.  
> 
> Help me bikeshed, any name suggestions?

BTW, I'm not trying to bikeshed :) This doesn't affect the value of your
patch at all, it was just an offhand thing I saw.

> 
> > I guess something might be needed like this when dealing with generic
> > as directives common to all architectures, though.  
> 
> Indeed, it actually seems we don't have much in this area, so this is small
> baby step in that direction.
> 
> > I would say include/asm-generic/asm.h should be a better place.  
> 
> I thought about this -- I'd be adding a new asm-generic/asm.h -- are folks OK
> with that right now? Or should we do that as a secondary step ? I preferred to
> do this as a secondary step as this series is long enough already and there is
> quite a bit that can be dumped in a common asm-generic/asm.h, a few thoughts
> on this already:
> 
>  o x86's asm/asm.h's use of __ASM_FORM() and include/linux/stringify.h share
>    some traits which deserve possible consideration / rebranding.
>  o Since C asm() just wrap things in strings defining a core set of
>    helpers for a task seems justifiable, so for example we have
>    __set_section_core_type(). Raw asm code then would use __set_section_core_type()
>    directly and C asm() would just __stringify() it.
> 
> I figured a bit of bikeshedding would be possible here, so I decided to leave
> this for a later set of patches. But indeed, I agree with you. If we want
> this meshed out now.. let me know and lets bikeshed away...

It's fine, I don't mind too much. I think asm-generic/asm.h should be
fine for generic asm'isms though. Or assembler.h to match compiler.h.


> > > diff --git a/include/linux/sections.h b/include/linux/sections.h
> > > new file mode 100644
> > > index 000000000000..f21c6ee88ded
> > > --- /dev/null
> > > +++ b/include/linux/sections.h
> > > @@ -0,0 +1,111 @@
> > > +#ifndef _LINUX_SECTIONS_H
> > > +#define _LINUX_SECTIONS_H
> > > +/*
> > > + * Linux de-facto sections
> > > + *
> > > + * 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>
> > > +#include <linux/export.h>
> > > +
> > > +#ifndef __ASSEMBLY__
> > > +
> > > +/**
> > > + * DOC: Introduction
> > > + *
> > > + * Linux defines a set of common helpers which can be used to against its use
> > > + * of standard or custom Linux sections, this section is dedicated to these
> > > + * helpers.  
> > 
> > I'm still not quite sure what a Linux de-facto/standard/common section is
> > after this. Are they output sections?  
> 
> We have ELF standard sections, and we have then sections which Linux has introduced
> over the years which are now just known to be expected part of Linux, such as init
> stuff which we free after boot. The combination of the ELF standard sections and
> series of expected sections in Linux across all architectures is what this refers
> to as Linux de-facto/standard/common sections. The header file is intended to
> document these, step by step, and also provide helpers which allow further
> customizations based on these sections.

Well but your macros are not linker sections. They are "Linux sections", which
appear to give you a start and end symbol name, but does not direct the linker
to create a specific output section. I just can't work out what exactly is a
"custom Linux section", and what DECLARE_LINUX_SECTION(), for example, actaully
gives you.


Thanks,
Nick

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-24  3:51           ` Nicholas Piggin
  0 siblings, 0 replies; 480+ messages in thread
From: Nicholas Piggin @ 2016-08-24  3:51 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3

On Tue, 23 Aug 2016 19:33:06 +0200
"Luis R. Rodriguez" <mcgrof@kernel.org> wrote:

> On Tue, Aug 23, 2016 at 11:26:33AM +1000, Nicholas Piggin wrote:
> > On Fri, 19 Aug 2016 14:34:02 -0700
> > mcgrof@kernel.org wrote:  
> > > +/**
> > > + * DOC: Standard ELF section use in Linux
> > > + *
> > > + * Linux makes use of the standard ELF sections, this sections documents
> > > + * these.
> > > + */
> > > +
> > > +/**
> > > + * DOC: SECTION_RODATA
> > > + *
> > > + * Macro name for code which must be protected from write access, read only
> > > + * data.
> > > + */
> > > +#define SECTION_RODATA			.rodata  
> > 
> > These, for example. The exact name of the section is important in linker
> > scripts and asm, so I can't see the benefit of hiding it. I could be
> > missing the bigger picture.  
> 
> There's two goals by using a macro for these core names. One is to allow us
> to easily aggregate documentation in central place for each, the second is
> to then provide more easily grep'able helpers so we can use them when devising
> extensions or using them in extensions which further customize the sections
> in the kernel.

Documentation is good, but not necessary to have the extra name indirection.
Sections tend (not always, but it would be nice if they did) to follow the
.name convention, which makes them reasonably easy to grep for. They are also
the names you'll be grepping for when you look at disassembly.


> > > +/**
> > > + * DOC: SECTION_TEXT
> > > + *
> > > + * Macro name used to annotate code (functions) used during regular
> > > + * kernel run time. This is combined with `SECTION_RODATA`, only this
> > > + * section also allows for execution.
> > > + *
> > > + */
> > > +#define SECTION_TEXT			.text  
> > 
> > I can't see how these comments are right. .rodata doesn't seem like it
> > should be combined with .text, and is not currently on powerpc. I think
> > it's for data, not code.  
> 
> On x86 and powerpc .rodata follows .text.

But follows is not the same as combined. And together with the comment that
RODATA is for code (which is wrong, it's data), it make it seem like it
is actually combined.


> On power currently the comment
> above in .rodata is:
> 
> /* Text, read only data and other permanent read-only sections */
> 
> When this was introduced however read commit 14cf11af6cf60 ("powerpc: Merge
> enough to start building in arch/powerpc.")
> 
> /* Read-only sections, merged into text segment: */
> 
> The format and style of putting rodata after text is kept from the older
> commits.
> 
> This begs the question. What the hell is this thing talking about?
> 
> On Linux this is done via mark_rodata_ro() on init/main.c when CONFIG_DEBUG_RODATA
> on architectures that support it. Architectures that implement this typically use
> issues set_memory_ro() -- on x86 a start address used is PFN_ALIGN(_text) with
> an end address of &__end_rodata_hpage_align.
> 
> When architectures do not have CONFIG_DEBUG_RODATA() you end up with:
> 
> static inline void mark_readonly(void)                                          
> {                                                                               
>         pr_warn("This architecture does not have kernel memory protection.\n"); 
> }
> 
> So -- I should I clarify then in Linux we strive to have helpers adjust text and
> rodata set to ro with memory protection implemented via mark_readonly(). Architectures
> that do not support memory protection will lack a mark_readonly() implementation.

Right, I wasn't talking about arch implementation of how the ro
protection is done, so much as just the comments being a bit misleading.


> For now I figured a less controversial introduction to the documentation as
> bland as it was above in my original patch would suffice, we can then expand on
> it with something like the above. Thoughts?

I think comments are one of the key features of this patch series (or at
least this patch, I've not looked through the others so much yet). I'm no
expert on linker stuff, but I think a lot of arch maintainers aren't
necessarily either so you tend to get a lot of copy and paste without
always people knowing what exactly is happening. It would be really good
to have some longer explanations and justifications/examples IMO. So I
don't think that would be controversial if you wanted to expand on it.


> > > +/*
> > > + * These section _ALL() helpers are for use on linker scripts and helpers
> > > + */
> > > +#define SECTION_ALL(__section)						\
> > > +	__section##.*  
> > 
> > This is another example. We know what .text.* does in the linker scripts
> > -- it's self documenting. But SECTION_ALL(.text)? I'm not sure that's an
> > improvement. Actually I saw it in the linker script changes and had to
> > come find the definition because I was a bit mislead:
> > 
> > SECTION_ALL(.text)
> > 
> > Initially I would expect this to be
> > 
> > .text*
> > 
> > Not
> > 
> > .text.*
> > 
> > The latter does not grab the .text section!  
> 
> Its not intended to grab .text but rather its for helpers that provide customizations
> based on a core section as base, in this case given your example it would be used by
> section ranges and linker tables for .text. Both section ranges and linker tables
> use postfix .something for their customizations. The SECTION_ALL() macro then is
> a helper for customizations on a core section.

Right, it's just that .text.* is *immediately* obvious. SECTION_ALL() is not.


> If the name is misleading would SECTION_CORE_ALL() be better with some documentation
> explaining this and the above goal ?

I don't know... not to be glib, but .section.* would be better and not require
documentation.

CORE does not really add anything as far as I can see. Other types of .text including
ones which are automatically generated by the compiler, for better or worse, are
.text.x sections too.

I would like to see more standardisation of naming convention -- some sections start
with .., some start with no dots, some use . to separate logical "subsections", others
use underscores or something else. I just don't see it would be a problem to simply
use the raw names and linker wildcards for it.


> > > +/*
> > > + * As per gcc's documentation a common asm separator is a new line followed
> > > + * by tab [0], it however seems possible to also just use a newline as its
> > > + * the most commonly empirically observed semantic and folks seem to agree
> > > + * this even works on S390. In case your architecture disagrees you may
> > > + * override this and define your own and keep the rest of the macros.
> > > + *
> > > + * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
> > > + */
> > > +# ifndef ASM_CMD_SEP
> > > +#  define ASM_CMD_SEP	"\n"
> > > +# endif  
> > 
> > This does not seem like it belongs here. The name is fairly ugly too.  
> 
> Help me bikeshed, any name suggestions?

BTW, I'm not trying to bikeshed :) This doesn't affect the value of your
patch at all, it was just an offhand thing I saw.

> 
> > I guess something might be needed like this when dealing with generic
> > as directives common to all architectures, though.  
> 
> Indeed, it actually seems we don't have much in this area, so this is small
> baby step in that direction.
> 
> > I would say include/asm-generic/asm.h should be a better place.  
> 
> I thought about this -- I'd be adding a new asm-generic/asm.h -- are folks OK
> with that right now? Or should we do that as a secondary step ? I preferred to
> do this as a secondary step as this series is long enough already and there is
> quite a bit that can be dumped in a common asm-generic/asm.h, a few thoughts
> on this already:
> 
>  o x86's asm/asm.h's use of __ASM_FORM() and include/linux/stringify.h share
>    some traits which deserve possible consideration / rebranding.
>  o Since C asm() just wrap things in strings defining a core set of
>    helpers for a task seems justifiable, so for example we have
>    __set_section_core_type(). Raw asm code then would use __set_section_core_type()
>    directly and C asm() would just __stringify() it.
> 
> I figured a bit of bikeshedding would be possible here, so I decided to leave
> this for a later set of patches. But indeed, I agree with you. If we want
> this meshed out now.. let me know and lets bikeshed away...

It's fine, I don't mind too much. I think asm-generic/asm.h should be
fine for generic asm'isms though. Or assembler.h to match compiler.h.


> > > diff --git a/include/linux/sections.h b/include/linux/sections.h
> > > new file mode 100644
> > > index 000000000000..f21c6ee88ded
> > > --- /dev/null
> > > +++ b/include/linux/sections.h
> > > @@ -0,0 +1,111 @@
> > > +#ifndef _LINUX_SECTIONS_H
> > > +#define _LINUX_SECTIONS_H
> > > +/*
> > > + * Linux de-facto sections
> > > + *
> > > + * 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>
> > > +#include <linux/export.h>
> > > +
> > > +#ifndef __ASSEMBLY__
> > > +
> > > +/**
> > > + * DOC: Introduction
> > > + *
> > > + * Linux defines a set of common helpers which can be used to against its use
> > > + * of standard or custom Linux sections, this section is dedicated to these
> > > + * helpers.  
> > 
> > I'm still not quite sure what a Linux de-facto/standard/common section is
> > after this. Are they output sections?  
> 
> We have ELF standard sections, and we have then sections which Linux has introduced
> over the years which are now just known to be expected part of Linux, such as init
> stuff which we free after boot. The combination of the ELF standard sections and
> series of expected sections in Linux across all architectures is what this refers
> to as Linux de-facto/standard/common sections. The header file is intended to
> document these, step by step, and also provide helpers which allow further
> customizations based on these sections.

Well but your macros are not linker sections. They are "Linux sections", which
appear to give you a start and end symbol name, but does not direct the linker
to create a specific output section. I just can't work out what exactly is a
"custom Linux section", and what DECLARE_LINUX_SECTION(), for example, actaully
gives you.


Thanks,
Nick

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-24  3:51           ` Nicholas Piggin
  0 siblings, 0 replies; 480+ messages in thread
From: Nicholas Piggin @ 2016-08-24  3:51 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, acme, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, paulus, mpe, James.Bottomley

On Tue, 23 Aug 2016 19:33:06 +0200
"Luis R. Rodriguez" <mcgrof@kernel.org> wrote:

> On Tue, Aug 23, 2016 at 11:26:33AM +1000, Nicholas Piggin wrote:
> > On Fri, 19 Aug 2016 14:34:02 -0700
> > mcgrof@kernel.org wrote:  
> > > +/**
> > > + * DOC: Standard ELF section use in Linux
> > > + *
> > > + * Linux makes use of the standard ELF sections, this sections documents
> > > + * these.
> > > + */
> > > +
> > > +/**
> > > + * DOC: SECTION_RODATA
> > > + *
> > > + * Macro name for code which must be protected from write access, read only
> > > + * data.
> > > + */
> > > +#define SECTION_RODATA			.rodata  
> > 
> > These, for example. The exact name of the section is important in linker
> > scripts and asm, so I can't see the benefit of hiding it. I could be
> > missing the bigger picture.  
> 
> There's two goals by using a macro for these core names. One is to allow us
> to easily aggregate documentation in central place for each, the second is
> to then provide more easily grep'able helpers so we can use them when devising
> extensions or using them in extensions which further customize the sections
> in the kernel.

Documentation is good, but not necessary to have the extra name indirection.
Sections tend (not always, but it would be nice if they did) to follow the
.name convention, which makes them reasonably easy to grep for. They are also
the names you'll be grepping for when you look at disassembly.


> > > +/**
> > > + * DOC: SECTION_TEXT
> > > + *
> > > + * Macro name used to annotate code (functions) used during regular
> > > + * kernel run time. This is combined with `SECTION_RODATA`, only this
> > > + * section also allows for execution.
> > > + *
> > > + */
> > > +#define SECTION_TEXT			.text  
> > 
> > I can't see how these comments are right. .rodata doesn't seem like it
> > should be combined with .text, and is not currently on powerpc. I think
> > it's for data, not code.  
> 
> On x86 and powerpc .rodata follows .text.

But follows is not the same as combined. And together with the comment that
RODATA is for code (which is wrong, it's data), it make it seem like it
is actually combined.


> On power currently the comment
> above in .rodata is:
> 
> /* Text, read only data and other permanent read-only sections */
> 
> When this was introduced however read commit 14cf11af6cf60 ("powerpc: Merge
> enough to start building in arch/powerpc.")
> 
> /* Read-only sections, merged into text segment: */
> 
> The format and style of putting rodata after text is kept from the older
> commits.
> 
> This begs the question. What the hell is this thing talking about?
> 
> On Linux this is done via mark_rodata_ro() on init/main.c when CONFIG_DEBUG_RODATA
> on architectures that support it. Architectures that implement this typically use
> issues set_memory_ro() -- on x86 a start address used is PFN_ALIGN(_text) with
> an end address of &__end_rodata_hpage_align.
> 
> When architectures do not have CONFIG_DEBUG_RODATA() you end up with:
> 
> static inline void mark_readonly(void)                                          
> {                                                                               
>         pr_warn("This architecture does not have kernel memory protection.\n"); 
> }
> 
> So -- I should I clarify then in Linux we strive to have helpers adjust text and
> rodata set to ro with memory protection implemented via mark_readonly(). Architectures
> that do not support memory protection will lack a mark_readonly() implementation.

Right, I wasn't talking about arch implementation of how the ro
protection is done, so much as just the comments being a bit misleading.


> For now I figured a less controversial introduction to the documentation as
> bland as it was above in my original patch would suffice, we can then expand on
> it with something like the above. Thoughts?

I think comments are one of the key features of this patch series (or at
least this patch, I've not looked through the others so much yet). I'm no
expert on linker stuff, but I think a lot of arch maintainers aren't
necessarily either so you tend to get a lot of copy and paste without
always people knowing what exactly is happening. It would be really good
to have some longer explanations and justifications/examples IMO. So I
don't think that would be controversial if you wanted to expand on it.


> > > +/*
> > > + * These section _ALL() helpers are for use on linker scripts and helpers
> > > + */
> > > +#define SECTION_ALL(__section)						\
> > > +	__section##.*  
> > 
> > This is another example. We know what .text.* does in the linker scripts
> > -- it's self documenting. But SECTION_ALL(.text)? I'm not sure that's an
> > improvement. Actually I saw it in the linker script changes and had to
> > come find the definition because I was a bit mislead:
> > 
> > SECTION_ALL(.text)
> > 
> > Initially I would expect this to be
> > 
> > .text*
> > 
> > Not
> > 
> > .text.*
> > 
> > The latter does not grab the .text section!  
> 
> Its not intended to grab .text but rather its for helpers that provide customizations
> based on a core section as base, in this case given your example it would be used by
> section ranges and linker tables for .text. Both section ranges and linker tables
> use postfix .something for their customizations. The SECTION_ALL() macro then is
> a helper for customizations on a core section.

Right, it's just that .text.* is *immediately* obvious. SECTION_ALL() is not.


> If the name is misleading would SECTION_CORE_ALL() be better with some documentation
> explaining this and the above goal ?

I don't know... not to be glib, but .section.* would be better and not require
documentation.

CORE does not really add anything as far as I can see. Other types of .text including
ones which are automatically generated by the compiler, for better or worse, are
.text.x sections too.

I would like to see more standardisation of naming convention -- some sections start
with .., some start with no dots, some use . to separate logical "subsections", others
use underscores or something else. I just don't see it would be a problem to simply
use the raw names and linker wildcards for it.


> > > +/*
> > > + * As per gcc's documentation a common asm separator is a new line followed
> > > + * by tab [0], it however seems possible to also just use a newline as its
> > > + * the most commonly empirically observed semantic and folks seem to agree
> > > + * this even works on S390. In case your architecture disagrees you may
> > > + * override this and define your own and keep the rest of the macros.
> > > + *
> > > + * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
> > > + */
> > > +# ifndef ASM_CMD_SEP
> > > +#  define ASM_CMD_SEP	"\n"
> > > +# endif  
> > 
> > This does not seem like it belongs here. The name is fairly ugly too.  
> 
> Help me bikeshed, any name suggestions?

BTW, I'm not trying to bikeshed :) This doesn't affect the value of your
patch at all, it was just an offhand thing I saw.

> 
> > I guess something might be needed like this when dealing with generic
> > as directives common to all architectures, though.  
> 
> Indeed, it actually seems we don't have much in this area, so this is small
> baby step in that direction.
> 
> > I would say include/asm-generic/asm.h should be a better place.  
> 
> I thought about this -- I'd be adding a new asm-generic/asm.h -- are folks OK
> with that right now? Or should we do that as a secondary step ? I preferred to
> do this as a secondary step as this series is long enough already and there is
> quite a bit that can be dumped in a common asm-generic/asm.h, a few thoughts
> on this already:
> 
>  o x86's asm/asm.h's use of __ASM_FORM() and include/linux/stringify.h share
>    some traits which deserve possible consideration / rebranding.
>  o Since C asm() just wrap things in strings defining a core set of
>    helpers for a task seems justifiable, so for example we have
>    __set_section_core_type(). Raw asm code then would use __set_section_core_type()
>    directly and C asm() would just __stringify() it.
> 
> I figured a bit of bikeshedding would be possible here, so I decided to leave
> this for a later set of patches. But indeed, I agree with you. If we want
> this meshed out now.. let me know and lets bikeshed away...

It's fine, I don't mind too much. I think asm-generic/asm.h should be
fine for generic asm'isms though. Or assembler.h to match compiler.h.


> > > diff --git a/include/linux/sections.h b/include/linux/sections.h
> > > new file mode 100644
> > > index 000000000000..f21c6ee88ded
> > > --- /dev/null
> > > +++ b/include/linux/sections.h
> > > @@ -0,0 +1,111 @@
> > > +#ifndef _LINUX_SECTIONS_H
> > > +#define _LINUX_SECTIONS_H
> > > +/*
> > > + * Linux de-facto sections
> > > + *
> > > + * 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>
> > > +#include <linux/export.h>
> > > +
> > > +#ifndef __ASSEMBLY__
> > > +
> > > +/**
> > > + * DOC: Introduction
> > > + *
> > > + * Linux defines a set of common helpers which can be used to against its use
> > > + * of standard or custom Linux sections, this section is dedicated to these
> > > + * helpers.  
> > 
> > I'm still not quite sure what a Linux de-facto/standard/common section is
> > after this. Are they output sections?  
> 
> We have ELF standard sections, and we have then sections which Linux has introduced
> over the years which are now just known to be expected part of Linux, such as init
> stuff which we free after boot. The combination of the ELF standard sections and
> series of expected sections in Linux across all architectures is what this refers
> to as Linux de-facto/standard/common sections. The header file is intended to
> document these, step by step, and also provide helpers which allow further
> customizations based on these sections.

Well but your macros are not linker sections. They are "Linux sections", which
appear to give you a start and end symbol name, but does not direct the linker
to create a specific output section. I just can't work out what exactly is a
"custom Linux section", and what DECLARE_LINUX_SECTION(), for example, actaully
gives you.


Thanks,
Nick

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 7/7] tools: add userspace linker table sandbox
@ 2016-08-24 12:39                   ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 480+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-08-24 12:39 UTC (permalink / raw)
  To: Kees Cook
  Cc: Arnaldo Carvalho de Melo, H. Peter Anvin, Luis R. Rodriguez,
	Josh Poimboeuf, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Russell King - ARM Linux, Masami Hiramatsu, jbaron,
	Heiko Carstens, ananth, anil.s.keshavamurthy, David S. Miller,
	Miao Steven, x86, Andy Lutomirski, Linus Torvalds, Greg KH,
	Rusty Russell, gnomes

Em Tue, Aug 23, 2016 at 10:28:39PM -0400, Kees Cook escreveu:
> On Tue, Aug 23, 2016 at 10:30 AM, Arnaldo Carvalho de Melo
> <acme@redhat.com> wrote:
> > Em Mon, Aug 22, 2016 at 05:28:42PM -0700, H. Peter Anvin escreveu:
> >> On August 22, 2016 5:07:39 PM PDT, "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> >> >On Fri, Aug 19, 2016 at 03:31:47PM -0700, Kees Cook wrote:

> >> >> Aren't a bunch of these files exact duplicates of the headers in
> >> >include/linux?

> >> >Indeed... This a userspace tools/ architecture decision that was made
> >> >long ago, so its not up to me, I am just following the strategy
> >> >devised and picked up.  Refer to
> >> >7d7d1bf1d1dabe435ef50efb051724b8664749cb ("perf bench: Copy kernel
> >> >files needed to build mem{cpy,set} x86_64 benchmarks") for an example
> >> >of previous similar work. By sharing header files this enable more
> >> >tools/ to be hacked on.

> >> I think this is a legacy from before the uapi change that should
> >> really be fixed.  If we need to export additional kernel structures
> >> for the tools, we could define a third level of we really need it.

> > No, it is something recent, its just that from time to time files that
> > tools/ included from outside, i.e. from the kernel sources, made tools/
> > break, so after discussion with Linus and Ingo[1], it was decided we would

> This [1] reference seems missing. I'm curious to see the thread. I

I added the '[1]', went to look for the discussion yesterday, but it was
a private conversation with ~15 people, bummer, but the one below has
Ingo describing it in another occasion where a new utility got added to
tools/, objtool:

  https://lkml.kernel.org/r/20160309183945.GA17956@gmail.com

And yeah, I started using stuff directly from the kernel, breakage took
place, we changed course.

> wonder if something could be done to just generate the needed headers
> from the canonical locations into the tools/ locations?

Then that would bring possible problems, better to do it manually when
auto-detected.
 
> > grab copies and never more access anything outside tools/ directly.
> >
> > Instead we would check for changes and warn the tools/ developers about
> > it, so that they could check what has changed, that could mean changes
> > should/could be done to tools/ using those headers.
> 
> Is there anything automated in place to notice when these changes happen?

See 791cceb89f7987c0375ff2e8971928a47f62ccae, among others, but it will
amount to something like:

    Changes detected by the tools build system:
    
      $ make -C tools/perf O=/tmp/build/perf install-bin
      make: Entering directory '/home/acme/git/linux/tools/perf'
        BUILD:   Doing 'make -j4' parallel build
--->  Warning: tools/include/uapi/linux/bpf.h differs from kernel <-------
        INSTALL  GTK UI
        CC       /tmp/build/perf/bench/mem-memcpy-x86-64-asm.o
      <SNIP>
      $

- Arnaldo

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 7/7] tools: add userspace linker table sandbox
@ 2016-08-24 12:39                   ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 480+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-08-24 12:39 UTC (permalink / raw)
  To: Kees Cook
  Cc: Arnaldo Carvalho de Melo, H. Peter Anvin, Luis R. Rodriguez,
	Josh Poimboeuf, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Russell King - ARM Linux, Masami Hiramatsu, jbaron,
	Heiko Carstens, ananth, anil.s.keshavamurthy, David S. Miller,
	Miao Steven, x86, Andy Lutomirski, Linus Torvalds, Greg KH,
	Rusty Russell, gnomes, Alan Cox, David Woodhouse, Arnd Bergmann,
	Ming Lei, linux-arch, benh, ananth, Paul Bolle, fontana, David

Em Tue, Aug 23, 2016 at 10:28:39PM -0400, Kees Cook escreveu:
> On Tue, Aug 23, 2016 at 10:30 AM, Arnaldo Carvalho de Melo
> <acme@redhat.com> wrote:
> > Em Mon, Aug 22, 2016 at 05:28:42PM -0700, H. Peter Anvin escreveu:
> >> On August 22, 2016 5:07:39 PM PDT, "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> >> >On Fri, Aug 19, 2016 at 03:31:47PM -0700, Kees Cook wrote:

> >> >> Aren't a bunch of these files exact duplicates of the headers in
> >> >include/linux?

> >> >Indeed... This a userspace tools/ architecture decision that was made
> >> >long ago, so its not up to me, I am just following the strategy
> >> >devised and picked up.  Refer to
> >> >7d7d1bf1d1dabe435ef50efb051724b8664749cb ("perf bench: Copy kernel
> >> >files needed to build mem{cpy,set} x86_64 benchmarks") for an example
> >> >of previous similar work. By sharing header files this enable more
> >> >tools/ to be hacked on.

> >> I think this is a legacy from before the uapi change that should
> >> really be fixed.  If we need to export additional kernel structures
> >> for the tools, we could define a third level of we really need it.

> > No, it is something recent, its just that from time to time files that
> > tools/ included from outside, i.e. from the kernel sources, made tools/
> > break, so after discussion with Linus and Ingo[1], it was decided we would

> This [1] reference seems missing. I'm curious to see the thread. I

I added the '[1]', went to look for the discussion yesterday, but it was
a private conversation with ~15 people, bummer, but the one below has
Ingo describing it in another occasion where a new utility got added to
tools/, objtool:

  https://lkml.kernel.org/r/20160309183945.GA17956@gmail.com

And yeah, I started using stuff directly from the kernel, breakage took
place, we changed course.

> wonder if something could be done to just generate the needed headers
> from the canonical locations into the tools/ locations?

Then that would bring possible problems, better to do it manually when
auto-detected.
 
> > grab copies and never more access anything outside tools/ directly.
> >
> > Instead we would check for changes and warn the tools/ developers about
> > it, so that they could check what has changed, that could mean changes
> > should/could be done to tools/ using those headers.
> 
> Is there anything automated in place to notice when these changes happen?

See 791cceb89f7987c0375ff2e8971928a47f62ccae, among others, but it will
amount to something like:

    Changes detected by the tools build system:
    
      $ make -C tools/perf O=/tmp/build/perf install-bin
      make: Entering directory '/home/acme/git/linux/tools/perf'
        BUILD:   Doing 'make -j4' parallel build
--->  Warning: tools/include/uapi/linux/bpf.h differs from kernel <-------
        INSTALL  GTK UI
        CC       /tmp/build/perf/bench/mem-memcpy-x86-64-asm.o
      <SNIP>
      $

- Arnaldo

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 7/7] tools: add userspace linker table sandbox
@ 2016-08-24 16:20                     ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-24 16:20 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Kees Cook, Arnaldo Carvalho de Melo, H. Peter Anvin,
	Josh Poimboeuf, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Russell King - ARM Linux, Masami Hiramatsu, jbaron,
	Heiko Carstens, ananth, anil.s.keshavamurthy, David S. Miller,
	Miao Steven, x86, Andy Lutomirski, Linus Torvalds, Greg KH,
	Rusty Russell, gnomes

On Wed, Aug 24, 2016 at 5:39 AM, Arnaldo Carvalho de Melo
<acme@kernel.org> wrote:
> Changes detected by the tools build system:
>
>       $ make -C tools/perf O=/tmp/build/perf install-bin
>       make: Entering directory '/home/acme/git/linux/tools/perf'
>         BUILD:   Doing 'make -j4' parallel build
> --->  Warning: tools/include/uapi/linux/bpf.h differs from kernel <-------
>         INSTALL  GTK UI
>         CC       /tmp/build/perf/bench/mem-memcpy-x86-64-asm.o
>       <SNIP>
>       $

I borrowed the same strategy from perf tools and generalized this
through helpers a bit as Makefile helpers in the linker-tables
sandbox:

HEADERS = \
          ../../include/asm-generic/section-core.h \
          ../../include/asm-generic/ranges.h \
          ../../include/asm-generic/tables.h \
          ../../include/linux/sections.h \
          ../../include/linux/ranges.h \
          ../../include/linux/tables.h

__check_headers: $(HEADERS)
        @$(foreach h, $(HEADERS), \
                (test -f $(h) && ( \
                        (diff -B $(subst ../,../,$(h)) $(h) >/dev/null) \
                        || echo "Warning: $(subst ../../,tools/,$(h))
differs from kernel" >&2 ) || true);)


Instead of doing the check / complaint at install it complains at
build time. Its up to the tools to decide when they want this check,
but perhaps later a generic check can be set up. My thought was later
to move some of this as helpers in a generic tools Makefile to more
easily enable other tools/ to do similar checks more easily. I suspect
we may later want to keep a tighter tab on what tools need what
headers and instead have a generic place to keep tabs on this, but we
can do that slowly later after generalizing a checker.

In doing the linker table sandbox one of the needs I found in needing
separate headers was that often you don't want the same copy as the
kernel provides, as you want to port things over to work in userspace
and often ported to libc. So other than the direct copies -- we also
have another category of headers -- ported headers. Its possible not
all tools may end up wanting the same port, this can be addressed
through two means. One is having a generic port which should suffice
for most tools that need libc, and for those that don't want the
generic port they can just carry their own port in their own tree. The
linker tables tools sandbox enables this by allowing first headers to
be search in its own directory, that way it can override what is
provided as generic in tools. However it may still be useful later to
have two separate directories to be able to easily distinguish between
"copies" and "ports". But this can be done later.

Thoughts?

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 7/7] tools: add userspace linker table sandbox
@ 2016-08-24 16:20                     ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-24 16:20 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Kees Cook, Arnaldo Carvalho de Melo, H. Peter Anvin,
	Josh Poimboeuf, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Russell King - ARM Linux, Masami Hiramatsu, jbaron,
	Heiko Carstens, ananth, anil.s.keshavamurthy, David S. Miller,
	Miao Steven, x86, Andy Lutomirski, Linus Torvalds, Greg KH,
	Rusty Russell, gnomes, Alan Cox, David Woodhouse, Arnd Bergmann,
	Ming Lei, linux-arch, benh, ananth, Paul Bolle, Richard Fontana,
	David

On Wed, Aug 24, 2016 at 5:39 AM, Arnaldo Carvalho de Melo
<acme@kernel.org> wrote:
> Changes detected by the tools build system:
>
>       $ make -C tools/perf O=/tmp/build/perf install-bin
>       make: Entering directory '/home/acme/git/linux/tools/perf'
>         BUILD:   Doing 'make -j4' parallel build
> --->  Warning: tools/include/uapi/linux/bpf.h differs from kernel <-------
>         INSTALL  GTK UI
>         CC       /tmp/build/perf/bench/mem-memcpy-x86-64-asm.o
>       <SNIP>
>       $

I borrowed the same strategy from perf tools and generalized this
through helpers a bit as Makefile helpers in the linker-tables
sandbox:

HEADERS = \
          ../../include/asm-generic/section-core.h \
          ../../include/asm-generic/ranges.h \
          ../../include/asm-generic/tables.h \
          ../../include/linux/sections.h \
          ../../include/linux/ranges.h \
          ../../include/linux/tables.h

__check_headers: $(HEADERS)
        @$(foreach h, $(HEADERS), \
                (test -f $(h) && ( \
                        (diff -B $(subst ../,../,$(h)) $(h) >/dev/null) \
                        || echo "Warning: $(subst ../../,tools/,$(h))
differs from kernel" >&2 ) || true);)


Instead of doing the check / complaint at install it complains at
build time. Its up to the tools to decide when they want this check,
but perhaps later a generic check can be set up. My thought was later
to move some of this as helpers in a generic tools Makefile to more
easily enable other tools/ to do similar checks more easily. I suspect
we may later want to keep a tighter tab on what tools need what
headers and instead have a generic place to keep tabs on this, but we
can do that slowly later after generalizing a checker.

In doing the linker table sandbox one of the needs I found in needing
separate headers was that often you don't want the same copy as the
kernel provides, as you want to port things over to work in userspace
and often ported to libc. So other than the direct copies -- we also
have another category of headers -- ported headers. Its possible not
all tools may end up wanting the same port, this can be addressed
through two means. One is having a generic port which should suffice
for most tools that need libc, and for those that don't want the
generic port they can just carry their own port in their own tree. The
linker tables tools sandbox enables this by allowing first headers to
be search in its own directory, that way it can override what is
provided as generic in tools. However it may still be useful later to
have two separate directories to be able to easily distinguish between
"copies" and "ports". But this can be done later.

Thoughts?

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 7/7] tools: add userspace linker table sandbox
@ 2016-08-24 19:17                       ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 480+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-08-24 19:17 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: Kees Cook, Arnaldo Carvalho de Melo, H. Peter Anvin,
	Josh Poimboeuf, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Russell King - ARM Linux, Masami Hiramatsu, jbaron,
	Heiko Carstens, ananth, anil.s.keshavamurthy, David S. Miller,
	Miao Steven, x86, Andy Lutomirski, Linus Torvalds, Greg KH,
	Rusty Russell, gnomes

Em Wed, Aug 24, 2016 at 09:20:12AM -0700, Luis R. Rodriguez escreveu:
> On Wed, Aug 24, 2016 at 5:39 AM, Arnaldo Carvalho de Melo
> <acme@kernel.org> wrote:
> > Changes detected by the tools build system:
> >
> >       $ make -C tools/perf O=/tmp/build/perf install-bin
> >       make: Entering directory '/home/acme/git/linux/tools/perf'
> >         BUILD:   Doing 'make -j4' parallel build
> > --->  Warning: tools/include/uapi/linux/bpf.h differs from kernel <-------
> >         INSTALL  GTK UI
> >         CC       /tmp/build/perf/bench/mem-memcpy-x86-64-asm.o
> >       <SNIP>
> >       $
 
> I borrowed the same strategy from perf tools and generalized this
> through helpers a bit as Makefile helpers in the linker-tables
> sandbox:
 
> HEADERS = \
>           ../../include/asm-generic/section-core.h \
>           ../../include/asm-generic/ranges.h \
>           ../../include/asm-generic/tables.h \
>           ../../include/linux/sections.h \
>           ../../include/linux/ranges.h \
>           ../../include/linux/tables.h
> 
> __check_headers: $(HEADERS)
>         @$(foreach h, $(HEADERS), \
>                 (test -f $(h) && ( \
>                         (diff -B $(subst ../,../,$(h)) $(h) >/dev/null) \
>                         || echo "Warning: $(subst ../../,tools/,$(h))
> differs from kernel" >&2 ) || true);)
 
> Instead of doing the check / complaint at install it complains at
> build time. Its up to the tools to decide when they want this check,
> but perhaps later a generic check can be set up. My thought was later
> to move some of this as helpers in a generic tools Makefile to more
> easily enable other tools/ to do similar checks more easily. I suspect
> we may later want to keep a tighter tab on what tools need what
> headers and instead have a generic place to keep tabs on this, but we
> can do that slowly later after generalizing a checker.

Right
 
> In doing the linker table sandbox one of the needs I found in needing
> separate headers was that often you don't want the same copy as the
> kernel provides, as you want to port things over to work in userspace

Right, the ones that are direct copies are the ones being checked with
diff, there are others, as you say, that are not copies and are not
being checked at all :-\

Example:

tools/include/linux/rbtree.h

The kernel one has RCU stuff, in it and tools still doesn't have some
userspace RCU implementation that could provide what it expects.

Without collaboration from the kernel people working on
include/linux/rbtree.h, that is what we can do.

> and often ported to libc. So other than the direct copies -- we also
> have another category of headers -- ported headers. Its possible not

yeah

> all tools may end up wanting the same port, this can be addressed
> through two means. One is having a generic port which should suffice
> for most tools that need libc, and for those that don't want the
> generic port they can just carry their own port in their own tree. The
> linker tables tools sandbox enables this by allowing first headers to
> be search in its own directory, that way it can override what is
> provided as generic in tools. However it may still be useful later to
> have two separate directories to be able to easily distinguish between
> "copies" and "ports". But this can be done later.
> 
> Thoughts?

I don't see problems with your reasoning, do what is faster for having
your tool in place and we can go on improving the way tools/ gets stuff
from the kernel, how we detect changes that could be interesting to get
and eventually how kernel developers can help in this process.

What we don't want is to burden the kernel developers with things for
tools/.

- Arnaldo

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v1 7/7] tools: add userspace linker table sandbox
@ 2016-08-24 19:17                       ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 480+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-08-24 19:17 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: Kees Cook, Arnaldo Carvalho de Melo, H. Peter Anvin,
	Josh Poimboeuf, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Russell King - ARM Linux, Masami Hiramatsu, jbaron,
	Heiko Carstens, ananth, anil.s.keshavamurthy, David S. Miller,
	Miao Steven, x86, Andy Lutomirski, Linus Torvalds, Greg KH,
	Rusty Russell, gnomes, Alan Cox, David Woodhouse, Arnd Bergmann,
	Ming Lei, linux-arch, benh, ananth, Paul Bolle, Richard Fontana,
	David

Em Wed, Aug 24, 2016 at 09:20:12AM -0700, Luis R. Rodriguez escreveu:
> On Wed, Aug 24, 2016 at 5:39 AM, Arnaldo Carvalho de Melo
> <acme@kernel.org> wrote:
> > Changes detected by the tools build system:
> >
> >       $ make -C tools/perf O=/tmp/build/perf install-bin
> >       make: Entering directory '/home/acme/git/linux/tools/perf'
> >         BUILD:   Doing 'make -j4' parallel build
> > --->  Warning: tools/include/uapi/linux/bpf.h differs from kernel <-------
> >         INSTALL  GTK UI
> >         CC       /tmp/build/perf/bench/mem-memcpy-x86-64-asm.o
> >       <SNIP>
> >       $
 
> I borrowed the same strategy from perf tools and generalized this
> through helpers a bit as Makefile helpers in the linker-tables
> sandbox:
 
> HEADERS = \
>           ../../include/asm-generic/section-core.h \
>           ../../include/asm-generic/ranges.h \
>           ../../include/asm-generic/tables.h \
>           ../../include/linux/sections.h \
>           ../../include/linux/ranges.h \
>           ../../include/linux/tables.h
> 
> __check_headers: $(HEADERS)
>         @$(foreach h, $(HEADERS), \
>                 (test -f $(h) && ( \
>                         (diff -B $(subst ../,../,$(h)) $(h) >/dev/null) \
>                         || echo "Warning: $(subst ../../,tools/,$(h))
> differs from kernel" >&2 ) || true);)
 
> Instead of doing the check / complaint at install it complains at
> build time. Its up to the tools to decide when they want this check,
> but perhaps later a generic check can be set up. My thought was later
> to move some of this as helpers in a generic tools Makefile to more
> easily enable other tools/ to do similar checks more easily. I suspect
> we may later want to keep a tighter tab on what tools need what
> headers and instead have a generic place to keep tabs on this, but we
> can do that slowly later after generalizing a checker.

Right
 
> In doing the linker table sandbox one of the needs I found in needing
> separate headers was that often you don't want the same copy as the
> kernel provides, as you want to port things over to work in userspace

Right, the ones that are direct copies are the ones being checked with
diff, there are others, as you say, that are not copies and are not
being checked at all :-\

Example:

tools/include/linux/rbtree.h

The kernel one has RCU stuff, in it and tools still doesn't have some
userspace RCU implementation that could provide what it expects.

Without collaboration from the kernel people working on
include/linux/rbtree.h, that is what we can do.

> and often ported to libc. So other than the direct copies -- we also
> have another category of headers -- ported headers. Its possible not

yeah

> all tools may end up wanting the same port, this can be addressed
> through two means. One is having a generic port which should suffice
> for most tools that need libc, and for those that don't want the
> generic port they can just carry their own port in their own tree. The
> linker tables tools sandbox enables this by allowing first headers to
> be search in its own directory, that way it can override what is
> provided as generic in tools. However it may still be useful later to
> have two separate directories to be able to easily distinguish between
> "copies" and "ports". But this can be done later.
> 
> Thoughts?

I don't see problems with your reasoning, do what is faster for having
your tool in place and we can go on improving the way tools/ gets stuff
from the kernel, how we detect changes that could be interesting to get
and eventually how kernel developers can help in this process.

What we don't want is to burden the kernel developers with things for
tools/.

- Arnaldo

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
  2016-08-24  3:51           ` Nicholas Piggin
  (?)
@ 2016-08-24 20:12             ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-24 20:12 UTC (permalink / raw)
  To: Nicholas Piggin
  Cc: Luis R. Rodriguez, hpa, tglx, mingo, jpoimboe, bp, linux,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Wed, Aug 24, 2016 at 01:51:41PM +1000, Nicholas Piggin wrote:
> On Tue, 23 Aug 2016 19:33:06 +0200
> "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> 
> > On Tue, Aug 23, 2016 at 11:26:33AM +1000, Nicholas Piggin wrote:
> > > On Fri, 19 Aug 2016 14:34:02 -0700
> > > mcgrof@kernel.org wrote:  
> > > > +/**
> > > > + * DOC: Standard ELF section use in Linux
> > > > + *
> > > > + * Linux makes use of the standard ELF sections, this sections documents
> > > > + * these.
> > > > + */
> > > > +
> > > > +/**
> > > > + * DOC: SECTION_RODATA
> > > > + *
> > > > + * Macro name for code which must be protected from write access, read only
> > > > + * data.
> > > > + */
> > > > +#define SECTION_RODATA			.rodata  
> > > 
> > > These, for example. The exact name of the section is important in linker
> > > scripts and asm, so I can't see the benefit of hiding it. I could be
> > > missing the bigger picture.  
> > 
> > There's two goals by using a macro for these core names. One is to allow us
> > to easily aggregate documentation in central place for each, the second is
> > to then provide more easily grep'able helpers so we can use them when devising
> > extensions or using them in extensions which further customize the sections
> > in the kernel.

Just thought of more more justification I had forgotten. I cover it below.

> Documentation is good, but not necessary to have the extra name indirection.

Fair point.

> Sections tend (not always, but it would be nice if they did) to follow the
> .name convention, which makes them reasonably easy to grep for.

git grep .text  doesn't work but that is typically expected...
git grep \.text doesn't work as expected

Ah finally:

git grep "\.text" seems to work. But WTF.

But:

git grep SECTION_TEXT works as expected immediately.

I guess its a matter of perspective.

> They are also
> the names you'll be grepping for when you look at disassembly.

Sure but if you're grepping asm, you very likely know what to look for.

> > > > +/**
> > > > + * DOC: SECTION_TEXT
> > > > + *
> > > > + * Macro name used to annotate code (functions) used during regular
> > > > + * kernel run time. This is combined with `SECTION_RODATA`, only this
> > > > + * section also allows for execution.
> > > > + *
> > > > + */
> > > > +#define SECTION_TEXT			.text  
> > > 
> > > I can't see how these comments are right. .rodata doesn't seem like it
> > > should be combined with .text, and is not currently on powerpc. I think
> > > it's for data, not code.  
> > 
> > On x86 and powerpc .rodata follows .text.
> 
> But follows is not the same as combined.

True and as I confirmed below, on PowerPC this is certainly not true.

> And together with the comment that RODATA is for code (which is wrong, it's data),

Where did I have that? If you refer to the above SECTION_TEXT documentation, it
refers to SECTION_TEXT being for code, but the goal was to highlight that
SECTION_TEXT is for execution, while SECTION_RODATA was for data. This
certainly can use some love though, thanks, will just drop the SECTION_RODATA
reference *or* properly explain the whole thing below.

> it make it seem like it is actually combined.

Will fix to ensure this is understood in proper context.

> > On power currently the comment
> > above in .rodata is:
> > 
> > /* Text, read only data and other permanent read-only sections */
> > 
> > When this was introduced however read commit 14cf11af6cf60 ("powerpc: Merge
> > enough to start building in arch/powerpc.")
> > 
> > /* Read-only sections, merged into text segment: */
> > 
> > The format and style of putting rodata after text is kept from the older
> > commits.
> > 
> > This begs the question. What the hell is this thing talking about?
> > 
> > On Linux this is done via mark_rodata_ro() on init/main.c when CONFIG_DEBUG_RODATA
> > on architectures that support it. Architectures that implement this typically use
> > issues set_memory_ro() -- on x86 a start address used is PFN_ALIGN(_text) with
> > an end address of &__end_rodata_hpage_align.
> > 
> > When architectures do not have CONFIG_DEBUG_RODATA() you end up with:
> > 
> > static inline void mark_readonly(void)                                          
> > {                                                                               
> >         pr_warn("This architecture does not have kernel memory protection.\n"); 
> > }
> > 
> > So -- I should I clarify then in Linux we strive to have helpers adjust text and
> > rodata set to ro with memory protection implemented via mark_readonly(). Architectures
> > that do not support memory protection will lack a mark_readonly() implementation.
> 
> Right, I wasn't talking about arch implementation of how the ro
> protection is done, so much as just the comments being a bit misleading.

Sure, got it, thanks, will fix.

> > For now I figured a less controversial introduction to the documentation as
> > bland as it was above in my original patch would suffice, we can then expand on
> > it with something like the above. Thoughts?
> 
> I think comments are one of the key features of this patch series (or at
> least this patch, I've not looked through the others so much yet).

Definitely -- the goal was to give us central place to document some of this
obscure dark magic only a few witches and warlocks tend to be aware of.

> I'm no
> expert on linker stuff, but I think a lot of arch maintainers aren't
> necessarily either so you tend to get a lot of copy and paste without
> always people knowing what exactly is happening.

:) Yes indeed, the little crusade over the PowerPC linker script comments
on .text and ro data is an example of how easily things can be misleading.

> It would be really good
> to have some longer explanations and justifications/examples IMO. So I
> don't think that would be controversial if you wanted to expand on it.

Sure, but what I was trying to say above is I'd rather have the basic
layout of the documentation finalized before we start getting into very
specific detailed elaborate details on some of these things. For instance
we still haven't decided if we wanted SECTION_TEXT or just require everyone
to hard code in .text in every place a user wants to use .text sections.
I'd rather settle that before trying to document mark_readonly().

> > > > +/*
> > > > + * These section _ALL() helpers are for use on linker scripts and helpers
> > > > + */
> > > > +#define SECTION_ALL(__section)						\
> > > > +	__section##.*  
> > > 
> > > This is another example. We know what .text.* does in the linker scripts
> > > -- it's self documenting. But SECTION_ALL(.text)? I'm not sure that's an
> > > improvement. Actually I saw it in the linker script changes and had to
> > > come find the definition because I was a bit mislead:
> > > 
> > > SECTION_ALL(.text)
> > > 
> > > Initially I would expect this to be
> > > 
> > > .text*
> > > 
> > > Not
> > > 
> > > .text.*
> > > 
> > > The latter does not grab the .text section!  
> > 
> > Its not intended to grab .text but rather its for helpers that provide customizations
> > based on a core section as base, in this case given your example it would be used by
> > section ranges and linker tables for .text. Both section ranges and linker tables
> > use postfix .something for their customizations. The SECTION_ALL() macro then is
> > a helper for customizations on a core section.
> 
> Right, it's just that .text.* is *immediately* obvious. SECTION_ALL() is not.

Which is why I was suggesting perhaps an alternative name.

> > If the name is misleading would SECTION_CORE_ALL() be better with some documentation
> > explaining this and the above goal ?
> 
> I don't know... not to be glib, but .section.* would be better and not require
> documentation.

Well consider the issues below for a second... and keep in mind with linker
tables we are about to open the prospect to add more things into the kernel's
sections more easily than before.

> CORE does not really add anything as far as I can see. Other types of .text including
> ones which are automatically generated by the compiler, for better or worse, are
> .text.x sections too.

Actually, sorry, in this case SECTION_ALL() *was* intended for things that are
not linker tables or section ranges, instead this was for globs that want to
use the new section macro names, so we only use this for:
*(SECTION_ALL(SECTION_RODATA)) at this time.  It would seem we just did not
have .text.* and friends (other section names documented here). So this is
more of a reaction to provide a way to use a glob for section names if they
have a macro name.

The idea was to add helpers to do the globbing more easily.

The glob for sections now documented   is SECTION_ALL()
The glob that is range specific        is SECTION_RNG_ALL()
The glob that is linker table specific is SECTION_TBL_ALL()

The only one needing SECTION_ALL() it turns out was .rodata:

-               *(.rodata) *(.rodata.*)                                 \
+               *(SECTION_RODATA) *(SECTION_ALL(SECTION_RODATA))        \

> I would like to see more standardisation of naming convention -- some sections start
> with .., some start with no dots, some use . to separate logical "subsections", others
> use underscores or something else.

Agreed... Actually while at it -- anyone happen to know why the two dot thing
started creeping up?

> I just don't see it would be a problem to simply use the raw names and linker
> wildcards for it.

A concern here is more abuse over this if we now expose APIs to users to
more easily customize sections. So let's review what the chances are.

$ git grep DEFINE_SECTION_RANGE| egrep -v "tools|include|Document"
kernel/kprobes.c:DEFINE_SECTION_RANGE(kprobes, SECTION_TEXT);

These require the actual desired section specified. Do we want
to just hide that ? Or are we OK in assuming users willing to use
proper names here?

For linker tables we actually provide full helpers for each section
type. So we have:

$ git grep DEFINE_LINKTABLE| egrep -v "tools|include|Document"
drivers/base/firmware_class.c:DEFINE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
kernel/jump_label.c:DEFINE_LINKTABLE(struct jump_entry, __jump_table);
kernel/kprobes.c:DEFINE_LINKTABLE_INIT_DATA(unsigned long, _kprobe_blacklist);
lib/dynamic_debug.c:DEFINE_LINKTABLE(struct _ddebug, __verbose);

So for linker tables we're safe from abuse as we provide all direct use
of the section up to the implementation behind the scenes.

If we're happy then with people using a proper section name for section
ranges then I think we can require the full section name being
spelled out.

> > > > +/*
> > > > + * As per gcc's documentation a common asm separator is a new line followed
> > > > + * by tab [0], it however seems possible to also just use a newline as its
> > > > + * the most commonly empirically observed semantic and folks seem to agree
> > > > + * this even works on S390. In case your architecture disagrees you may
> > > > + * override this and define your own and keep the rest of the macros.
> > > > + *
> > > > + * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
> > > > + */
> > > > +# ifndef ASM_CMD_SEP
> > > > +#  define ASM_CMD_SEP	"\n"
> > > > +# endif  
> > > 
> > > This does not seem like it belongs here. The name is fairly ugly too.  
> > 
> > Help me bikeshed, any name suggestions?
> 
> BTW, I'm not trying to bikeshed :) This doesn't affect the value of your
> patch at all, it was just an offhand thing I saw.

Just saying, if you say its ugly please help me with a different name then.

> > > I guess something might be needed like this when dealing with generic
> > > as directives common to all architectures, though.  
> > 
> > Indeed, it actually seems we don't have much in this area, so this is small
> > baby step in that direction.
> > 
> > > I would say include/asm-generic/asm.h should be a better place.  
> > 
> > I thought about this -- I'd be adding a new asm-generic/asm.h -- are folks OK
> > with that right now? Or should we do that as a secondary step ? I preferred to
> > do this as a secondary step as this series is long enough already and there is
> > quite a bit that can be dumped in a common asm-generic/asm.h, a few thoughts
> > on this already:
> > 
> >  o x86's asm/asm.h's use of __ASM_FORM() and include/linux/stringify.h share
> >    some traits which deserve possible consideration / rebranding.
> >  o Since C asm() just wrap things in strings defining a core set of
> >    helpers for a task seems justifiable, so for example we have
> >    __set_section_core_type(). Raw asm code then would use __set_section_core_type()
> >    directly and C asm() would just __stringify() it.
> > 
> > I figured a bit of bikeshedding would be possible here, so I decided to leave
> > this for a later set of patches. But indeed, I agree with you. If we want
> > this meshed out now.. let me know and lets bikeshed away...
> 
> It's fine, I don't mind too much. I think asm-generic/asm.h should be
> fine for generic asm'isms though. Or assembler.h to match compiler.h.

I'd like address this in asm.h but I would hope we can do this as a secondary
step, given the length of this patch set already. Thoughts ?

> 
> > > > diff --git a/include/linux/sections.h b/include/linux/sections.h
> > > > new file mode 100644
> > > > index 000000000000..f21c6ee88ded
> > > > --- /dev/null
> > > > +++ b/include/linux/sections.h
> > > > @@ -0,0 +1,111 @@
> > > > +#ifndef _LINUX_SECTIONS_H
> > > > +#define _LINUX_SECTIONS_H
> > > > +/*
> > > > + * Linux de-facto sections
> > > > + *
> > > > + * 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>
> > > > +#include <linux/export.h>
> > > > +
> > > > +#ifndef __ASSEMBLY__
> > > > +
> > > > +/**
> > > > + * DOC: Introduction
> > > > + *
> > > > + * Linux defines a set of common helpers which can be used to against its use
> > > > + * of standard or custom Linux sections, this section is dedicated to these
> > > > + * helpers.  
> > > 
> > > I'm still not quite sure what a Linux de-facto/standard/common section is
> > > after this. Are they output sections?  
> > 
> > We have ELF standard sections, and we have then sections which Linux has introduced
> > over the years which are now just known to be expected part of Linux, such as init
> > stuff which we free after boot. The combination of the ELF standard sections and
> > series of expected sections in Linux across all architectures is what this refers
> > to as Linux de-facto/standard/common sections. The header file is intended to
> > document these, step by step, and also provide helpers which allow further
> > customizations based on these sections.
> 
> Well but your macros are not linker sections. They are "Linux sections", which
> appear to give you a start and end symbol name, but does not direct the linker
> to create a specific output section.

You're right the above can use some love to help explain this better.

How about:

At the top just use "Linux sections helpers"

Then:

/**
 * DOC: Introduction
 *
 * We document below a dedicated set of helpers used in Linux to make sections
 * defined in the Linux linker script accessible in C code in a generic form and 
 * and provide certain attributes about them.
 */

> I just can't work out what exactly is a
> "custom Linux section", and what DECLARE_LINUX_SECTION(), for example, actaully
> gives you.

Its a way to replace the:

extern char foo[], foo__end[];

So this provides a generalized form to use declarations used in C code to make
the linker script start and end symbols from esctions accessible in C code. Since
DEFINE_SECTION_RANGE() and DEFINE_LINKTABLE() macros use this, then the
DECLARE_LINUX_SECTION() is only needed if you need access to these symbols in C
code outside of the one that is defining and mainly in charge of managing the
section. We provide DECLARE_*() helpers for section ranges and linker tables
though so those can be used instead to help annotate the type of a custom
section they are.

So for instance, since the following tables are used in C code outside
of the code that implemented and manages them:

mcgrof@ergon ~/linux-next (git::20160822-linker-table-v5)$ git grep DECLARE_LINKTA| egrep -v "Documentation|tools|tables"
arch/x86/kernel/cpu/microcode/core.c:DECLARE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
include/linux/dynamic_debug.h:DECLARE_LINKTABLE(struct _ddebug, __verbose);
include/linux/jump_label.h:DECLARE_LINKTABLE(struct jump_entry, __jump_table);
include/linux/kprobes.h:DECLARE_LINKTABLE(unsigned long, _kprobe_blacklist);

Note that the big trick here was to enable users to associate a new custom
section in C to a well defined already existing Linux section without modifying
the Linux linker script. Then, since as we observe and study uses of how Linux
sections are used, we've noticed a pattern -- most declarations of these sections
of really of two types, a section ranges or linker table. The patch set then
provides generic building blocks for these and ports a few existing custom Linux
sections to them as an example.

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-24 20:12             ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-24 20:12 UTC (permalink / raw)
  To: Nicholas Piggin
  Cc: Luis R. Rodriguez, hpa, tglx, mingo, jpoimboe, bp, linux,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Wed, Aug 24, 2016 at 01:51:41PM +1000, Nicholas Piggin wrote:
> On Tue, 23 Aug 2016 19:33:06 +0200
> "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> 
> > On Tue, Aug 23, 2016 at 11:26:33AM +1000, Nicholas Piggin wrote:
> > > On Fri, 19 Aug 2016 14:34:02 -0700
> > > mcgrof@kernel.org wrote:  
> > > > +/**
> > > > + * DOC: Standard ELF section use in Linux
> > > > + *
> > > > + * Linux makes use of the standard ELF sections, this sections documents
> > > > + * these.
> > > > + */
> > > > +
> > > > +/**
> > > > + * DOC: SECTION_RODATA
> > > > + *
> > > > + * Macro name for code which must be protected from write access, read only
> > > > + * data.
> > > > + */
> > > > +#define SECTION_RODATA			.rodata  
> > > 
> > > These, for example. The exact name of the section is important in linker
> > > scripts and asm, so I can't see the benefit of hiding it. I could be
> > > missing the bigger picture.  
> > 
> > There's two goals by using a macro for these core names. One is to allow us
> > to easily aggregate documentation in central place for each, the second is
> > to then provide more easily grep'able helpers so we can use them when devising
> > extensions or using them in extensions which further customize the sections
> > in the kernel.

Just thought of more more justification I had forgotten. I cover it below.

> Documentation is good, but not necessary to have the extra name indirection.

Fair point.

> Sections tend (not always, but it would be nice if they did) to follow the
> .name convention, which makes them reasonably easy to grep for.

git grep .text  doesn't work but that is typically expected...
git grep \.text doesn't work as expected

Ah finally:

git grep "\.text" seems to work. But WTF.

But:

git grep SECTION_TEXT works as expected immediately.

I guess its a matter of perspective.

> They are also
> the names you'll be grepping for when you look at disassembly.

Sure but if you're grepping asm, you very likely know what to look for.

> > > > +/**
> > > > + * DOC: SECTION_TEXT
> > > > + *
> > > > + * Macro name used to annotate code (functions) used during regular
> > > > + * kernel run time. This is combined with `SECTION_RODATA`, only this
> > > > + * section also allows for execution.
> > > > + *
> > > > + */
> > > > +#define SECTION_TEXT			.text  
> > > 
> > > I can't see how these comments are right. .rodata doesn't seem like it
> > > should be combined with .text, and is not currently on powerpc. I think
> > > it's for data, not code.  
> > 
> > On x86 and powerpc .rodata follows .text.
> 
> But follows is not the same as combined.

True and as I confirmed below, on PowerPC this is certainly not true.

> And together with the comment that RODATA is for code (which is wrong, it's data),

Where did I have that? If you refer to the above SECTION_TEXT documentation, it
refers to SECTION_TEXT being for code, but the goal was to highlight that
SECTION_TEXT is for execution, while SECTION_RODATA was for data. This
certainly can use some love though, thanks, will just drop the SECTION_RODATA
reference *or* properly explain the whole thing below.

> it make it seem like it is actually combined.

Will fix to ensure this is understood in proper context.

> > On power currently the comment
> > above in .rodata is:
> > 
> > /* Text, read only data and other permanent read-only sections */
> > 
> > When this was introduced however read commit 14cf11af6cf60 ("powerpc: Merge
> > enough to start building in arch/powerpc.")
> > 
> > /* Read-only sections, merged into text segment: */
> > 
> > The format and style of putting rodata after text is kept from the older
> > commits.
> > 
> > This begs the question. What the hell is this thing talking about?
> > 
> > On Linux this is done via mark_rodata_ro() on init/main.c when CONFIG_DEBUG_RODATA
> > on architectures that support it. Architectures that implement this typically use
> > issues set_memory_ro() -- on x86 a start address used is PFN_ALIGN(_text) with
> > an end address of &__end_rodata_hpage_align.
> > 
> > When architectures do not have CONFIG_DEBUG_RODATA() you end up with:
> > 
> > static inline void mark_readonly(void)                                          
> > {                                                                               
> >         pr_warn("This architecture does not have kernel memory protection.\n"); 
> > }
> > 
> > So -- I should I clarify then in Linux we strive to have helpers adjust text and
> > rodata set to ro with memory protection implemented via mark_readonly(). Architectures
> > that do not support memory protection will lack a mark_readonly() implementation.
> 
> Right, I wasn't talking about arch implementation of how the ro
> protection is done, so much as just the comments being a bit misleading.

Sure, got it, thanks, will fix.

> > For now I figured a less controversial introduction to the documentation as
> > bland as it was above in my original patch would suffice, we can then expand on
> > it with something like the above. Thoughts?
> 
> I think comments are one of the key features of this patch series (or at
> least this patch, I've not looked through the others so much yet).

Definitely -- the goal was to give us central place to document some of this
obscure dark magic only a few witches and warlocks tend to be aware of.

> I'm no
> expert on linker stuff, but I think a lot of arch maintainers aren't
> necessarily either so you tend to get a lot of copy and paste without
> always people knowing what exactly is happening.

:) Yes indeed, the little crusade over the PowerPC linker script comments
on .text and ro data is an example of how easily things can be misleading.

> It would be really good
> to have some longer explanations and justifications/examples IMO. So I
> don't think that would be controversial if you wanted to expand on it.

Sure, but what I was trying to say above is I'd rather have the basic
layout of the documentation finalized before we start getting into very
specific detailed elaborate details on some of these things. For instance
we still haven't decided if we wanted SECTION_TEXT or just require everyone
to hard code in .text in every place a user wants to use .text sections.
I'd rather settle that before trying to document mark_readonly().

> > > > +/*
> > > > + * These section _ALL() helpers are for use on linker scripts and helpers
> > > > + */
> > > > +#define SECTION_ALL(__section)						\
> > > > +	__section##.*  
> > > 
> > > This is another example. We know what .text.* does in the linker scripts
> > > -- it's self documenting. But SECTION_ALL(.text)? I'm not sure that's an
> > > improvement. Actually I saw it in the linker script changes and had to
> > > come find the definition because I was a bit mislead:
> > > 
> > > SECTION_ALL(.text)
> > > 
> > > Initially I would expect this to be
> > > 
> > > .text*
> > > 
> > > Not
> > > 
> > > .text.*
> > > 
> > > The latter does not grab the .text section!  
> > 
> > Its not intended to grab .text but rather its for helpers that provide customizations
> > based on a core section as base, in this case given your example it would be used by
> > section ranges and linker tables for .text. Both section ranges and linker tables
> > use postfix .something for their customizations. The SECTION_ALL() macro then is
> > a helper for customizations on a core section.
> 
> Right, it's just that .text.* is *immediately* obvious. SECTION_ALL() is not.

Which is why I was suggesting perhaps an alternative name.

> > If the name is misleading would SECTION_CORE_ALL() be better with some documentation
> > explaining this and the above goal ?
> 
> I don't know... not to be glib, but .section.* would be better and not require
> documentation.

Well consider the issues below for a second... and keep in mind with linker
tables we are about to open the prospect to add more things into the kernel's
sections more easily than before.

> CORE does not really add anything as far as I can see. Other types of .text including
> ones which are automatically generated by the compiler, for better or worse, are
> .text.x sections too.

Actually, sorry, in this case SECTION_ALL() *was* intended for things that are
not linker tables or section ranges, instead this was for globs that want to
use the new section macro names, so we only use this for:
*(SECTION_ALL(SECTION_RODATA)) at this time.  It would seem we just did not
have .text.* and friends (other section names documented here). So this is
more of a reaction to provide a way to use a glob for section names if they
have a macro name.

The idea was to add helpers to do the globbing more easily.

The glob for sections now documented   is SECTION_ALL()
The glob that is range specific        is SECTION_RNG_ALL()
The glob that is linker table specific is SECTION_TBL_ALL()

The only one needing SECTION_ALL() it turns out was .rodata:

-               *(.rodata) *(.rodata.*)                                 \
+               *(SECTION_RODATA) *(SECTION_ALL(SECTION_RODATA))        \

> I would like to see more standardisation of naming convention -- some sections start
> with .., some start with no dots, some use . to separate logical "subsections", others
> use underscores or something else.

Agreed... Actually while at it -- anyone happen to know why the two dot thing
started creeping up?

> I just don't see it would be a problem to simply use the raw names and linker
> wildcards for it.

A concern here is more abuse over this if we now expose APIs to users to
more easily customize sections. So let's review what the chances are.

$ git grep DEFINE_SECTION_RANGE| egrep -v "tools|include|Document"
kernel/kprobes.c:DEFINE_SECTION_RANGE(kprobes, SECTION_TEXT);

These require the actual desired section specified. Do we want
to just hide that ? Or are we OK in assuming users willing to use
proper names here?

For linker tables we actually provide full helpers for each section
type. So we have:

$ git grep DEFINE_LINKTABLE| egrep -v "tools|include|Document"
drivers/base/firmware_class.c:DEFINE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
kernel/jump_label.c:DEFINE_LINKTABLE(struct jump_entry, __jump_table);
kernel/kprobes.c:DEFINE_LINKTABLE_INIT_DATA(unsigned long, _kprobe_blacklist);
lib/dynamic_debug.c:DEFINE_LINKTABLE(struct _ddebug, __verbose);

So for linker tables we're safe from abuse as we provide all direct use
of the section up to the implementation behind the scenes.

If we're happy then with people using a proper section name for section
ranges then I think we can require the full section name being
spelled out.

> > > > +/*
> > > > + * As per gcc's documentation a common asm separator is a new line followed
> > > > + * by tab [0], it however seems possible to also just use a newline as its
> > > > + * the most commonly empirically observed semantic and folks seem to agree
> > > > + * this even works on S390. In case your architecture disagrees you may
> > > > + * override this and define your own and keep the rest of the macros.
> > > > + *
> > > > + * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
> > > > + */
> > > > +# ifndef ASM_CMD_SEP
> > > > +#  define ASM_CMD_SEP	"\n"
> > > > +# endif  
> > > 
> > > This does not seem like it belongs here. The name is fairly ugly too.  
> > 
> > Help me bikeshed, any name suggestions?
> 
> BTW, I'm not trying to bikeshed :) This doesn't affect the value of your
> patch at all, it was just an offhand thing I saw.

Just saying, if you say its ugly please help me with a different name then.

> > > I guess something might be needed like this when dealing with generic
> > > as directives common to all architectures, though.  
> > 
> > Indeed, it actually seems we don't have much in this area, so this is small
> > baby step in that direction.
> > 
> > > I would say include/asm-generic/asm.h should be a better place.  
> > 
> > I thought about this -- I'd be adding a new asm-generic/asm.h -- are folks OK
> > with that right now? Or should we do that as a secondary step ? I preferred to
> > do this as a secondary step as this series is long enough already and there is
> > quite a bit that can be dumped in a common asm-generic/asm.h, a few thoughts
> > on this already:
> > 
> >  o x86's asm/asm.h's use of __ASM_FORM() and include/linux/stringify.h share
> >    some traits which deserve possible consideration / rebranding.
> >  o Since C asm() just wrap things in strings defining a core set of
> >    helpers for a task seems justifiable, so for example we have
> >    __set_section_core_type(). Raw asm code then would use __set_section_core_type()
> >    directly and C asm() would just __stringify() it.
> > 
> > I figured a bit of bikeshedding would be possible here, so I decided to leave
> > this for a later set of patches. But indeed, I agree with you. If we want
> > this meshed out now.. let me know and lets bikeshed away...
> 
> It's fine, I don't mind too much. I think asm-generic/asm.h should be
> fine for generic asm'isms though. Or assembler.h to match compiler.h.

I'd like address this in asm.h but I would hope we can do this as a secondary
step, given the length of this patch set already. Thoughts ?

> 
> > > > diff --git a/include/linux/sections.h b/include/linux/sections.h
> > > > new file mode 100644
> > > > index 000000000000..f21c6ee88ded
> > > > --- /dev/null
> > > > +++ b/include/linux/sections.h
> > > > @@ -0,0 +1,111 @@
> > > > +#ifndef _LINUX_SECTIONS_H
> > > > +#define _LINUX_SECTIONS_H
> > > > +/*
> > > > + * Linux de-facto sections
> > > > + *
> > > > + * 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>
> > > > +#include <linux/export.h>
> > > > +
> > > > +#ifndef __ASSEMBLY__
> > > > +
> > > > +/**
> > > > + * DOC: Introduction
> > > > + *
> > > > + * Linux defines a set of common helpers which can be used to against its use
> > > > + * of standard or custom Linux sections, this section is dedicated to these
> > > > + * helpers.  
> > > 
> > > I'm still not quite sure what a Linux de-facto/standard/common section is
> > > after this. Are they output sections?  
> > 
> > We have ELF standard sections, and we have then sections which Linux has introduced
> > over the years which are now just known to be expected part of Linux, such as init
> > stuff which we free after boot. The combination of the ELF standard sections and
> > series of expected sections in Linux across all architectures is what this refers
> > to as Linux de-facto/standard/common sections. The header file is intended to
> > document these, step by step, and also provide helpers which allow further
> > customizations based on these sections.
> 
> Well but your macros are not linker sections. They are "Linux sections", which
> appear to give you a start and end symbol name, but does not direct the linker
> to create a specific output section.

You're right the above can use some love to help explain this better.

How about:

At the top just use "Linux sections helpers"

Then:

/**
 * DOC: Introduction
 *
 * We document below a dedicated set of helpers used in Linux to make sections
 * defined in the Linux linker script accessible in C code in a generic form and 
 * and provide certain attributes about them.
 */

> I just can't work out what exactly is a
> "custom Linux section", and what DECLARE_LINUX_SECTION(), for example, actaully
> gives you.

Its a way to replace the:

extern char foo[], foo__end[];

So this provides a generalized form to use declarations used in C code to make
the linker script start and end symbols from esctions accessible in C code. Since
DEFINE_SECTION_RANGE() and DEFINE_LINKTABLE() macros use this, then the
DECLARE_LINUX_SECTION() is only needed if you need access to these symbols in C
code outside of the one that is defining and mainly in charge of managing the
section. We provide DECLARE_*() helpers for section ranges and linker tables
though so those can be used instead to help annotate the type of a custom
section they are.

So for instance, since the following tables are used in C code outside
of the code that implemented and manages them:

mcgrof@ergon ~/linux-next (git::20160822-linker-table-v5)$ git grep DECLARE_LINKTA| egrep -v "Documentation|tools|tables"
arch/x86/kernel/cpu/microcode/core.c:DECLARE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
include/linux/dynamic_debug.h:DECLARE_LINKTABLE(struct _ddebug, __verbose);
include/linux/jump_label.h:DECLARE_LINKTABLE(struct jump_entry, __jump_table);
include/linux/kprobes.h:DECLARE_LINKTABLE(unsigned long, _kprobe_blacklist);

Note that the big trick here was to enable users to associate a new custom
section in C to a well defined already existing Linux section without modifying
the Linux linker script. Then, since as we observe and study uses of how Linux
sections are used, we've noticed a pattern -- most declarations of these sections
of really of two types, a section ranges or linker table. The patch set then
provides generic building blocks for these and ports a few existing custom Linux
sections to them as an example.

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-24 20:12             ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-24 20:12 UTC (permalink / raw)
  To: Nicholas Piggin
  Cc: Luis R. Rodriguez, hpa, tglx, mingo, jpoimboe, bp, linux,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, acme, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, paulus, mpe, James.Bottomley

On Wed, Aug 24, 2016 at 01:51:41PM +1000, Nicholas Piggin wrote:
> On Tue, 23 Aug 2016 19:33:06 +0200
> "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> 
> > On Tue, Aug 23, 2016 at 11:26:33AM +1000, Nicholas Piggin wrote:
> > > On Fri, 19 Aug 2016 14:34:02 -0700
> > > mcgrof@kernel.org wrote:  
> > > > +/**
> > > > + * DOC: Standard ELF section use in Linux
> > > > + *
> > > > + * Linux makes use of the standard ELF sections, this sections documents
> > > > + * these.
> > > > + */
> > > > +
> > > > +/**
> > > > + * DOC: SECTION_RODATA
> > > > + *
> > > > + * Macro name for code which must be protected from write access, read only
> > > > + * data.
> > > > + */
> > > > +#define SECTION_RODATA			.rodata  
> > > 
> > > These, for example. The exact name of the section is important in linker
> > > scripts and asm, so I can't see the benefit of hiding it. I could be
> > > missing the bigger picture.  
> > 
> > There's two goals by using a macro for these core names. One is to allow us
> > to easily aggregate documentation in central place for each, the second is
> > to then provide more easily grep'able helpers so we can use them when devising
> > extensions or using them in extensions which further customize the sections
> > in the kernel.

Just thought of more more justification I had forgotten. I cover it below.

> Documentation is good, but not necessary to have the extra name indirection.

Fair point.

> Sections tend (not always, but it would be nice if they did) to follow the
> .name convention, which makes them reasonably easy to grep for.

git grep .text  doesn't work but that is typically expected...
git grep \.text doesn't work as expected

Ah finally:

git grep "\.text" seems to work. But WTF.

But:

git grep SECTION_TEXT works as expected immediately.

I guess its a matter of perspective.

> They are also
> the names you'll be grepping for when you look at disassembly.

Sure but if you're grepping asm, you very likely know what to look for.

> > > > +/**
> > > > + * DOC: SECTION_TEXT
> > > > + *
> > > > + * Macro name used to annotate code (functions) used during regular
> > > > + * kernel run time. This is combined with `SECTION_RODATA`, only this
> > > > + * section also allows for execution.
> > > > + *
> > > > + */
> > > > +#define SECTION_TEXT			.text  
> > > 
> > > I can't see how these comments are right. .rodata doesn't seem like it
> > > should be combined with .text, and is not currently on powerpc. I think
> > > it's for data, not code.  
> > 
> > On x86 and powerpc .rodata follows .text.
> 
> But follows is not the same as combined.

True and as I confirmed below, on PowerPC this is certainly not true.

> And together with the comment that RODATA is for code (which is wrong, it's data),

Where did I have that? If you refer to the above SECTION_TEXT documentation, it
refers to SECTION_TEXT being for code, but the goal was to highlight that
SECTION_TEXT is for execution, while SECTION_RODATA was for data. This
certainly can use some love though, thanks, will just drop the SECTION_RODATA
reference *or* properly explain the whole thing below.

> it make it seem like it is actually combined.

Will fix to ensure this is understood in proper context.

> > On power currently the comment
> > above in .rodata is:
> > 
> > /* Text, read only data and other permanent read-only sections */
> > 
> > When this was introduced however read commit 14cf11af6cf60 ("powerpc: Merge
> > enough to start building in arch/powerpc.")
> > 
> > /* Read-only sections, merged into text segment: */
> > 
> > The format and style of putting rodata after text is kept from the older
> > commits.
> > 
> > This begs the question. What the hell is this thing talking about?
> > 
> > On Linux this is done via mark_rodata_ro() on init/main.c when CONFIG_DEBUG_RODATA
> > on architectures that support it. Architectures that implement this typically use
> > issues set_memory_ro() -- on x86 a start address used is PFN_ALIGN(_text) with
> > an end address of &__end_rodata_hpage_align.
> > 
> > When architectures do not have CONFIG_DEBUG_RODATA() you end up with:
> > 
> > static inline void mark_readonly(void)                                          
> > {                                                                               
> >         pr_warn("This architecture does not have kernel memory protection.\n"); 
> > }
> > 
> > So -- I should I clarify then in Linux we strive to have helpers adjust text and
> > rodata set to ro with memory protection implemented via mark_readonly(). Architectures
> > that do not support memory protection will lack a mark_readonly() implementation.
> 
> Right, I wasn't talking about arch implementation of how the ro
> protection is done, so much as just the comments being a bit misleading.

Sure, got it, thanks, will fix.

> > For now I figured a less controversial introduction to the documentation as
> > bland as it was above in my original patch would suffice, we can then expand on
> > it with something like the above. Thoughts?
> 
> I think comments are one of the key features of this patch series (or at
> least this patch, I've not looked through the others so much yet).

Definitely -- the goal was to give us central place to document some of this
obscure dark magic only a few witches and warlocks tend to be aware of.

> I'm no
> expert on linker stuff, but I think a lot of arch maintainers aren't
> necessarily either so you tend to get a lot of copy and paste without
> always people knowing what exactly is happening.

:) Yes indeed, the little crusade over the PowerPC linker script comments
on .text and ro data is an example of how easily things can be misleading.

> It would be really good
> to have some longer explanations and justifications/examples IMO. So I
> don't think that would be controversial if you wanted to expand on it.

Sure, but what I was trying to say above is I'd rather have the basic
layout of the documentation finalized before we start getting into very
specific detailed elaborate details on some of these things. For instance
we still haven't decided if we wanted SECTION_TEXT or just require everyone
to hard code in .text in every place a user wants to use .text sections.
I'd rather settle that before trying to document mark_readonly().

> > > > +/*
> > > > + * These section _ALL() helpers are for use on linker scripts and helpers
> > > > + */
> > > > +#define SECTION_ALL(__section)						\
> > > > +	__section##.*  
> > > 
> > > This is another example. We know what .text.* does in the linker scripts
> > > -- it's self documenting. But SECTION_ALL(.text)? I'm not sure that's an
> > > improvement. Actually I saw it in the linker script changes and had to
> > > come find the definition because I was a bit mislead:
> > > 
> > > SECTION_ALL(.text)
> > > 
> > > Initially I would expect this to be
> > > 
> > > .text*
> > > 
> > > Not
> > > 
> > > .text.*
> > > 
> > > The latter does not grab the .text section!  
> > 
> > Its not intended to grab .text but rather its for helpers that provide customizations
> > based on a core section as base, in this case given your example it would be used by
> > section ranges and linker tables for .text. Both section ranges and linker tables
> > use postfix .something for their customizations. The SECTION_ALL() macro then is
> > a helper for customizations on a core section.
> 
> Right, it's just that .text.* is *immediately* obvious. SECTION_ALL() is not.

Which is why I was suggesting perhaps an alternative name.

> > If the name is misleading would SECTION_CORE_ALL() be better with some documentation
> > explaining this and the above goal ?
> 
> I don't know... not to be glib, but .section.* would be better and not require
> documentation.

Well consider the issues below for a second... and keep in mind with linker
tables we are about to open the prospect to add more things into the kernel's
sections more easily than before.

> CORE does not really add anything as far as I can see. Other types of .text including
> ones which are automatically generated by the compiler, for better or worse, are
> .text.x sections too.

Actually, sorry, in this case SECTION_ALL() *was* intended for things that are
not linker tables or section ranges, instead this was for globs that want to
use the new section macro names, so we only use this for:
*(SECTION_ALL(SECTION_RODATA)) at this time.  It would seem we just did not
have .text.* and friends (other section names documented here). So this is
more of a reaction to provide a way to use a glob for section names if they
have a macro name.

The idea was to add helpers to do the globbing more easily.

The glob for sections now documented   is SECTION_ALL()
The glob that is range specific        is SECTION_RNG_ALL()
The glob that is linker table specific is SECTION_TBL_ALL()

The only one needing SECTION_ALL() it turns out was .rodata:

-               *(.rodata) *(.rodata.*)                                 \
+               *(SECTION_RODATA) *(SECTION_ALL(SECTION_RODATA))        \

> I would like to see more standardisation of naming convention -- some sections start
> with .., some start with no dots, some use . to separate logical "subsections", others
> use underscores or something else.

Agreed... Actually while at it -- anyone happen to know why the two dot thing
started creeping up?

> I just don't see it would be a problem to simply use the raw names and linker
> wildcards for it.

A concern here is more abuse over this if we now expose APIs to users to
more easily customize sections. So let's review what the chances are.

$ git grep DEFINE_SECTION_RANGE| egrep -v "tools|include|Document"
kernel/kprobes.c:DEFINE_SECTION_RANGE(kprobes, SECTION_TEXT);

These require the actual desired section specified. Do we want
to just hide that ? Or are we OK in assuming users willing to use
proper names here?

For linker tables we actually provide full helpers for each section
type. So we have:

$ git grep DEFINE_LINKTABLE| egrep -v "tools|include|Document"
drivers/base/firmware_class.c:DEFINE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
kernel/jump_label.c:DEFINE_LINKTABLE(struct jump_entry, __jump_table);
kernel/kprobes.c:DEFINE_LINKTABLE_INIT_DATA(unsigned long, _kprobe_blacklist);
lib/dynamic_debug.c:DEFINE_LINKTABLE(struct _ddebug, __verbose);

So for linker tables we're safe from abuse as we provide all direct use
of the section up to the implementation behind the scenes.

If we're happy then with people using a proper section name for section
ranges then I think we can require the full section name being
spelled out.

> > > > +/*
> > > > + * As per gcc's documentation a common asm separator is a new line followed
> > > > + * by tab [0], it however seems possible to also just use a newline as its
> > > > + * the most commonly empirically observed semantic and folks seem to agree
> > > > + * this even works on S390. In case your architecture disagrees you may
> > > > + * override this and define your own and keep the rest of the macros.
> > > > + *
> > > > + * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
> > > > + */
> > > > +# ifndef ASM_CMD_SEP
> > > > +#  define ASM_CMD_SEP	"\n"
> > > > +# endif  
> > > 
> > > This does not seem like it belongs here. The name is fairly ugly too.  
> > 
> > Help me bikeshed, any name suggestions?
> 
> BTW, I'm not trying to bikeshed :) This doesn't affect the value of your
> patch at all, it was just an offhand thing I saw.

Just saying, if you say its ugly please help me with a different name then.

> > > I guess something might be needed like this when dealing with generic
> > > as directives common to all architectures, though.  
> > 
> > Indeed, it actually seems we don't have much in this area, so this is small
> > baby step in that direction.
> > 
> > > I would say include/asm-generic/asm.h should be a better place.  
> > 
> > I thought about this -- I'd be adding a new asm-generic/asm.h -- are folks OK
> > with that right now? Or should we do that as a secondary step ? I preferred to
> > do this as a secondary step as this series is long enough already and there is
> > quite a bit that can be dumped in a common asm-generic/asm.h, a few thoughts
> > on this already:
> > 
> >  o x86's asm/asm.h's use of __ASM_FORM() and include/linux/stringify.h share
> >    some traits which deserve possible consideration / rebranding.
> >  o Since C asm() just wrap things in strings defining a core set of
> >    helpers for a task seems justifiable, so for example we have
> >    __set_section_core_type(). Raw asm code then would use __set_section_core_type()
> >    directly and C asm() would just __stringify() it.
> > 
> > I figured a bit of bikeshedding would be possible here, so I decided to leave
> > this for a later set of patches. But indeed, I agree with you. If we want
> > this meshed out now.. let me know and lets bikeshed away...
> 
> It's fine, I don't mind too much. I think asm-generic/asm.h should be
> fine for generic asm'isms though. Or assembler.h to match compiler.h.

I'd like address this in asm.h but I would hope we can do this as a secondary
step, given the length of this patch set already. Thoughts ?

> 
> > > > diff --git a/include/linux/sections.h b/include/linux/sections.h
> > > > new file mode 100644
> > > > index 000000000000..f21c6ee88ded
> > > > --- /dev/null
> > > > +++ b/include/linux/sections.h
> > > > @@ -0,0 +1,111 @@
> > > > +#ifndef _LINUX_SECTIONS_H
> > > > +#define _LINUX_SECTIONS_H
> > > > +/*
> > > > + * Linux de-facto sections
> > > > + *
> > > > + * 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>
> > > > +#include <linux/export.h>
> > > > +
> > > > +#ifndef __ASSEMBLY__
> > > > +
> > > > +/**
> > > > + * DOC: Introduction
> > > > + *
> > > > + * Linux defines a set of common helpers which can be used to against its use
> > > > + * of standard or custom Linux sections, this section is dedicated to these
> > > > + * helpers.  
> > > 
> > > I'm still not quite sure what a Linux de-facto/standard/common section is
> > > after this. Are they output sections?  
> > 
> > We have ELF standard sections, and we have then sections which Linux has introduced
> > over the years which are now just known to be expected part of Linux, such as init
> > stuff which we free after boot. The combination of the ELF standard sections and
> > series of expected sections in Linux across all architectures is what this refers
> > to as Linux de-facto/standard/common sections. The header file is intended to
> > document these, step by step, and also provide helpers which allow further
> > customizations based on these sections.
> 
> Well but your macros are not linker sections. They are "Linux sections", which
> appear to give you a start and end symbol name, but does not direct the linker
> to create a specific output section.

You're right the above can use some love to help explain this better.

How about:

At the top just use "Linux sections helpers"

Then:

/**
 * DOC: Introduction
 *
 * We document below a dedicated set of helpers used in Linux to make sections
 * defined in the Linux linker script accessible in C code in a generic form and 
 * and provide certain attributes about them.
 */

> I just can't work out what exactly is a
> "custom Linux section", and what DECLARE_LINUX_SECTION(), for example, actaully
> gives you.

Its a way to replace the:

extern char foo[], foo__end[];

So this provides a generalized form to use declarations used in C code to make
the linker script start and end symbols from esctions accessible in C code. Since
DEFINE_SECTION_RANGE() and DEFINE_LINKTABLE() macros use this, then the
DECLARE_LINUX_SECTION() is only needed if you need access to these symbols in C
code outside of the one that is defining and mainly in charge of managing the
section. We provide DECLARE_*() helpers for section ranges and linker tables
though so those can be used instead to help annotate the type of a custom
section they are.

So for instance, since the following tables are used in C code outside
of the code that implemented and manages them:

mcgrof@ergon ~/linux-next (git::20160822-linker-table-v5)$ git grep DECLARE_LINKTA| egrep -v "Documentation|tools|tables"
arch/x86/kernel/cpu/microcode/core.c:DECLARE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
include/linux/dynamic_debug.h:DECLARE_LINKTABLE(struct _ddebug, __verbose);
include/linux/jump_label.h:DECLARE_LINKTABLE(struct jump_entry, __jump_table);
include/linux/kprobes.h:DECLARE_LINKTABLE(unsigned long, _kprobe_blacklist);

Note that the big trick here was to enable users to associate a new custom
section in C to a well defined already existing Linux section without modifying
the Linux linker script. Then, since as we observe and study uses of how Linux
sections are used, we've noticed a pattern -- most declarations of these sections
of really of two types, a section ranges or linker table. The patch set then
provides generic building blocks for these and ports a few existing custom Linux
sections to them as an example.

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
  2016-08-24 20:12             ` Luis R. Rodriguez
  (?)
@ 2016-08-25  2:06               ` Nicholas Piggin
  -1 siblings, 0 replies; 480+ messages in thread
From: Nicholas Piggin @ 2016-08-25  2:06 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, heiko.carstens,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	mpe, hpa, masami.hiramatsu.pt, mchehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, linux, linux-sh,
	will.deacon, korea.drzix, x86, anil.s.keshavamurthy, fontana,
	mingo, linux-arm-kernel, catalin.marinas, dvhart, dwmw2,
	david.vrabel, linux-xtensa, pali.rohar, keescook, arnd

On Wed, 24 Aug 2016 22:12:53 +0200
"Luis R. Rodriguez" <mcgrof@kernel.org> wrote:

> On Wed, Aug 24, 2016 at 01:51:41PM +1000, Nicholas Piggin wrote:
> > On Tue, 23 Aug 2016 19:33:06 +0200
> > "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> >   
> > > On Tue, Aug 23, 2016 at 11:26:33AM +1000, Nicholas Piggin wrote:  
> > > > On Fri, 19 Aug 2016 14:34:02 -0700
> > > > mcgrof@kernel.org wrote:    
> > > > > +/**
> > > > > + * DOC: Standard ELF section use in Linux
> > > > > + *
> > > > > + * Linux makes use of the standard ELF sections, this sections documents
> > > > > + * these.
> > > > > + */
> > > > > +
> > > > > +/**
> > > > > + * DOC: SECTION_RODATA
> > > > > + *
> > > > > + * Macro name for code which must be protected from write access, read only
> > > > > + * data.
> > > > > + */
> > > > > +#define SECTION_RODATA			.rodata    
> > > > 
> > > > These, for example. The exact name of the section is important in linker
> > > > scripts and asm, so I can't see the benefit of hiding it. I could be
> > > > missing the bigger picture.    
> > > 
> > > There's two goals by using a macro for these core names. One is to allow us
> > > to easily aggregate documentation in central place for each, the second is
> > > to then provide more easily grep'able helpers so we can use them when devising
> > > extensions or using them in extensions which further customize the sections
> > > in the kernel.  
> 
> Just thought of more more justification I had forgotten. I cover it below.
> 
> > Documentation is good, but not necessary to have the extra name indirection.  
> 
> Fair point.
> 
> > Sections tend (not always, but it would be nice if they did) to follow the
> > .name convention, which makes them reasonably easy to grep for.  
> 
> git grep .text  doesn't work but that is typically expected...
> git grep \.text doesn't work as expected
> 
> Ah finally:
> 
> git grep "\.text" seems to work. But WTF.

This is simply how grep works though.


> But:
> 
> git grep SECTION_TEXT works as expected immediately.
> 
> I guess its a matter of perspective.
> 
> > They are also
> > the names you'll be grepping for when you look at disassembly.  
> 
> Sure but if you're grepping asm, you very likely know what to look for.

After you have gone through the extra layer of naming indirection
to work out what it is. I'm still not sold on the name indirection
and hiding wildcards. Not just for asm grepping, but I don't think
it's a negative thing for devs working on the linker to know what
actual section names and commands are being used, as much as possible.


> > > > > +/**
> > > > > + * DOC: SECTION_TEXT
> > > > > + *
> > > > > + * Macro name used to annotate code (functions) used during regular
> > > > > + * kernel run time. This is combined with `SECTION_RODATA`, only this
> > > > > + * section also allows for execution.
> > > > > + *
> > > > > + */
> > > > > +#define SECTION_TEXT			.text    
> > > > 
> > > > I can't see how these comments are right. .rodata doesn't seem like it
> > > > should be combined with .text, and is not currently on powerpc. I think
> > > > it's for data, not code.    
> > > 
> > > On x86 and powerpc .rodata follows .text.  
> > 
> > But follows is not the same as combined.  
> 
> True and as I confirmed below, on PowerPC this is certainly not true.

OK.


> > And together with the comment that RODATA is for code (which is wrong, it's data),  
> 
> Where did I have that? If you refer to the above SECTION_TEXT documentation, it
> refers to SECTION_TEXT being for code, but the goal was to highlight that
> SECTION_TEXT is for execution, while SECTION_RODATA was for data. This
> certainly can use some love though, thanks, will just drop the SECTION_RODATA
> reference *or* properly explain the whole thing below.

+/**
+ * DOC: SECTION_RODATA
+ *
+ * Macro name for code which must be protected from write access, read only
+ * data.
+ */
+#define SECTION_RODATA			.rodata

This together with the "combined with .text" part confused me.


> > it make it seem like it is actually combined.  
> 
> Will fix to ensure this is understood in proper context.

Thanks.



> > > Its not intended to grab .text but rather its for helpers that provide customizations
> > > based on a core section as base, in this case given your example it would be used by
> > > section ranges and linker tables for .text. Both section ranges and linker tables
> > > use postfix .something for their customizations. The SECTION_ALL() macro then is
> > > a helper for customizations on a core section.  
> > 
> > Right, it's just that .text.* is *immediately* obvious. SECTION_ALL() is not.  
> 
> Which is why I was suggesting perhaps an alternative name.
> 
> > > If the name is misleading would SECTION_CORE_ALL() be better with some documentation
> > > explaining this and the above goal ?  
> > 
> > I don't know... not to be glib, but .section.* would be better and not require
> > documentation.  
> 
> Well consider the issues below for a second... and keep in mind with linker
> tables we are about to open the prospect to add more things into the kernel's
> sections more easily than before.
> 
> > CORE does not really add anything as far as I can see. Other types of .text including
> > ones which are automatically generated by the compiler, for better or worse, are
> > .text.x sections too.  
> 
> Actually, sorry, in this case SECTION_ALL() *was* intended for things that are
> not linker tables or section ranges, instead this was for globs that want to
> use the new section macro names, so we only use this for:
> *(SECTION_ALL(SECTION_RODATA)) at this time.  It would seem we just did not
> have .text.* and friends (other section names documented here). So this is
> more of a reaction to provide a way to use a glob for section names if they
> have a macro name.
> 
> The idea was to add helpers to do the globbing more easily.
> 
> The glob for sections now documented   is SECTION_ALL()
> The glob that is range specific        is SECTION_RNG_ALL()
> The glob that is linker table specific is SECTION_TBL_ALL()

I still don't see this is better than

.text*
.text.*
.text.range.*
.text.table.*
etc.



> 
> The only one needing SECTION_ALL() it turns out was .rodata:
> 
> -               *(.rodata) *(.rodata.*)                                 \
> +               *(SECTION_RODATA) *(SECTION_ALL(SECTION_RODATA))        \
> 
> > I would like to see more standardisation of naming convention -- some sections start
> > with .., some start with no dots, some use . to separate logical "subsections", others
> > use underscores or something else.  
> 
> Agreed... Actually while at it -- anyone happen to know why the two dot thing
> started creeping up?

I'm not sure, but I suspect it may have been due to . not being a valid C
symbol name. I'm not saying it's always the wrong thing to do, but I think
copy&paste and lack of documentation has left the naming conventions in
need of some love.

The section names themselves of course can and should have some greppable
distinguishing conventions -- we don't need macro name for that.


> > I just don't see it would be a problem to simply use the raw names and linker
> > wildcards for it.  
> 
> A concern here is more abuse over this if we now expose APIs to users to
> more easily customize sections. So let's review what the chances are.
> 
> $ git grep DEFINE_SECTION_RANGE| egrep -v "tools|include|Document"
> kernel/kprobes.c:DEFINE_SECTION_RANGE(kprobes, SECTION_TEXT);
> 
> These require the actual desired section specified. Do we want
> to just hide that ? Or are we OK in assuming users willing to use
> proper names here?

For me, DEFINE_SECTION_RANGE(kprobes, .text) would be fine.


> > BTW, I'm not trying to bikeshed :) This doesn't affect the value of your
> > patch at all, it was just an offhand thing I saw.  
> 
> Just saying, if you say its ugly please help me with a different name then.

Sure, but point taken it's more productive to discuss fundamentals
first. Let's consider exact details afterward.


> > It's fine, I don't mind too much. I think asm-generic/asm.h should be
> > fine for generic asm'isms though. Or assembler.h to match compiler.h.  
> 
> I'd like address this in asm.h but I would hope we can do this as a secondary
> step, given the length of this patch set already. Thoughts ?

It's not a big deal, so whatever suits you. Some of the bugfixes and
cleanups could be pushed through various arch and other maintainers
first too, which would make the core series look more managable and
touch fewer parts.


> > Well but your macros are not linker sections. They are "Linux sections", which
> > appear to give you a start and end symbol name, but does not direct the linker
> > to create a specific output section.  
> 
> You're right the above can use some love to help explain this better.
> 
> How about:
> 
> At the top just use "Linux sections helpers"
> 
> Then:
> 
> /**
>  * DOC: Introduction
>  *
>  * We document below a dedicated set of helpers used in Linux to make sections
>  * defined in the Linux linker script accessible in C code in a generic form and 
>  * and provide certain attributes about them.
>  */
> 
> > I just can't work out what exactly is a
> > "custom Linux section", and what DECLARE_LINUX_SECTION(), for example, actaully
> > gives you.  
> 
> Its a way to replace the:
> 
> extern char foo[], foo__end[];
> 
> So this provides a generalized form to use declarations used in C code to make
> the linker script start and end symbols from esctions accessible in C code. Since
> DEFINE_SECTION_RANGE() and DEFINE_LINKTABLE() macros use this, then the
> DECLARE_LINUX_SECTION() is only needed if you need access to these symbols in C
> code outside of the one that is defining and mainly in charge of managing the
> section. We provide DECLARE_*() helpers for section ranges and linker tables
> though so those can be used instead to help annotate the type of a custom
> section they are.

Oh, that makes more sense. The SECTION stuff and custom sections was
confusing me. I would prefer just to drop all the LINUX_SECTION naming
and make it match the functionality you're using. For example:

+DEFINE_LINKTABLE(struct jump_entry, __jump_table);
+
 /* mutex to protect coming/going of the the jump_label table */
 static DEFINE_MUTEX(jump_label_mutex);
 
@@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
 
 void __init jump_label_init(void)
 {
-	struct jump_entry *iter_start = __start___jump_table;
-	struct jump_entry *iter_stop = __stop___jump_table;
 	struct static_key *key = NULL;
 	struct jump_entry *iter;
 
@@ -292,9 +293,10 @@ void __init jump_label_init(void)
 		return;
 
 	jump_label_lock();
-	jump_label_sort_entries(iter_start, iter_stop);
+	jump_label_sort_entries(LINUX_SECTION_START(__jump_table),
+				LINUX_SECTION_END(__jump_table));

Now I think this is a fine abstraction to have. I think it would look
even cleaner if you had:

LINKTABLE_START(__jump_table)
LINKTABLE_END(__jump_table)

Then do we need to even have the LINUX_SECTION middle man at all?

Thanks,
Nick

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-25  2:06               ` Nicholas Piggin
  0 siblings, 0 replies; 480+ messages in thread
From: Nicholas Piggin @ 2016-08-25  2:06 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, heiko.carstens,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	mpe, hpa, masami.hiramatsu.pt, mchehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, linux, linux-sh,
	will.deacon, korea.drzix, x86, anil.s.keshavamurthy, fontana,
	mingo, linux-arm-kernel, catalin.marinas, dvhart, dwmw2,
	david.vrabel, linux-xtensa, pali.rohar, keescook, arnd

On Wed, 24 Aug 2016 22:12:53 +0200
"Luis R. Rodriguez" <mcgrof@kernel.org> wrote:

> On Wed, Aug 24, 2016 at 01:51:41PM +1000, Nicholas Piggin wrote:
> > On Tue, 23 Aug 2016 19:33:06 +0200
> > "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> >   
> > > On Tue, Aug 23, 2016 at 11:26:33AM +1000, Nicholas Piggin wrote:  
> > > > On Fri, 19 Aug 2016 14:34:02 -0700
> > > > mcgrof@kernel.org wrote:    
> > > > > +/**
> > > > > + * DOC: Standard ELF section use in Linux
> > > > > + *
> > > > > + * Linux makes use of the standard ELF sections, this sections documents
> > > > > + * these.
> > > > > + */
> > > > > +
> > > > > +/**
> > > > > + * DOC: SECTION_RODATA
> > > > > + *
> > > > > + * Macro name for code which must be protected from write access, read only
> > > > > + * data.
> > > > > + */
> > > > > +#define SECTION_RODATA			.rodata    
> > > > 
> > > > These, for example. The exact name of the section is important in linker
> > > > scripts and asm, so I can't see the benefit of hiding it. I could be
> > > > missing the bigger picture.    
> > > 
> > > There's two goals by using a macro for these core names. One is to allow us
> > > to easily aggregate documentation in central place for each, the second is
> > > to then provide more easily grep'able helpers so we can use them when devising
> > > extensions or using them in extensions which further customize the sections
> > > in the kernel.  
> 
> Just thought of more more justification I had forgotten. I cover it below.
> 
> > Documentation is good, but not necessary to have the extra name indirection.  
> 
> Fair point.
> 
> > Sections tend (not always, but it would be nice if they did) to follow the
> > .name convention, which makes them reasonably easy to grep for.  
> 
> git grep .text  doesn't work but that is typically expected...
> git grep \.text doesn't work as expected
> 
> Ah finally:
> 
> git grep "\.text" seems to work. But WTF.

This is simply how grep works though.


> But:
> 
> git grep SECTION_TEXT works as expected immediately.
> 
> I guess its a matter of perspective.
> 
> > They are also
> > the names you'll be grepping for when you look at disassembly.  
> 
> Sure but if you're grepping asm, you very likely know what to look for.

After you have gone through the extra layer of naming indirection
to work out what it is. I'm still not sold on the name indirection
and hiding wildcards. Not just for asm grepping, but I don't think
it's a negative thing for devs working on the linker to know what
actual section names and commands are being used, as much as possible.


> > > > > +/**
> > > > > + * DOC: SECTION_TEXT
> > > > > + *
> > > > > + * Macro name used to annotate code (functions) used during regular
> > > > > + * kernel run time. This is combined with `SECTION_RODATA`, only this
> > > > > + * section also allows for execution.
> > > > > + *
> > > > > + */
> > > > > +#define SECTION_TEXT			.text    
> > > > 
> > > > I can't see how these comments are right. .rodata doesn't seem like it
> > > > should be combined with .text, and is not currently on powerpc. I think
> > > > it's for data, not code.    
> > > 
> > > On x86 and powerpc .rodata follows .text.  
> > 
> > But follows is not the same as combined.  
> 
> True and as I confirmed below, on PowerPC this is certainly not true.

OK.


> > And together with the comment that RODATA is for code (which is wrong, it's data),  
> 
> Where did I have that? If you refer to the above SECTION_TEXT documentation, it
> refers to SECTION_TEXT being for code, but the goal was to highlight that
> SECTION_TEXT is for execution, while SECTION_RODATA was for data. This
> certainly can use some love though, thanks, will just drop the SECTION_RODATA
> reference *or* properly explain the whole thing below.

+/**
+ * DOC: SECTION_RODATA
+ *
+ * Macro name for code which must be protected from write access, read only
+ * data.
+ */
+#define SECTION_RODATA			.rodata

This together with the "combined with .text" part confused me.


> > it make it seem like it is actually combined.  
> 
> Will fix to ensure this is understood in proper context.

Thanks.



> > > Its not intended to grab .text but rather its for helpers that provide customizations
> > > based on a core section as base, in this case given your example it would be used by
> > > section ranges and linker tables for .text. Both section ranges and linker tables
> > > use postfix .something for their customizations. The SECTION_ALL() macro then is
> > > a helper for customizations on a core section.  
> > 
> > Right, it's just that .text.* is *immediately* obvious. SECTION_ALL() is not.  
> 
> Which is why I was suggesting perhaps an alternative name.
> 
> > > If the name is misleading would SECTION_CORE_ALL() be better with some documentation
> > > explaining this and the above goal ?  
> > 
> > I don't know... not to be glib, but .section.* would be better and not require
> > documentation.  
> 
> Well consider the issues below for a second... and keep in mind with linker
> tables we are about to open the prospect to add more things into the kernel's
> sections more easily than before.
> 
> > CORE does not really add anything as far as I can see. Other types of .text including
> > ones which are automatically generated by the compiler, for better or worse, are
> > .text.x sections too.  
> 
> Actually, sorry, in this case SECTION_ALL() *was* intended for things that are
> not linker tables or section ranges, instead this was for globs that want to
> use the new section macro names, so we only use this for:
> *(SECTION_ALL(SECTION_RODATA)) at this time.  It would seem we just did not
> have .text.* and friends (other section names documented here). So this is
> more of a reaction to provide a way to use a glob for section names if they
> have a macro name.
> 
> The idea was to add helpers to do the globbing more easily.
> 
> The glob for sections now documented   is SECTION_ALL()
> The glob that is range specific        is SECTION_RNG_ALL()
> The glob that is linker table specific is SECTION_TBL_ALL()

I still don't see this is better than

.text*
.text.*
.text.range.*
.text.table.*
etc.



> 
> The only one needing SECTION_ALL() it turns out was .rodata:
> 
> -               *(.rodata) *(.rodata.*)                                 \
> +               *(SECTION_RODATA) *(SECTION_ALL(SECTION_RODATA))        \
> 
> > I would like to see more standardisation of naming convention -- some sections start
> > with .., some start with no dots, some use . to separate logical "subsections", others
> > use underscores or something else.  
> 
> Agreed... Actually while at it -- anyone happen to know why the two dot thing
> started creeping up?

I'm not sure, but I suspect it may have been due to . not being a valid C
symbol name. I'm not saying it's always the wrong thing to do, but I think
copy&paste and lack of documentation has left the naming conventions in
need of some love.

The section names themselves of course can and should have some greppable
distinguishing conventions -- we don't need macro name for that.


> > I just don't see it would be a problem to simply use the raw names and linker
> > wildcards for it.  
> 
> A concern here is more abuse over this if we now expose APIs to users to
> more easily customize sections. So let's review what the chances are.
> 
> $ git grep DEFINE_SECTION_RANGE| egrep -v "tools|include|Document"
> kernel/kprobes.c:DEFINE_SECTION_RANGE(kprobes, SECTION_TEXT);
> 
> These require the actual desired section specified. Do we want
> to just hide that ? Or are we OK in assuming users willing to use
> proper names here?

For me, DEFINE_SECTION_RANGE(kprobes, .text) would be fine.


> > BTW, I'm not trying to bikeshed :) This doesn't affect the value of your
> > patch at all, it was just an offhand thing I saw.  
> 
> Just saying, if you say its ugly please help me with a different name then.

Sure, but point taken it's more productive to discuss fundamentals
first. Let's consider exact details afterward.


> > It's fine, I don't mind too much. I think asm-generic/asm.h should be
> > fine for generic asm'isms though. Or assembler.h to match compiler.h.  
> 
> I'd like address this in asm.h but I would hope we can do this as a secondary
> step, given the length of this patch set already. Thoughts ?

It's not a big deal, so whatever suits you. Some of the bugfixes and
cleanups could be pushed through various arch and other maintainers
first too, which would make the core series look more managable and
touch fewer parts.


> > Well but your macros are not linker sections. They are "Linux sections", which
> > appear to give you a start and end symbol name, but does not direct the linker
> > to create a specific output section.  
> 
> You're right the above can use some love to help explain this better.
> 
> How about:
> 
> At the top just use "Linux sections helpers"
> 
> Then:
> 
> /**
>  * DOC: Introduction
>  *
>  * We document below a dedicated set of helpers used in Linux to make sections
>  * defined in the Linux linker script accessible in C code in a generic form and 
>  * and provide certain attributes about them.
>  */
> 
> > I just can't work out what exactly is a
> > "custom Linux section", and what DECLARE_LINUX_SECTION(), for example, actaully
> > gives you.  
> 
> Its a way to replace the:
> 
> extern char foo[], foo__end[];
> 
> So this provides a generalized form to use declarations used in C code to make
> the linker script start and end symbols from esctions accessible in C code. Since
> DEFINE_SECTION_RANGE() and DEFINE_LINKTABLE() macros use this, then the
> DECLARE_LINUX_SECTION() is only needed if you need access to these symbols in C
> code outside of the one that is defining and mainly in charge of managing the
> section. We provide DECLARE_*() helpers for section ranges and linker tables
> though so those can be used instead to help annotate the type of a custom
> section they are.

Oh, that makes more sense. The SECTION stuff and custom sections was
confusing me. I would prefer just to drop all the LINUX_SECTION naming
and make it match the functionality you're using. For example:

+DEFINE_LINKTABLE(struct jump_entry, __jump_table);
+
 /* mutex to protect coming/going of the the jump_label table */
 static DEFINE_MUTEX(jump_label_mutex);
 
@@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
 
 void __init jump_label_init(void)
 {
-	struct jump_entry *iter_start = __start___jump_table;
-	struct jump_entry *iter_stop = __stop___jump_table;
 	struct static_key *key = NULL;
 	struct jump_entry *iter;
 
@@ -292,9 +293,10 @@ void __init jump_label_init(void)
 		return;
 
 	jump_label_lock();
-	jump_label_sort_entries(iter_start, iter_stop);
+	jump_label_sort_entries(LINUX_SECTION_START(__jump_table),
+				LINUX_SECTION_END(__jump_table));

Now I think this is a fine abstraction to have. I think it would look
even cleaner if you had:

LINKTABLE_START(__jump_table)
LINKTABLE_END(__jump_table)

Then do we need to even have the LINUX_SECTION middle man at all?

Thanks,
Nick

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-25  2:06               ` Nicholas Piggin
  0 siblings, 0 replies; 480+ messages in thread
From: Nicholas Piggin @ 2016-08-25  2:06 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, acme, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, paulus, mpe, James.Bottomley

On Wed, 24 Aug 2016 22:12:53 +0200
"Luis R. Rodriguez" <mcgrof@kernel.org> wrote:

> On Wed, Aug 24, 2016 at 01:51:41PM +1000, Nicholas Piggin wrote:
> > On Tue, 23 Aug 2016 19:33:06 +0200
> > "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> >   
> > > On Tue, Aug 23, 2016 at 11:26:33AM +1000, Nicholas Piggin wrote:  
> > > > On Fri, 19 Aug 2016 14:34:02 -0700
> > > > mcgrof@kernel.org wrote:    
> > > > > +/**
> > > > > + * DOC: Standard ELF section use in Linux
> > > > > + *
> > > > > + * Linux makes use of the standard ELF sections, this sections documents
> > > > > + * these.
> > > > > + */
> > > > > +
> > > > > +/**
> > > > > + * DOC: SECTION_RODATA
> > > > > + *
> > > > > + * Macro name for code which must be protected from write access, read only
> > > > > + * data.
> > > > > + */
> > > > > +#define SECTION_RODATA			.rodata    
> > > > 
> > > > These, for example. The exact name of the section is important in linker
> > > > scripts and asm, so I can't see the benefit of hiding it. I could be
> > > > missing the bigger picture.    
> > > 
> > > There's two goals by using a macro for these core names. One is to allow us
> > > to easily aggregate documentation in central place for each, the second is
> > > to then provide more easily grep'able helpers so we can use them when devising
> > > extensions or using them in extensions which further customize the sections
> > > in the kernel.  
> 
> Just thought of more more justification I had forgotten. I cover it below.
> 
> > Documentation is good, but not necessary to have the extra name indirection.  
> 
> Fair point.
> 
> > Sections tend (not always, but it would be nice if they did) to follow the
> > .name convention, which makes them reasonably easy to grep for.  
> 
> git grep .text  doesn't work but that is typically expected...
> git grep \.text doesn't work as expected
> 
> Ah finally:
> 
> git grep "\.text" seems to work. But WTF.

This is simply how grep works though.


> But:
> 
> git grep SECTION_TEXT works as expected immediately.
> 
> I guess its a matter of perspective.
> 
> > They are also
> > the names you'll be grepping for when you look at disassembly.  
> 
> Sure but if you're grepping asm, you very likely know what to look for.

After you have gone through the extra layer of naming indirection
to work out what it is. I'm still not sold on the name indirection
and hiding wildcards. Not just for asm grepping, but I don't think
it's a negative thing for devs working on the linker to know what
actual section names and commands are being used, as much as possible.


> > > > > +/**
> > > > > + * DOC: SECTION_TEXT
> > > > > + *
> > > > > + * Macro name used to annotate code (functions) used during regular
> > > > > + * kernel run time. This is combined with `SECTION_RODATA`, only this
> > > > > + * section also allows for execution.
> > > > > + *
> > > > > + */
> > > > > +#define SECTION_TEXT			.text    
> > > > 
> > > > I can't see how these comments are right. .rodata doesn't seem like it
> > > > should be combined with .text, and is not currently on powerpc. I think
> > > > it's for data, not code.    
> > > 
> > > On x86 and powerpc .rodata follows .text.  
> > 
> > But follows is not the same as combined.  
> 
> True and as I confirmed below, on PowerPC this is certainly not true.

OK.


> > And together with the comment that RODATA is for code (which is wrong, it's data),  
> 
> Where did I have that? If you refer to the above SECTION_TEXT documentation, it
> refers to SECTION_TEXT being for code, but the goal was to highlight that
> SECTION_TEXT is for execution, while SECTION_RODATA was for data. This
> certainly can use some love though, thanks, will just drop the SECTION_RODATA
> reference *or* properly explain the whole thing below.

+/**
+ * DOC: SECTION_RODATA
+ *
+ * Macro name for code which must be protected from write access, read only
+ * data.
+ */
+#define SECTION_RODATA			.rodata

This together with the "combined with .text" part confused me.


> > it make it seem like it is actually combined.  
> 
> Will fix to ensure this is understood in proper context.

Thanks.



> > > Its not intended to grab .text but rather its for helpers that provide customizations
> > > based on a core section as base, in this case given your example it would be used by
> > > section ranges and linker tables for .text. Both section ranges and linker tables
> > > use postfix .something for their customizations. The SECTION_ALL() macro then is
> > > a helper for customizations on a core section.  
> > 
> > Right, it's just that .text.* is *immediately* obvious. SECTION_ALL() is not.  
> 
> Which is why I was suggesting perhaps an alternative name.
> 
> > > If the name is misleading would SECTION_CORE_ALL() be better with some documentation
> > > explaining this and the above goal ?  
> > 
> > I don't know... not to be glib, but .section.* would be better and not require
> > documentation.  
> 
> Well consider the issues below for a second... and keep in mind with linker
> tables we are about to open the prospect to add more things into the kernel's
> sections more easily than before.
> 
> > CORE does not really add anything as far as I can see. Other types of .text including
> > ones which are automatically generated by the compiler, for better or worse, are
> > .text.x sections too.  
> 
> Actually, sorry, in this case SECTION_ALL() *was* intended for things that are
> not linker tables or section ranges, instead this was for globs that want to
> use the new section macro names, so we only use this for:
> *(SECTION_ALL(SECTION_RODATA)) at this time.  It would seem we just did not
> have .text.* and friends (other section names documented here). So this is
> more of a reaction to provide a way to use a glob for section names if they
> have a macro name.
> 
> The idea was to add helpers to do the globbing more easily.
> 
> The glob for sections now documented   is SECTION_ALL()
> The glob that is range specific        is SECTION_RNG_ALL()
> The glob that is linker table specific is SECTION_TBL_ALL()

I still don't see this is better than

.text*
.text.*
.text.range.*
.text.table.*
etc.



> 
> The only one needing SECTION_ALL() it turns out was .rodata:
> 
> -               *(.rodata) *(.rodata.*)                                 \
> +               *(SECTION_RODATA) *(SECTION_ALL(SECTION_RODATA))        \
> 
> > I would like to see more standardisation of naming convention -- some sections start
> > with .., some start with no dots, some use . to separate logical "subsections", others
> > use underscores or something else.  
> 
> Agreed... Actually while at it -- anyone happen to know why the two dot thing
> started creeping up?

I'm not sure, but I suspect it may have been due to . not being a valid C
symbol name. I'm not saying it's always the wrong thing to do, but I think
copy&paste and lack of documentation has left the naming conventions in
need of some love.

The section names themselves of course can and should have some greppable
distinguishing conventions -- we don't need macro name for that.


> > I just don't see it would be a problem to simply use the raw names and linker
> > wildcards for it.  
> 
> A concern here is more abuse over this if we now expose APIs to users to
> more easily customize sections. So let's review what the chances are.
> 
> $ git grep DEFINE_SECTION_RANGE| egrep -v "tools|include|Document"
> kernel/kprobes.c:DEFINE_SECTION_RANGE(kprobes, SECTION_TEXT);
> 
> These require the actual desired section specified. Do we want
> to just hide that ? Or are we OK in assuming users willing to use
> proper names here?

For me, DEFINE_SECTION_RANGE(kprobes, .text) would be fine.


> > BTW, I'm not trying to bikeshed :) This doesn't affect the value of your
> > patch at all, it was just an offhand thing I saw.  
> 
> Just saying, if you say its ugly please help me with a different name then.

Sure, but point taken it's more productive to discuss fundamentals
first. Let's consider exact details afterward.


> > It's fine, I don't mind too much. I think asm-generic/asm.h should be
> > fine for generic asm'isms though. Or assembler.h to match compiler.h.  
> 
> I'd like address this in asm.h but I would hope we can do this as a secondary
> step, given the length of this patch set already. Thoughts ?

It's not a big deal, so whatever suits you. Some of the bugfixes and
cleanups could be pushed through various arch and other maintainers
first too, which would make the core series look more managable and
touch fewer parts.


> > Well but your macros are not linker sections. They are "Linux sections", which
> > appear to give you a start and end symbol name, but does not direct the linker
> > to create a specific output section.  
> 
> You're right the above can use some love to help explain this better.
> 
> How about:
> 
> At the top just use "Linux sections helpers"
> 
> Then:
> 
> /**
>  * DOC: Introduction
>  *
>  * We document below a dedicated set of helpers used in Linux to make sections
>  * defined in the Linux linker script accessible in C code in a generic form and 
>  * and provide certain attributes about them.
>  */
> 
> > I just can't work out what exactly is a
> > "custom Linux section", and what DECLARE_LINUX_SECTION(), for example, actaully
> > gives you.  
> 
> Its a way to replace the:
> 
> extern char foo[], foo__end[];
> 
> So this provides a generalized form to use declarations used in C code to make
> the linker script start and end symbols from esctions accessible in C code. Since
> DEFINE_SECTION_RANGE() and DEFINE_LINKTABLE() macros use this, then the
> DECLARE_LINUX_SECTION() is only needed if you need access to these symbols in C
> code outside of the one that is defining and mainly in charge of managing the
> section. We provide DECLARE_*() helpers for section ranges and linker tables
> though so those can be used instead to help annotate the type of a custom
> section they are.

Oh, that makes more sense. The SECTION stuff and custom sections was
confusing me. I would prefer just to drop all the LINUX_SECTION naming
and make it match the functionality you're using. For example:

+DEFINE_LINKTABLE(struct jump_entry, __jump_table);
+
 /* mutex to protect coming/going of the the jump_label table */
 static DEFINE_MUTEX(jump_label_mutex);
 
@@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
 
 void __init jump_label_init(void)
 {
-	struct jump_entry *iter_start = __start___jump_table;
-	struct jump_entry *iter_stop = __stop___jump_table;
 	struct static_key *key = NULL;
 	struct jump_entry *iter;
 
@@ -292,9 +293,10 @@ void __init jump_label_init(void)
 		return;
 
 	jump_label_lock();
-	jump_label_sort_entries(iter_start, iter_stop);
+	jump_label_sort_entries(LINUX_SECTION_START(__jump_table),
+				LINUX_SECTION_END(__jump_table));

Now I think this is a fine abstraction to have. I think it would look
even cleaner if you had:

LINKTABLE_START(__jump_table)
LINKTABLE_END(__jump_table)

Then do we need to even have the LINUX_SECTION middle man at all?

Thanks,
Nick

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
  2016-08-25  2:06               ` Nicholas Piggin
  (?)
@ 2016-08-25  6:05                 ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-25  6:05 UTC (permalink / raw)
  To: Nicholas Piggin
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, heiko.carstens,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	mpe, hpa, masami.hiramatsu.pt, mchehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, linux, linux-sh,
	will.deacon, korea.drzix, x86, anil.s.keshavamurthy, fontana,
	mingo, linux-arm-kernel, catalin.marinas, dvhart, dwmw2,
	david.vrabel, linux-xtensa, pali.rohar, keescook, arnd

On Thu, Aug 25, 2016 at 12:06:33PM +1000, Nicholas Piggin wrote:
> On Wed, 24 Aug 2016 22:12:53 +0200
> "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> > But:
> > 
> > git grep SECTION_TEXT works as expected immediately.
> > 
> > I guess its a matter of perspective.
> > 
> > > They are also
> > > the names you'll be grepping for when you look at disassembly.  
> > 
> > Sure but if you're grepping asm, you very likely know what to look for.
> 
> After you have gone through the extra layer of naming indirection
> to work out what it is. I'm still not sold on the name indirection
> and hiding wildcards. Not just for asm grepping, but I don't think
> it's a negative thing for devs working on the linker to know what
> actual section names and commands are being used, as much as possible.

OK lets see what it looks like after dropping them. Will try that.

> > The idea was to add helpers to do the globbing more easily.
> > 
> > The glob for sections now documented   is SECTION_ALL()
> > The glob that is range specific        is SECTION_RNG_ALL()
> > The glob that is linker table specific is SECTION_TBL_ALL()
> 
> I still don't see this is better than
> 
> .text*
> .text.*
> .text.range.*
> .text.table.*
> etc.

OK will drop it.

> > How about:
> > 
> > At the top just use "Linux sections helpers"
> > 
> > Then:
> > 
> > /**
> >  * DOC: Introduction
> >  *
> >  * We document below a dedicated set of helpers used in Linux to make sections
> >  * defined in the Linux linker script accessible in C code in a generic form and 
> >  * and provide certain attributes about them.
> >  */
> > 
> > > I just can't work out what exactly is a
> > > "custom Linux section", and what DECLARE_LINUX_SECTION(), for example, actaully
> > > gives you.  
> > 
> > Its a way to replace the:
> > 
> > extern char foo[], foo__end[];
> > 
> > So this provides a generalized form to use declarations used in C code to make
> > the linker script start and end symbols from esctions accessible in C code. Since
> > DEFINE_SECTION_RANGE() and DEFINE_LINKTABLE() macros use this, then the
> > DECLARE_LINUX_SECTION() is only needed if you need access to these symbols in C
> > code outside of the one that is defining and mainly in charge of managing the
> > section. We provide DECLARE_*() helpers for section ranges and linker tables
> > though so those can be used instead to help annotate the type of a custom
> > section they are.
> 
> Oh, that makes more sense. The SECTION stuff and custom sections was
> confusing me. I would prefer just to drop all the LINUX_SECTION naming
> and make it match the functionality you're using. For example:
> 
> +DEFINE_LINKTABLE(struct jump_entry, __jump_table);
> +
>  /* mutex to protect coming/going of the the jump_label table */
>  static DEFINE_MUTEX(jump_label_mutex);
>  
> @@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
>  
>  void __init jump_label_init(void)
>  {
> -	struct jump_entry *iter_start = __start___jump_table;
> -	struct jump_entry *iter_stop = __stop___jump_table;
>  	struct static_key *key = NULL;
>  	struct jump_entry *iter;
>  
> @@ -292,9 +293,10 @@ void __init jump_label_init(void)
>  		return;
>  
>  	jump_label_lock();
> -	jump_label_sort_entries(iter_start, iter_stop);
> +	jump_label_sort_entries(LINUX_SECTION_START(__jump_table),
> +				LINUX_SECTION_END(__jump_table));
> 
> Now I think this is a fine abstraction to have.

OK will keep this one.

> I think it would look
> even cleaner if you had:
> 
> LINKTABLE_START(__jump_table)
> LINKTABLE_END(__jump_table)
>
> Then do we need to even have the LINUX_SECTION middle man at all?

Ah, thing is we use this for both linktables and section ranges.
Or do we want macros for both that do the same thing ?

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-25  6:05                 ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-25  6:05 UTC (permalink / raw)
  To: Nicholas Piggin
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, heiko.carstens,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	mpe, hpa, masami.hiramatsu.pt, mchehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, linux, linux-sh,
	will.deacon, korea.drzix, x86, anil.s.keshavamurthy, fontana,
	mingo, linux-arm-kernel, catalin.marinas, dvhart, dwmw2,
	david.vrabel, linux-xtensa, pali.rohar, keescook, arnd

On Thu, Aug 25, 2016 at 12:06:33PM +1000, Nicholas Piggin wrote:
> On Wed, 24 Aug 2016 22:12:53 +0200
> "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> > But:
> > 
> > git grep SECTION_TEXT works as expected immediately.
> > 
> > I guess its a matter of perspective.
> > 
> > > They are also
> > > the names you'll be grepping for when you look at disassembly.  
> > 
> > Sure but if you're grepping asm, you very likely know what to look for.
> 
> After you have gone through the extra layer of naming indirection
> to work out what it is. I'm still not sold on the name indirection
> and hiding wildcards. Not just for asm grepping, but I don't think
> it's a negative thing for devs working on the linker to know what
> actual section names and commands are being used, as much as possible.

OK lets see what it looks like after dropping them. Will try that.

> > The idea was to add helpers to do the globbing more easily.
> > 
> > The glob for sections now documented   is SECTION_ALL()
> > The glob that is range specific        is SECTION_RNG_ALL()
> > The glob that is linker table specific is SECTION_TBL_ALL()
> 
> I still don't see this is better than
> 
> .text*
> .text.*
> .text.range.*
> .text.table.*
> etc.

OK will drop it.

> > How about:
> > 
> > At the top just use "Linux sections helpers"
> > 
> > Then:
> > 
> > /**
> >  * DOC: Introduction
> >  *
> >  * We document below a dedicated set of helpers used in Linux to make sections
> >  * defined in the Linux linker script accessible in C code in a generic form and 
> >  * and provide certain attributes about them.
> >  */
> > 
> > > I just can't work out what exactly is a
> > > "custom Linux section", and what DECLARE_LINUX_SECTION(), for example, actaully
> > > gives you.  
> > 
> > Its a way to replace the:
> > 
> > extern char foo[], foo__end[];
> > 
> > So this provides a generalized form to use declarations used in C code to make
> > the linker script start and end symbols from esctions accessible in C code. Since
> > DEFINE_SECTION_RANGE() and DEFINE_LINKTABLE() macros use this, then the
> > DECLARE_LINUX_SECTION() is only needed if you need access to these symbols in C
> > code outside of the one that is defining and mainly in charge of managing the
> > section. We provide DECLARE_*() helpers for section ranges and linker tables
> > though so those can be used instead to help annotate the type of a custom
> > section they are.
> 
> Oh, that makes more sense. The SECTION stuff and custom sections was
> confusing me. I would prefer just to drop all the LINUX_SECTION naming
> and make it match the functionality you're using. For example:
> 
> +DEFINE_LINKTABLE(struct jump_entry, __jump_table);
> +
>  /* mutex to protect coming/going of the the jump_label table */
>  static DEFINE_MUTEX(jump_label_mutex);
>  
> @@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
>  
>  void __init jump_label_init(void)
>  {
> -	struct jump_entry *iter_start = __start___jump_table;
> -	struct jump_entry *iter_stop = __stop___jump_table;
>  	struct static_key *key = NULL;
>  	struct jump_entry *iter;
>  
> @@ -292,9 +293,10 @@ void __init jump_label_init(void)
>  		return;
>  
>  	jump_label_lock();
> -	jump_label_sort_entries(iter_start, iter_stop);
> +	jump_label_sort_entries(LINUX_SECTION_START(__jump_table),
> +				LINUX_SECTION_END(__jump_table));
> 
> Now I think this is a fine abstraction to have.

OK will keep this one.

> I think it would look
> even cleaner if you had:
> 
> LINKTABLE_START(__jump_table)
> LINKTABLE_END(__jump_table)
>
> Then do we need to even have the LINUX_SECTION middle man at all?

Ah, thing is we use this for both linktables and section ranges.
Or do we want macros for both that do the same thing ?

  Luis

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-25  6:05                 ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-25  6:05 UTC (permalink / raw)
  To: Nicholas Piggin
  Cc: Luis R. Rodriguez, hpa, tglx, mingo, jpoimboe, bp, linux,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, acme, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, paulus, mpe, James.Bottomley

On Thu, Aug 25, 2016 at 12:06:33PM +1000, Nicholas Piggin wrote:
> On Wed, 24 Aug 2016 22:12:53 +0200
> "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> > But:
> > 
> > git grep SECTION_TEXT works as expected immediately.
> > 
> > I guess its a matter of perspective.
> > 
> > > They are also
> > > the names you'll be grepping for when you look at disassembly.  
> > 
> > Sure but if you're grepping asm, you very likely know what to look for.
> 
> After you have gone through the extra layer of naming indirection
> to work out what it is. I'm still not sold on the name indirection
> and hiding wildcards. Not just for asm grepping, but I don't think
> it's a negative thing for devs working on the linker to know what
> actual section names and commands are being used, as much as possible.

OK lets see what it looks like after dropping them. Will try that.

> > The idea was to add helpers to do the globbing more easily.
> > 
> > The glob for sections now documented   is SECTION_ALL()
> > The glob that is range specific        is SECTION_RNG_ALL()
> > The glob that is linker table specific is SECTION_TBL_ALL()
> 
> I still don't see this is better than
> 
> .text*
> .text.*
> .text.range.*
> .text.table.*
> etc.

OK will drop it.

> > How about:
> > 
> > At the top just use "Linux sections helpers"
> > 
> > Then:
> > 
> > /**
> >  * DOC: Introduction
> >  *
> >  * We document below a dedicated set of helpers used in Linux to make sections
> >  * defined in the Linux linker script accessible in C code in a generic form and 
> >  * and provide certain attributes about them.
> >  */
> > 
> > > I just can't work out what exactly is a
> > > "custom Linux section", and what DECLARE_LINUX_SECTION(), for example, actaully
> > > gives you.  
> > 
> > Its a way to replace the:
> > 
> > extern char foo[], foo__end[];
> > 
> > So this provides a generalized form to use declarations used in C code to make
> > the linker script start and end symbols from esctions accessible in C code. Since
> > DEFINE_SECTION_RANGE() and DEFINE_LINKTABLE() macros use this, then the
> > DECLARE_LINUX_SECTION() is only needed if you need access to these symbols in C
> > code outside of the one that is defining and mainly in charge of managing the
> > section. We provide DECLARE_*() helpers for section ranges and linker tables
> > though so those can be used instead to help annotate the type of a custom
> > section they are.
> 
> Oh, that makes more sense. The SECTION stuff and custom sections was
> confusing me. I would prefer just to drop all the LINUX_SECTION naming
> and make it match the functionality you're using. For example:
> 
> +DEFINE_LINKTABLE(struct jump_entry, __jump_table);
> +
>  /* mutex to protect coming/going of the the jump_label table */
>  static DEFINE_MUTEX(jump_label_mutex);
>  
> @@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
>  
>  void __init jump_label_init(void)
>  {
> -	struct jump_entry *iter_start = __start___jump_table;
> -	struct jump_entry *iter_stop = __stop___jump_table;
>  	struct static_key *key = NULL;
>  	struct jump_entry *iter;
>  
> @@ -292,9 +293,10 @@ void __init jump_label_init(void)
>  		return;
>  
>  	jump_label_lock();
> -	jump_label_sort_entries(iter_start, iter_stop);
> +	jump_label_sort_entries(LINUX_SECTION_START(__jump_table),
> +				LINUX_SECTION_END(__jump_table));
> 
> Now I think this is a fine abstraction to have.

OK will keep this one.

> I think it would look
> even cleaner if you had:
> 
> LINKTABLE_START(__jump_table)
> LINKTABLE_END(__jump_table)
>
> Then do we need to even have the LINUX_SECTION middle man at all?

Ah, thing is we use this for both linktables and section ranges.
Or do we want macros for both that do the same thing ?

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
  2016-08-25  6:05                 ` Luis R. Rodriguez
  (?)
@ 2016-08-25  6:51                   ` Nicholas Piggin
  -1 siblings, 0 replies; 480+ messages in thread
From: Nicholas Piggin @ 2016-08-25  6:51 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3

On Thu, 25 Aug 2016 08:05:40 +0200
"Luis R. Rodriguez" <mcgrof@kernel.org> wrote:

> On Thu, Aug 25, 2016 at 12:06:33PM +1000, Nicholas Piggin wrote:
> > On Wed, 24 Aug 2016 22:12:53 +0200
> > "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:  
> > > But:
> > > 
> > > git grep SECTION_TEXT works as expected immediately.
> > > 
> > > I guess its a matter of perspective.
> > >   
> > > > They are also
> > > > the names you'll be grepping for when you look at disassembly.    
> > > 
> > > Sure but if you're grepping asm, you very likely know what to look for.  
> > 
> > After you have gone through the extra layer of naming indirection
> > to work out what it is. I'm still not sold on the name indirection
> > and hiding wildcards. Not just for asm grepping, but I don't think
> > it's a negative thing for devs working on the linker to know what
> > actual section names and commands are being used, as much as possible.  
> 
> OK lets see what it looks like after dropping them. Will try that.
> 
> > > The idea was to add helpers to do the globbing more easily.
> > > 
> > > The glob for sections now documented   is SECTION_ALL()
> > > The glob that is range specific        is SECTION_RNG_ALL()
> > > The glob that is linker table specific is SECTION_TBL_ALL()  
> > 
> > I still don't see this is better than
> > 
> > .text*
> > .text.*
> > .text.range.*
> > .text.table.*
> > etc.  
> 
> OK will drop it.

Thank you for considering it, I appreciate that.


> > > How about:
> > > 
> > > At the top just use "Linux sections helpers"
> > > 
> > > Then:
> > > 
> > > /**
> > >  * DOC: Introduction
> > >  *
> > >  * We document below a dedicated set of helpers used in Linux to make sections
> > >  * defined in the Linux linker script accessible in C code in a generic form and 
> > >  * and provide certain attributes about them.
> > >  */
> > >   
> > > > I just can't work out what exactly is a
> > > > "custom Linux section", and what DECLARE_LINUX_SECTION(), for example, actaully
> > > > gives you.    
> > > 
> > > Its a way to replace the:
> > > 
> > > extern char foo[], foo__end[];
> > > 
> > > So this provides a generalized form to use declarations used in C code to make
> > > the linker script start and end symbols from esctions accessible in C code. Since
> > > DEFINE_SECTION_RANGE() and DEFINE_LINKTABLE() macros use this, then the
> > > DECLARE_LINUX_SECTION() is only needed if you need access to these symbols in C
> > > code outside of the one that is defining and mainly in charge of managing the
> > > section. We provide DECLARE_*() helpers for section ranges and linker tables
> > > though so those can be used instead to help annotate the type of a custom
> > > section they are.  
> > 
> > Oh, that makes more sense. The SECTION stuff and custom sections was
> > confusing me. I would prefer just to drop all the LINUX_SECTION naming
> > and make it match the functionality you're using. For example:
> > 
> > +DEFINE_LINKTABLE(struct jump_entry, __jump_table);
> > +
> >  /* mutex to protect coming/going of the the jump_label table */
> >  static DEFINE_MUTEX(jump_label_mutex);
> >  
> > @@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
> >  
> >  void __init jump_label_init(void)
> >  {
> > -	struct jump_entry *iter_start = __start___jump_table;
> > -	struct jump_entry *iter_stop = __stop___jump_table;
> >  	struct static_key *key = NULL;
> >  	struct jump_entry *iter;
> >  
> > @@ -292,9 +293,10 @@ void __init jump_label_init(void)
> >  		return;
> >  
> >  	jump_label_lock();
> > -	jump_label_sort_entries(iter_start, iter_stop);
> > +	jump_label_sort_entries(LINUX_SECTION_START(__jump_table),
> > +				LINUX_SECTION_END(__jump_table));
> > 
> > Now I think this is a fine abstraction to have.  
> 
> OK will keep this one.
> 
> > I think it would look
> > even cleaner if you had:
> > 
> > LINKTABLE_START(__jump_table)
> > LINKTABLE_END(__jump_table)
> >
> > Then do we need to even have the LINUX_SECTION middle man at all?  
> 
> Ah, thing is we use this for both linktables and section ranges.
> Or do we want macros for both that do the same thing ?

I think it would make the code using it more readable.

Thanks,
Nick

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-25  6:51                   ` Nicholas Piggin
  0 siblings, 0 replies; 480+ messages in thread
From: Nicholas Piggin @ 2016-08-25  6:51 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3

On Thu, 25 Aug 2016 08:05:40 +0200
"Luis R. Rodriguez" <mcgrof@kernel.org> wrote:

> On Thu, Aug 25, 2016 at 12:06:33PM +1000, Nicholas Piggin wrote:
> > On Wed, 24 Aug 2016 22:12:53 +0200
> > "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:  
> > > But:
> > > 
> > > git grep SECTION_TEXT works as expected immediately.
> > > 
> > > I guess its a matter of perspective.
> > >   
> > > > They are also
> > > > the names you'll be grepping for when you look at disassembly.    
> > > 
> > > Sure but if you're grepping asm, you very likely know what to look for.  
> > 
> > After you have gone through the extra layer of naming indirection
> > to work out what it is. I'm still not sold on the name indirection
> > and hiding wildcards. Not just for asm grepping, but I don't think
> > it's a negative thing for devs working on the linker to know what
> > actual section names and commands are being used, as much as possible.  
> 
> OK lets see what it looks like after dropping them. Will try that.
> 
> > > The idea was to add helpers to do the globbing more easily.
> > > 
> > > The glob for sections now documented   is SECTION_ALL()
> > > The glob that is range specific        is SECTION_RNG_ALL()
> > > The glob that is linker table specific is SECTION_TBL_ALL()  
> > 
> > I still don't see this is better than
> > 
> > .text*
> > .text.*
> > .text.range.*
> > .text.table.*
> > etc.  
> 
> OK will drop it.

Thank you for considering it, I appreciate that.


> > > How about:
> > > 
> > > At the top just use "Linux sections helpers"
> > > 
> > > Then:
> > > 
> > > /**
> > >  * DOC: Introduction
> > >  *
> > >  * We document below a dedicated set of helpers used in Linux to make sections
> > >  * defined in the Linux linker script accessible in C code in a generic form and 
> > >  * and provide certain attributes about them.
> > >  */
> > >   
> > > > I just can't work out what exactly is a
> > > > "custom Linux section", and what DECLARE_LINUX_SECTION(), for example, actaully
> > > > gives you.    
> > > 
> > > Its a way to replace the:
> > > 
> > > extern char foo[], foo__end[];
> > > 
> > > So this provides a generalized form to use declarations used in C code to make
> > > the linker script start and end symbols from esctions accessible in C code. Since
> > > DEFINE_SECTION_RANGE() and DEFINE_LINKTABLE() macros use this, then the
> > > DECLARE_LINUX_SECTION() is only needed if you need access to these symbols in C
> > > code outside of the one that is defining and mainly in charge of managing the
> > > section. We provide DECLARE_*() helpers for section ranges and linker tables
> > > though so those can be used instead to help annotate the type of a custom
> > > section they are.  
> > 
> > Oh, that makes more sense. The SECTION stuff and custom sections was
> > confusing me. I would prefer just to drop all the LINUX_SECTION naming
> > and make it match the functionality you're using. For example:
> > 
> > +DEFINE_LINKTABLE(struct jump_entry, __jump_table);
> > +
> >  /* mutex to protect coming/going of the the jump_label table */
> >  static DEFINE_MUTEX(jump_label_mutex);
> >  
> > @@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
> >  
> >  void __init jump_label_init(void)
> >  {
> > -	struct jump_entry *iter_start = __start___jump_table;
> > -	struct jump_entry *iter_stop = __stop___jump_table;
> >  	struct static_key *key = NULL;
> >  	struct jump_entry *iter;
> >  
> > @@ -292,9 +293,10 @@ void __init jump_label_init(void)
> >  		return;
> >  
> >  	jump_label_lock();
> > -	jump_label_sort_entries(iter_start, iter_stop);
> > +	jump_label_sort_entries(LINUX_SECTION_START(__jump_table),
> > +				LINUX_SECTION_END(__jump_table));
> > 
> > Now I think this is a fine abstraction to have.  
> 
> OK will keep this one.
> 
> > I think it would look
> > even cleaner if you had:
> > 
> > LINKTABLE_START(__jump_table)
> > LINKTABLE_END(__jump_table)
> >
> > Then do we need to even have the LINUX_SECTION middle man at all?  
> 
> Ah, thing is we use this for both linktables and section ranges.
> Or do we want macros for both that do the same thing ?

I think it would make the code using it more readable.

Thanks,
Nick

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-25  6:51                   ` Nicholas Piggin
  0 siblings, 0 replies; 480+ messages in thread
From: Nicholas Piggin @ 2016-08-25  6:51 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, acme, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, paulus, mpe, James.Bottomley

On Thu, 25 Aug 2016 08:05:40 +0200
"Luis R. Rodriguez" <mcgrof@kernel.org> wrote:

> On Thu, Aug 25, 2016 at 12:06:33PM +1000, Nicholas Piggin wrote:
> > On Wed, 24 Aug 2016 22:12:53 +0200
> > "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:  
> > > But:
> > > 
> > > git grep SECTION_TEXT works as expected immediately.
> > > 
> > > I guess its a matter of perspective.
> > >   
> > > > They are also
> > > > the names you'll be grepping for when you look at disassembly.    
> > > 
> > > Sure but if you're grepping asm, you very likely know what to look for.  
> > 
> > After you have gone through the extra layer of naming indirection
> > to work out what it is. I'm still not sold on the name indirection
> > and hiding wildcards. Not just for asm grepping, but I don't think
> > it's a negative thing for devs working on the linker to know what
> > actual section names and commands are being used, as much as possible.  
> 
> OK lets see what it looks like after dropping them. Will try that.
> 
> > > The idea was to add helpers to do the globbing more easily.
> > > 
> > > The glob for sections now documented   is SECTION_ALL()
> > > The glob that is range specific        is SECTION_RNG_ALL()
> > > The glob that is linker table specific is SECTION_TBL_ALL()  
> > 
> > I still don't see this is better than
> > 
> > .text*
> > .text.*
> > .text.range.*
> > .text.table.*
> > etc.  
> 
> OK will drop it.

Thank you for considering it, I appreciate that.


> > > How about:
> > > 
> > > At the top just use "Linux sections helpers"
> > > 
> > > Then:
> > > 
> > > /**
> > >  * DOC: Introduction
> > >  *
> > >  * We document below a dedicated set of helpers used in Linux to make sections
> > >  * defined in the Linux linker script accessible in C code in a generic form and 
> > >  * and provide certain attributes about them.
> > >  */
> > >   
> > > > I just can't work out what exactly is a
> > > > "custom Linux section", and what DECLARE_LINUX_SECTION(), for example, actaully
> > > > gives you.    
> > > 
> > > Its a way to replace the:
> > > 
> > > extern char foo[], foo__end[];
> > > 
> > > So this provides a generalized form to use declarations used in C code to make
> > > the linker script start and end symbols from esctions accessible in C code. Since
> > > DEFINE_SECTION_RANGE() and DEFINE_LINKTABLE() macros use this, then the
> > > DECLARE_LINUX_SECTION() is only needed if you need access to these symbols in C
> > > code outside of the one that is defining and mainly in charge of managing the
> > > section. We provide DECLARE_*() helpers for section ranges and linker tables
> > > though so those can be used instead to help annotate the type of a custom
> > > section they are.  
> > 
> > Oh, that makes more sense. The SECTION stuff and custom sections was
> > confusing me. I would prefer just to drop all the LINUX_SECTION naming
> > and make it match the functionality you're using. For example:
> > 
> > +DEFINE_LINKTABLE(struct jump_entry, __jump_table);
> > +
> >  /* mutex to protect coming/going of the the jump_label table */
> >  static DEFINE_MUTEX(jump_label_mutex);
> >  
> > @@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
> >  
> >  void __init jump_label_init(void)
> >  {
> > -	struct jump_entry *iter_start = __start___jump_table;
> > -	struct jump_entry *iter_stop = __stop___jump_table;
> >  	struct static_key *key = NULL;
> >  	struct jump_entry *iter;
> >  
> > @@ -292,9 +293,10 @@ void __init jump_label_init(void)
> >  		return;
> >  
> >  	jump_label_lock();
> > -	jump_label_sort_entries(iter_start, iter_stop);
> > +	jump_label_sort_entries(LINUX_SECTION_START(__jump_table),
> > +				LINUX_SECTION_END(__jump_table));
> > 
> > Now I think this is a fine abstraction to have.  
> 
> OK will keep this one.
> 
> > I think it would look
> > even cleaner if you had:
> > 
> > LINKTABLE_START(__jump_table)
> > LINKTABLE_END(__jump_table)
> >
> > Then do we need to even have the LINUX_SECTION middle man at all?  
> 
> Ah, thing is we use this for both linktables and section ranges.
> Or do we want macros for both that do the same thing ?

I think it would make the code using it more readable.

Thanks,
Nick

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
  2016-08-25  6:51                   ` Nicholas Piggin
  (?)
@ 2016-08-25 17:52                     ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-25 17:52 UTC (permalink / raw)
  To: Nicholas Piggin
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, heiko.carstens,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	mpe, hpa, masami.hiramatsu.pt, mchehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, linux, linux-sh,
	will.deacon, korea.drzix, x86, anil.s.keshavamurthy, fontana,
	mingo, linux-arm-kernel, catalin.marinas, dvhart, dwmw2,
	david.vrabel, linux-xtensa, pali.rohar, keescook, arnd

On Thu, Aug 25, 2016 at 04:51:21PM +1000, Nicholas Piggin wrote:
> On Thu, 25 Aug 2016 08:05:40 +0200
> "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> > > Oh, that makes more sense. The SECTION stuff and custom sections was
> > > confusing me. I would prefer just to drop all the LINUX_SECTION naming
> > > and make it match the functionality you're using. For example:
> > > 
> > > +DEFINE_LINKTABLE(struct jump_entry, __jump_table);
> > > +
> > >  /* mutex to protect coming/going of the the jump_label table */
> > >  static DEFINE_MUTEX(jump_label_mutex);
> > >  
> > > @@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
> > >  
> > >  void __init jump_label_init(void)
> > >  {
> > > -	struct jump_entry *iter_start = __start___jump_table;
> > > -	struct jump_entry *iter_stop = __stop___jump_table;
> > >  	struct static_key *key = NULL;
> > >  	struct jump_entry *iter;
> > >  
> > > @@ -292,9 +293,10 @@ void __init jump_label_init(void)
> > >  		return;
> > >  
> > >  	jump_label_lock();
> > > -	jump_label_sort_entries(iter_start, iter_stop);
> > > +	jump_label_sort_entries(LINUX_SECTION_START(__jump_table),
> > > +				LINUX_SECTION_END(__jump_table));
> > > 
> > > Now I think this is a fine abstraction to have.  
> > 
> > OK will keep this one.
> > 
> > > I think it would look
> > > even cleaner if you had:
> > > 
> > > LINKTABLE_START(__jump_table)
> > > LINKTABLE_END(__jump_table)
> > >
> > > Then do we need to even have the LINUX_SECTION middle man at all?  
> > 
> > Ah, thing is we use this for both linktables and section ranges.
> > Or do we want macros for both that do the same thing ?
> 
> I think it would make the code using it more readable.

Alrighty... so:

LINKTABLE_START()
LINKTABLE_END()

SECTION_RANGE_START()
SECTION_RANGE_END()

And these macros do the exact same thing. Ie, nothing shared. Right?

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-25 17:52                     ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-25 17:52 UTC (permalink / raw)
  To: Nicholas Piggin
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, heiko.carstens,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	mpe, hpa, masami.hiramatsu.pt, mchehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, linux, linux-sh,
	will.deacon, korea.drzix, x86, anil.s.keshavamurthy, fontana,
	mingo, linux-arm-kernel, catalin.marinas, dvhart, dwmw2,
	david.vrabel, linux-xtensa, pali.rohar, keescook, arnd

On Thu, Aug 25, 2016 at 04:51:21PM +1000, Nicholas Piggin wrote:
> On Thu, 25 Aug 2016 08:05:40 +0200
> "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> > > Oh, that makes more sense. The SECTION stuff and custom sections was
> > > confusing me. I would prefer just to drop all the LINUX_SECTION naming
> > > and make it match the functionality you're using. For example:
> > > 
> > > +DEFINE_LINKTABLE(struct jump_entry, __jump_table);
> > > +
> > >  /* mutex to protect coming/going of the the jump_label table */
> > >  static DEFINE_MUTEX(jump_label_mutex);
> > >  
> > > @@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
> > >  
> > >  void __init jump_label_init(void)
> > >  {
> > > -	struct jump_entry *iter_start = __start___jump_table;
> > > -	struct jump_entry *iter_stop = __stop___jump_table;
> > >  	struct static_key *key = NULL;
> > >  	struct jump_entry *iter;
> > >  
> > > @@ -292,9 +293,10 @@ void __init jump_label_init(void)
> > >  		return;
> > >  
> > >  	jump_label_lock();
> > > -	jump_label_sort_entries(iter_start, iter_stop);
> > > +	jump_label_sort_entries(LINUX_SECTION_START(__jump_table),
> > > +				LINUX_SECTION_END(__jump_table));
> > > 
> > > Now I think this is a fine abstraction to have.  
> > 
> > OK will keep this one.
> > 
> > > I think it would look
> > > even cleaner if you had:
> > > 
> > > LINKTABLE_START(__jump_table)
> > > LINKTABLE_END(__jump_table)
> > >
> > > Then do we need to even have the LINUX_SECTION middle man at all?  
> > 
> > Ah, thing is we use this for both linktables and section ranges.
> > Or do we want macros for both that do the same thing ?
> 
> I think it would make the code using it more readable.

Alrighty... so:

LINKTABLE_START()
LINKTABLE_END()

SECTION_RANGE_START()
SECTION_RANGE_END()

And these macros do the exact same thing. Ie, nothing shared. Right?

  Luis

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-25 17:52                     ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-25 17:52 UTC (permalink / raw)
  To: Nicholas Piggin
  Cc: Luis R. Rodriguez, hpa, tglx, mingo, jpoimboe, bp, linux,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, acme, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, paulus, mpe, James.Bottomley

On Thu, Aug 25, 2016 at 04:51:21PM +1000, Nicholas Piggin wrote:
> On Thu, 25 Aug 2016 08:05:40 +0200
> "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> > > Oh, that makes more sense. The SECTION stuff and custom sections was
> > > confusing me. I would prefer just to drop all the LINUX_SECTION naming
> > > and make it match the functionality you're using. For example:
> > > 
> > > +DEFINE_LINKTABLE(struct jump_entry, __jump_table);
> > > +
> > >  /* mutex to protect coming/going of the the jump_label table */
> > >  static DEFINE_MUTEX(jump_label_mutex);
> > >  
> > > @@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
> > >  
> > >  void __init jump_label_init(void)
> > >  {
> > > -	struct jump_entry *iter_start = __start___jump_table;
> > > -	struct jump_entry *iter_stop = __stop___jump_table;
> > >  	struct static_key *key = NULL;
> > >  	struct jump_entry *iter;
> > >  
> > > @@ -292,9 +293,10 @@ void __init jump_label_init(void)
> > >  		return;
> > >  
> > >  	jump_label_lock();
> > > -	jump_label_sort_entries(iter_start, iter_stop);
> > > +	jump_label_sort_entries(LINUX_SECTION_START(__jump_table),
> > > +				LINUX_SECTION_END(__jump_table));
> > > 
> > > Now I think this is a fine abstraction to have.  
> > 
> > OK will keep this one.
> > 
> > > I think it would look
> > > even cleaner if you had:
> > > 
> > > LINKTABLE_START(__jump_table)
> > > LINKTABLE_END(__jump_table)
> > >
> > > Then do we need to even have the LINUX_SECTION middle man at all?  
> > 
> > Ah, thing is we use this for both linktables and section ranges.
> > Or do we want macros for both that do the same thing ?
> 
> I think it would make the code using it more readable.

Alrighty... so:

LINKTABLE_START()
LINKTABLE_END()

SECTION_RANGE_START()
SECTION_RANGE_END()

And these macros do the exact same thing. Ie, nothing shared. Right?

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
  2016-08-25 17:52                     ` Luis R. Rodriguez
  (?)
@ 2016-08-26  3:00                       ` Nicholas Piggin
  -1 siblings, 0 replies; 480+ messages in thread
From: Nicholas Piggin @ 2016-08-26  3:00 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, heiko.carstens,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	mpe, hpa, masami.hiramatsu.pt, mchehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, linux, linux-sh,
	will.deacon, korea.drzix, x86, anil.s.keshavamurthy, fontana,
	mingo, linux-arm-kernel, catalin.marinas, dvhart, dwmw2,
	david.vrabel, linux-xtensa, pali.rohar, keescook, arnd

On Thu, 25 Aug 2016 19:52:39 +0200
"Luis R. Rodriguez" <mcgrof@kernel.org> wrote:

> On Thu, Aug 25, 2016 at 04:51:21PM +1000, Nicholas Piggin wrote:
> > On Thu, 25 Aug 2016 08:05:40 +0200
> > "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:  
> > > > Oh, that makes more sense. The SECTION stuff and custom sections was
> > > > confusing me. I would prefer just to drop all the LINUX_SECTION naming
> > > > and make it match the functionality you're using. For example:
> > > > 
> > > > +DEFINE_LINKTABLE(struct jump_entry, __jump_table);
> > > > +
> > > >  /* mutex to protect coming/going of the the jump_label table */
> > > >  static DEFINE_MUTEX(jump_label_mutex);
> > > >  
> > > > @@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
> > > >  
> > > >  void __init jump_label_init(void)
> > > >  {
> > > > -	struct jump_entry *iter_start = __start___jump_table;
> > > > -	struct jump_entry *iter_stop = __stop___jump_table;
> > > >  	struct static_key *key = NULL;
> > > >  	struct jump_entry *iter;
> > > >  
> > > > @@ -292,9 +293,10 @@ void __init jump_label_init(void)
> > > >  		return;
> > > >  
> > > >  	jump_label_lock();
> > > > -	jump_label_sort_entries(iter_start, iter_stop);
> > > > +	jump_label_sort_entries(LINUX_SECTION_START(__jump_table),
> > > > +				LINUX_SECTION_END(__jump_table));
> > > > 
> > > > Now I think this is a fine abstraction to have.    
> > > 
> > > OK will keep this one.
> > >   
> > > > I think it would look
> > > > even cleaner if you had:
> > > > 
> > > > LINKTABLE_START(__jump_table)
> > > > LINKTABLE_END(__jump_table)
> > > >
> > > > Then do we need to even have the LINUX_SECTION middle man at all?    
> > > 
> > > Ah, thing is we use this for both linktables and section ranges.
> > > Or do we want macros for both that do the same thing ?  
> > 
> > I think it would make the code using it more readable.  
> 
> Alrighty... so:
> 
> LINKTABLE_START()
> LINKTABLE_END()
> 
> SECTION_RANGE_START()
> SECTION_RANGE_END()
> 
> And these macros do the exact same thing. Ie, nothing shared. Right?

Yeah I think so. Internally they would probably be aliased to the
same common definition (unless you had some type check or something),
but user would know about such details.

Thanks,
Nick

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-26  3:00                       ` Nicholas Piggin
  0 siblings, 0 replies; 480+ messages in thread
From: Nicholas Piggin @ 2016-08-26  3:00 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, heiko.carstens,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	mpe, hpa, masami.hiramatsu.pt, mchehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, linux, linux-sh,
	will.deacon, korea.drzix, x86, anil.s.keshavamurthy, fontana,
	mingo, linux-arm-kernel, catalin.marinas, dvhart, dwmw2,
	david.vrabel, linux-xtensa, pali.rohar, keescook, arnd

On Thu, 25 Aug 2016 19:52:39 +0200
"Luis R. Rodriguez" <mcgrof@kernel.org> wrote:

> On Thu, Aug 25, 2016 at 04:51:21PM +1000, Nicholas Piggin wrote:
> > On Thu, 25 Aug 2016 08:05:40 +0200
> > "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:  
> > > > Oh, that makes more sense. The SECTION stuff and custom sections was
> > > > confusing me. I would prefer just to drop all the LINUX_SECTION naming
> > > > and make it match the functionality you're using. For example:
> > > > 
> > > > +DEFINE_LINKTABLE(struct jump_entry, __jump_table);
> > > > +
> > > >  /* mutex to protect coming/going of the the jump_label table */
> > > >  static DEFINE_MUTEX(jump_label_mutex);
> > > >  
> > > > @@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
> > > >  
> > > >  void __init jump_label_init(void)
> > > >  {
> > > > -	struct jump_entry *iter_start = __start___jump_table;
> > > > -	struct jump_entry *iter_stop = __stop___jump_table;
> > > >  	struct static_key *key = NULL;
> > > >  	struct jump_entry *iter;
> > > >  
> > > > @@ -292,9 +293,10 @@ void __init jump_label_init(void)
> > > >  		return;
> > > >  
> > > >  	jump_label_lock();
> > > > -	jump_label_sort_entries(iter_start, iter_stop);
> > > > +	jump_label_sort_entries(LINUX_SECTION_START(__jump_table),
> > > > +				LINUX_SECTION_END(__jump_table));
> > > > 
> > > > Now I think this is a fine abstraction to have.    
> > > 
> > > OK will keep this one.
> > >   
> > > > I think it would look
> > > > even cleaner if you had:
> > > > 
> > > > LINKTABLE_START(__jump_table)
> > > > LINKTABLE_END(__jump_table)
> > > >
> > > > Then do we need to even have the LINUX_SECTION middle man at all?    
> > > 
> > > Ah, thing is we use this for both linktables and section ranges.
> > > Or do we want macros for both that do the same thing ?  
> > 
> > I think it would make the code using it more readable.  
> 
> Alrighty... so:
> 
> LINKTABLE_START()
> LINKTABLE_END()
> 
> SECTION_RANGE_START()
> SECTION_RANGE_END()
> 
> And these macros do the exact same thing. Ie, nothing shared. Right?

Yeah I think so. Internally they would probably be aliased to the
same common definition (unless you had some type check or something),
but user would know about such details.

Thanks,
Nick

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-26  3:00                       ` Nicholas Piggin
  0 siblings, 0 replies; 480+ messages in thread
From: Nicholas Piggin @ 2016-08-26  3:00 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: hpa, tglx, mingo, jpoimboe, bp, linux, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, acme, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, paulus, mpe, James.Bottomley

On Thu, 25 Aug 2016 19:52:39 +0200
"Luis R. Rodriguez" <mcgrof@kernel.org> wrote:

> On Thu, Aug 25, 2016 at 04:51:21PM +1000, Nicholas Piggin wrote:
> > On Thu, 25 Aug 2016 08:05:40 +0200
> > "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:  
> > > > Oh, that makes more sense. The SECTION stuff and custom sections was
> > > > confusing me. I would prefer just to drop all the LINUX_SECTION naming
> > > > and make it match the functionality you're using. For example:
> > > > 
> > > > +DEFINE_LINKTABLE(struct jump_entry, __jump_table);
> > > > +
> > > >  /* mutex to protect coming/going of the the jump_label table */
> > > >  static DEFINE_MUTEX(jump_label_mutex);
> > > >  
> > > > @@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
> > > >  
> > > >  void __init jump_label_init(void)
> > > >  {
> > > > -	struct jump_entry *iter_start = __start___jump_table;
> > > > -	struct jump_entry *iter_stop = __stop___jump_table;
> > > >  	struct static_key *key = NULL;
> > > >  	struct jump_entry *iter;
> > > >  
> > > > @@ -292,9 +293,10 @@ void __init jump_label_init(void)
> > > >  		return;
> > > >  
> > > >  	jump_label_lock();
> > > > -	jump_label_sort_entries(iter_start, iter_stop);
> > > > +	jump_label_sort_entries(LINUX_SECTION_START(__jump_table),
> > > > +				LINUX_SECTION_END(__jump_table));
> > > > 
> > > > Now I think this is a fine abstraction to have.    
> > > 
> > > OK will keep this one.
> > >   
> > > > I think it would look
> > > > even cleaner if you had:
> > > > 
> > > > LINKTABLE_START(__jump_table)
> > > > LINKTABLE_END(__jump_table)
> > > >
> > > > Then do we need to even have the LINUX_SECTION middle man at all?    
> > > 
> > > Ah, thing is we use this for both linktables and section ranges.
> > > Or do we want macros for both that do the same thing ?  
> > 
> > I think it would make the code using it more readable.  
> 
> Alrighty... so:
> 
> LINKTABLE_START()
> LINKTABLE_END()
> 
> SECTION_RANGE_START()
> SECTION_RANGE_END()
> 
> And these macros do the exact same thing. Ie, nothing shared. Right?

Yeah I think so. Internally they would probably be aliased to the
same common definition (unless you had some type check or something),
but user would know about such details.

Thanks,
Nick

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
  2016-08-26  3:00                       ` Nicholas Piggin
  (?)
  (?)
@ 2016-08-26  6:38                       ` Luis R. Rodriguez
  2016-08-26  7:33                           ` Nicholas Piggin
  -1 siblings, 1 reply; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-26  6:38 UTC (permalink / raw)
  To: Nicholas Piggin
  Cc: gnomes, linux-ia64, realmz6, linux-sh, benh, ming.lei,
	heiko.carstens, linux, platform-driver-x86, James.Bottomley,
	jcmvbkbc, paulus, hpa, masami.hiramatsu.pt, mchehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, msalter, davem, mpe, x86,
	anil.s.keshavamurthy, fontana, mingo, catalin.marinas, dvhart,
	dwmw2, mhiramat, linux-xtensa, rusty, keescook, arnd,
	linux-kbuild, jani.nikula


[-- Attachment #1.1: Type: text/plain, Size: 2558 bytes --]

On Aug 25, 2016 8:00 PM, "Nicholas Piggin" <npiggin@gmail.com> wrote:
>
> On Thu, 25 Aug 2016 19:52:39 +0200
> "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
>
> > On Thu, Aug 25, 2016 at 04:51:21PM +1000, Nicholas Piggin wrote:
> > > On Thu, 25 Aug 2016 08:05:40 +0200
> > > "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> > > > > Oh, that makes more sense. The SECTION stuff and custom sections
was
> > > > > confusing me. I would prefer just to drop all the LINUX_SECTION
naming
> > > > > and make it match the functionality you're using. For example:
> > > > >
> > > > > +DEFINE_LINKTABLE(struct jump_entry, __jump_table);
> > > > > +
> > > > >  /* mutex to protect coming/going of the the jump_label table */
> > > > >  static DEFINE_MUTEX(jump_label_mutex);
> > > > >
> > > > > @@ -274,8 +277,6 @@ static void __jump_label_update(struct
static_key *key,
> > > > >
> > > > >  void __init jump_label_init(void)
> > > > >  {
> > > > > -       struct jump_entry *iter_start = __start___jump_table;
> > > > > -       struct jump_entry *iter_stop = __stop___jump_table;
> > > > >         struct static_key *key = NULL;
> > > > >         struct jump_entry *iter;
> > > > >
> > > > > @@ -292,9 +293,10 @@ void __init jump_label_init(void)
> > > > >                 return;
> > > > >
> > > > >         jump_label_lock();
> > > > > -       jump_label_sort_entries(iter_start, iter_stop);
> > > > > +       jump_label_sort_entries(LINUX_SECTION_START(__jump_table),
> > > > > +                               LINUX_SECTION_END(__jump_table));
> > > > >
> > > > > Now I think this is a fine abstraction to have.
> > > >
> > > > OK will keep this one.
> > > >
> > > > > I think it would look
> > > > > even cleaner if you had:
> > > > >
> > > > > LINKTABLE_START(__jump_table)
> > > > > LINKTABLE_END(__jump_table)
> > > > >
> > > > > Then do we need to even have the LINUX_SECTION middle man at all?
> > > >
> > > > Ah, thing is we use this for both linktables and section ranges.
> > > > Or do we want macros for both that do the same thing ?
> > >
> > > I think it would make the code using it more readable.
> >
> > Alrighty... so:
> >
> > LINKTABLE_START()
> > LINKTABLE_END()
> >
> > SECTION_RANGE_START()
> > SECTION_RANGE_END()
> >
> > And these macros do the exact same thing. Ie, nothing shared. Right?
>
> Yeah I think so. Internally they would probably be aliased to the
> same common definition (unless you had some type check or something),
> but user would know about such details.

What name should we use for such common macro definition ?

  Luis

[-- Attachment #1.2: Type: text/html, Size: 3882 bytes --]

[-- Attachment #2: Type: text/plain, Size: 127 bytes --]

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
  2016-08-26  6:38                       ` Luis R. Rodriguez
  2016-08-26  7:33                           ` Nicholas Piggin
@ 2016-08-26  7:33                           ` Nicholas Piggin
  0 siblings, 0 replies; 480+ messages in thread
From: Nicholas Piggin @ 2016-08-26  7:33 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: benh, jani.nikula, masami.hiramatsu.pt, linux, linux-kbuild,
	linux-sh, luto, gnomes, jcmvbkbc, torvalds, akpm, dwmw2,
	xen-devel, anil.s.keshavamurthy, will.deacon, linux-ia64, x86,
	korea.drzix, mingo, andrew.cooper3, jgross, tglx, keescook,
	ananth, jpoimboe, rostedt, hpa, acme, arnd, davem,
	platform-driver-x86, jkosina, david.vrabel

On Thu, 25 Aug 2016 23:38:44 -0700
"Luis R. Rodriguez" <mcgrof@kernel.org> wrote:

> On Aug 25, 2016 8:00 PM, "Nicholas Piggin" <npiggin@gmail.com> wrote:
> >
> > On Thu, 25 Aug 2016 19:52:39 +0200
> > "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> >  
> > > On Thu, Aug 25, 2016 at 04:51:21PM +1000, Nicholas Piggin wrote:  
> > > > On Thu, 25 Aug 2016 08:05:40 +0200
> > > > "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:  
> > > > > > Oh, that makes more sense. The SECTION stuff and custom sections  
> was
> > > > > > confusing me. I would prefer just to drop all the LINUX_SECTION  
> naming
> > > > > > and make it match the functionality you're using. For example:
> > > > > >
> > > > > > +DEFINE_LINKTABLE(struct jump_entry, __jump_table);
> > > > > > +
> > > > > >  /* mutex to protect coming/going of the the jump_label table */
> > > > > >  static DEFINE_MUTEX(jump_label_mutex);
> > > > > >
> > > > > > @@ -274,8 +277,6 @@ static void __jump_label_update(struct  
> static_key *key,
> > > > > >
> > > > > >  void __init jump_label_init(void)
> > > > > >  {
> > > > > > -       struct jump_entry *iter_start = __start___jump_table;
> > > > > > -       struct jump_entry *iter_stop = __stop___jump_table;
> > > > > >         struct static_key *key = NULL;
> > > > > >         struct jump_entry *iter;
> > > > > >
> > > > > > @@ -292,9 +293,10 @@ void __init jump_label_init(void)
> > > > > >                 return;
> > > > > >
> > > > > >         jump_label_lock();
> > > > > > -       jump_label_sort_entries(iter_start, iter_stop);
> > > > > > +       jump_label_sort_entries(LINUX_SECTION_START(__jump_table),
> > > > > > +                               LINUX_SECTION_END(__jump_table));
> > > > > >
> > > > > > Now I think this is a fine abstraction to have.  
> > > > >
> > > > > OK will keep this one.
> > > > >  
> > > > > > I think it would look
> > > > > > even cleaner if you had:
> > > > > >
> > > > > > LINKTABLE_START(__jump_table)
> > > > > > LINKTABLE_END(__jump_table)
> > > > > >
> > > > > > Then do we need to even have the LINUX_SECTION middle man at all?  
> > > > >
> > > > > Ah, thing is we use this for both linktables and section ranges.
> > > > > Or do we want macros for both that do the same thing ?  
> > > >
> > > > I think it would make the code using it more readable.  
> > >
> > > Alrighty... so:
> > >
> > > LINKTABLE_START()
> > > LINKTABLE_END()
> > >
> > > SECTION_RANGE_START()
> > > SECTION_RANGE_END()
> > >
> > > And these macros do the exact same thing. Ie, nothing shared. Right?  
> >
> > Yeah I think so. Internally they would probably be aliased to the
> > same common definition (unless you had some type check or something),
> > but user would know about such details.  
> 
> What name should we use for such common macro definition ?


Ah, not really sure. I guess the "link table" is some kind of
section range? I haven't actually looked closely at both of them
in the subsequent patches. It matters less if it's not expected
to be used as an API though.

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-26  7:33                           ` Nicholas Piggin
  0 siblings, 0 replies; 480+ messages in thread
From: Nicholas Piggin @ 2016-08-26  7:33 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: benh, jani.nikula, masami.hiramatsu.pt, linux, linux-kbuild,
	linux-sh, luto, gnomes, jcmvbkbc, torvalds, akpm, dwmw2,
	xen-devel, anil.s.keshavamurthy, will.deacon, linux-ia64, x86,
	korea.drzix, mingo, andrew.cooper3, jgross, tglx, keescook,
	ananth, jpoimboe, rostedt, hpa, acme, arnd, davem,
	platform-driver-x86, jkosina, david.vrabel

On Thu, 25 Aug 2016 23:38:44 -0700
"Luis R. Rodriguez" <mcgrof@kernel.org> wrote:

> On Aug 25, 2016 8:00 PM, "Nicholas Piggin" <npiggin@gmail.com> wrote:
> >
> > On Thu, 25 Aug 2016 19:52:39 +0200
> > "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> >  
> > > On Thu, Aug 25, 2016 at 04:51:21PM +1000, Nicholas Piggin wrote:  
> > > > On Thu, 25 Aug 2016 08:05:40 +0200
> > > > "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:  
> > > > > > Oh, that makes more sense. The SECTION stuff and custom sections  
> was
> > > > > > confusing me. I would prefer just to drop all the LINUX_SECTION  
> naming
> > > > > > and make it match the functionality you're using. For example:
> > > > > >
> > > > > > +DEFINE_LINKTABLE(struct jump_entry, __jump_table);
> > > > > > +
> > > > > >  /* mutex to protect coming/going of the the jump_label table */
> > > > > >  static DEFINE_MUTEX(jump_label_mutex);
> > > > > >
> > > > > > @@ -274,8 +277,6 @@ static void __jump_label_update(struct  
> static_key *key,
> > > > > >
> > > > > >  void __init jump_label_init(void)
> > > > > >  {
> > > > > > -       struct jump_entry *iter_start = __start___jump_table;
> > > > > > -       struct jump_entry *iter_stop = __stop___jump_table;
> > > > > >         struct static_key *key = NULL;
> > > > > >         struct jump_entry *iter;
> > > > > >
> > > > > > @@ -292,9 +293,10 @@ void __init jump_label_init(void)
> > > > > >                 return;
> > > > > >
> > > > > >         jump_label_lock();
> > > > > > -       jump_label_sort_entries(iter_start, iter_stop);
> > > > > > +       jump_label_sort_entries(LINUX_SECTION_START(__jump_table),
> > > > > > +                               LINUX_SECTION_END(__jump_table));
> > > > > >
> > > > > > Now I think this is a fine abstraction to have.  
> > > > >
> > > > > OK will keep this one.
> > > > >  
> > > > > > I think it would look
> > > > > > even cleaner if you had:
> > > > > >
> > > > > > LINKTABLE_START(__jump_table)
> > > > > > LINKTABLE_END(__jump_table)
> > > > > >
> > > > > > Then do we need to even have the LINUX_SECTION middle man at all?  
> > > > >
> > > > > Ah, thing is we use this for both linktables and section ranges.
> > > > > Or do we want macros for both that do the same thing ?  
> > > >
> > > > I think it would make the code using it more readable.  
> > >
> > > Alrighty... so:
> > >
> > > LINKTABLE_START()
> > > LINKTABLE_END()
> > >
> > > SECTION_RANGE_START()
> > > SECTION_RANGE_END()
> > >
> > > And these macros do the exact same thing. Ie, nothing shared. Right?  
> >
> > Yeah I think so. Internally they would probably be aliased to the
> > same common definition (unless you had some type check or something),
> > but user would know about such details.  
> 
> What name should we use for such common macro definition ?


Ah, not really sure. I guess the "link table" is some kind of
section range? I haven't actually looked closely at both of them
in the subsequent patches. It matters less if it's not expected
to be used as an API though.

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-26  7:33                           ` Nicholas Piggin
  0 siblings, 0 replies; 480+ messages in thread
From: Nicholas Piggin @ 2016-08-26  7:33 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: benh, jani.nikula, masami.hiramatsu.pt, linux, linux-kbuild,
	linux-sh, luto, gnomes, jcmvbkbc, torvalds, akpm, dwmw2,
	xen-devel, anil.s.keshavamurthy, will.deacon, linux-ia64, x86,
	korea.drzix, mingo, andrew.cooper3, jgross, tglx, keescook,
	ananth, jpoimboe, rostedt, hpa, acme, arnd, davem,
	platform-driver-x86, jkosina, david.vrabel, James.Bottomley,
	realmz6, fontana, mpe, konrad.wilk, ananth, paulus,
	paul.gortmaker, pali.rohar, mchehab, ak, pebolle, chris, jbaron,
	markus.heiser, mmarek, rusty, linux-xtensa, tony.luck,
	catalin.marinas, jolsa, dvhart, msalter, linux-arm-kernel,
	ming.lei, linux, andriy.shevchenko, linux-arch, mcb30,
	heiko.carstens, gregkh, mhiramat, bp, sparclinux, alan

On Thu, 25 Aug 2016 23:38:44 -0700
"Luis R. Rodriguez" <mcgrof@kernel.org> wrote:

> On Aug 25, 2016 8:00 PM, "Nicholas Piggin" <npiggin@gmail.com> wrote:
> >
> > On Thu, 25 Aug 2016 19:52:39 +0200
> > "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> >  
> > > On Thu, Aug 25, 2016 at 04:51:21PM +1000, Nicholas Piggin wrote:  
> > > > On Thu, 25 Aug 2016 08:05:40 +0200
> > > > "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:  
> > > > > > Oh, that makes more sense. The SECTION stuff and custom sections  
> was
> > > > > > confusing me. I would prefer just to drop all the LINUX_SECTION  
> naming
> > > > > > and make it match the functionality you're using. For example:
> > > > > >
> > > > > > +DEFINE_LINKTABLE(struct jump_entry, __jump_table);
> > > > > > +
> > > > > >  /* mutex to protect coming/going of the the jump_label table */
> > > > > >  static DEFINE_MUTEX(jump_label_mutex);
> > > > > >
> > > > > > @@ -274,8 +277,6 @@ static void __jump_label_update(struct  
> static_key *key,
> > > > > >
> > > > > >  void __init jump_label_init(void)
> > > > > >  {
> > > > > > -       struct jump_entry *iter_start = __start___jump_table;
> > > > > > -       struct jump_entry *iter_stop = __stop___jump_table;
> > > > > >         struct static_key *key = NULL;
> > > > > >         struct jump_entry *iter;
> > > > > >
> > > > > > @@ -292,9 +293,10 @@ void __init jump_label_init(void)
> > > > > >                 return;
> > > > > >
> > > > > >         jump_label_lock();
> > > > > > -       jump_label_sort_entries(iter_start, iter_stop);
> > > > > > +       jump_label_sort_entries(LINUX_SECTION_START(__jump_table),
> > > > > > +                               LINUX_SECTION_END(__jump_table));
> > > > > >
> > > > > > Now I think this is a fine abstraction to have.  
> > > > >
> > > > > OK will keep this one.
> > > > >  
> > > > > > I think it would look
> > > > > > even cleaner if you had:
> > > > > >
> > > > > > LINKTABLE_START(__jump_table)
> > > > > > LINKTABLE_END(__jump_table)
> > > > > >
> > > > > > Then do we need to even have the LINUX_SECTION middle man at all?  
> > > > >
> > > > > Ah, thing is we use this for both linktables and section ranges.
> > > > > Or do we want macros for both that do the same thing ?  
> > > >
> > > > I think it would make the code using it more readable.  
> > >
> > > Alrighty... so:
> > >
> > > LINKTABLE_START()
> > > LINKTABLE_END()
> > >
> > > SECTION_RANGE_START()
> > > SECTION_RANGE_END()
> > >
> > > And these macros do the exact same thing. Ie, nothing shared. Right?  
> >
> > Yeah I think so. Internally they would probably be aliased to the
> > same common definition (unless you had some type check or something),
> > but user would know about such details.  
> 
> What name should we use for such common macro definition ?


Ah, not really sure. I guess the "link table" is some kind of
section range? I haven't actually looked closely at both of them
in the subsequent patches. It matters less if it's not expected
to be used as an API though.

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
  2016-08-26  7:33                           ` Nicholas Piggin
  (?)
@ 2016-08-26 13:22                             ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-26 13:22 UTC (permalink / raw)
  To: Nicholas Piggin
  Cc: gnomes, linux-ia64, realmz6, linux-sh, benh, ming.lei,
	heiko.carstens, linux, platform-driver-x86, James.Bottomley,
	jcmvbkbc, paulus, hpa, masami.hiramatsu.pt, mchehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, msalter, davem, mpe, x86,
	anil.s.keshavamurthy, fontana, mingo, catalin.marinas, dvhart,
	dwmw2, mhiramat, linux-xtensa, rusty, keescook, arnd,
	linux-kbuild, jani.nikula

On Fri, Aug 26, 2016 at 05:33:38PM +1000, Nicholas Piggin wrote:
> On Thu, 25 Aug 2016 23:38:44 -0700
> "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> > > > > > Ah, thing is we use this for both linktables and section ranges.
> > > > > > Or do we want macros for both that do the same thing ?  
> > > > >
> > > > > I think it would make the code using it more readable.  
> > > >
> > > > Alrighty... so:
> > > >
> > > > LINKTABLE_START()
> > > > LINKTABLE_END()
> > > >
> > > > SECTION_RANGE_START()
> > > > SECTION_RANGE_END()
> > > >
> > > > And these macros do the exact same thing. Ie, nothing shared. Right?  
> > >
> > > Yeah I think so. Internally they would probably be aliased to the
> > > same common definition (unless you had some type check or something),
> > > but user would know about such details.  
> > 
> > What name should we use for such common macro definition ?
> 
> 
> Ah, not really sure. I guess the "link table" is some kind of
> section range? I haven't actually looked closely at both of them
> in the subsequent patches. It matters less if it's not expected
> to be used as an API though.
> 

OK well, going with LINUX_SECTION_START() so we'll have:

#define LINKTABLE_START		LINUX_SECTION_START
#define LINKTABLE_END		LINUX_SECTION_END

#define SECTION_RANGE_START	LINUX_SECTION_START
#define SECTION_RANGE_END	LINUX_SECTION_END

Is that OK?

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-26 13:22                             ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-26 13:22 UTC (permalink / raw)
  To: Nicholas Piggin
  Cc: gnomes, linux-ia64, realmz6, linux-sh, benh, ming.lei,
	heiko.carstens, linux, platform-driver-x86, James.Bottomley,
	jcmvbkbc, paulus, hpa, masami.hiramatsu.pt, mchehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, msalter, davem, mpe, x86,
	anil.s.keshavamurthy, fontana, mingo, catalin.marinas, dvhart,
	dwmw2, mhiramat, linux-xtensa, rusty, keescook, arnd,
	linux-kbuild, jani.nikula

On Fri, Aug 26, 2016 at 05:33:38PM +1000, Nicholas Piggin wrote:
> On Thu, 25 Aug 2016 23:38:44 -0700
> "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> > > > > > Ah, thing is we use this for both linktables and section ranges.
> > > > > > Or do we want macros for both that do the same thing ?  
> > > > >
> > > > > I think it would make the code using it more readable.  
> > > >
> > > > Alrighty... so:
> > > >
> > > > LINKTABLE_START()
> > > > LINKTABLE_END()
> > > >
> > > > SECTION_RANGE_START()
> > > > SECTION_RANGE_END()
> > > >
> > > > And these macros do the exact same thing. Ie, nothing shared. Right?  
> > >
> > > Yeah I think so. Internally they would probably be aliased to the
> > > same common definition (unless you had some type check or something),
> > > but user would know about such details.  
> > 
> > What name should we use for such common macro definition ?
> 
> 
> Ah, not really sure. I guess the "link table" is some kind of
> section range? I haven't actually looked closely at both of them
> in the subsequent patches. It matters less if it's not expected
> to be used as an API though.
> 

OK well, going with LINUX_SECTION_START() so we'll have:

#define LINKTABLE_START		LINUX_SECTION_START
#define LINKTABLE_END		LINUX_SECTION_END

#define SECTION_RANGE_START	LINUX_SECTION_START
#define SECTION_RANGE_END	LINUX_SECTION_END

Is that OK?

  Luis

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-26 13:22                             ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-26 13:22 UTC (permalink / raw)
  To: Nicholas Piggin
  Cc: Luis R. Rodriguez, benh, jani.nikula, masami.hiramatsu.pt, linux,
	linux-kbuild, linux-sh, luto, gnomes, jcmvbkbc, torvalds, akpm,
	dwmw2, xen-devel, anil.s.keshavamurthy, will.deacon, linux-ia64,
	x86, korea.drzix, mingo, andrew.cooper3, jgross, tglx, keescook,
	ananth, jpoimboe, rostedt, hpa, acme, arnd, davem,
	platform-driver-x86, jkosina, david.vrabel, James.Bottomley,
	realmz6, fontana, mpe, konrad.wilk, ananth, paulus,
	paul.gortmaker, pali.rohar, mchehab, ak, pebolle, chris, jbaron,
	markus.heiser, mmarek, rusty, linux-xtensa, tony.luck,
	catalin.marinas, jolsa, dvhart, msalter, linux-arm-kernel,
	ming.lei, linux, andriy.shevchenko, linux-arch, mcb30,
	heiko.carstens, gregkh, mhiramat, bp, sparclinux, alan

On Fri, Aug 26, 2016 at 05:33:38PM +1000, Nicholas Piggin wrote:
> On Thu, 25 Aug 2016 23:38:44 -0700
> "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> > > > > > Ah, thing is we use this for both linktables and section ranges.
> > > > > > Or do we want macros for both that do the same thing ?  
> > > > >
> > > > > I think it would make the code using it more readable.  
> > > >
> > > > Alrighty... so:
> > > >
> > > > LINKTABLE_START()
> > > > LINKTABLE_END()
> > > >
> > > > SECTION_RANGE_START()
> > > > SECTION_RANGE_END()
> > > >
> > > > And these macros do the exact same thing. Ie, nothing shared. Right?  
> > >
> > > Yeah I think so. Internally they would probably be aliased to the
> > > same common definition (unless you had some type check or something),
> > > but user would know about such details.  
> > 
> > What name should we use for such common macro definition ?
> 
> 
> Ah, not really sure. I guess the "link table" is some kind of
> section range? I haven't actually looked closely at both of them
> in the subsequent patches. It matters less if it's not expected
> to be used as an API though.
> 

OK well, going with LINUX_SECTION_START() so we'll have:

#define LINKTABLE_START		LINUX_SECTION_START
#define LINKTABLE_END		LINUX_SECTION_END

#define SECTION_RANGE_START	LINUX_SECTION_START
#define SECTION_RANGE_END	LINUX_SECTION_END

Is that OK?

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
  2016-08-26 13:22                             ` Luis R. Rodriguez
  (?)
@ 2016-08-26 13:28                               ` Nicholas Piggin
  -1 siblings, 0 replies; 480+ messages in thread
From: Nicholas Piggin @ 2016-08-26 13:28 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: benh, jani.nikula, masami.hiramatsu.pt, linux, linux-kbuild,
	linux-sh, luto, gnomes, jcmvbkbc, torvalds, akpm, dwmw2,
	xen-devel, anil.s.keshavamurthy, will.deacon, linux-ia64, x86,
	korea.drzix, mingo, andrew.cooper3, jgross, tglx, keescook,
	ananth, jpoimboe, rostedt, hpa, acme, arnd, davem,
	platform-driver-x86, jkosina, david.vrabel

On Fri, 26 Aug 2016 15:22:19 +0200
"Luis R. Rodriguez" <mcgrof@kernel.org> wrote:

> On Fri, Aug 26, 2016 at 05:33:38PM +1000, Nicholas Piggin wrote:
> > On Thu, 25 Aug 2016 23:38:44 -0700
> > "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:  
> > > > > > > Ah, thing is we use this for both linktables and section ranges.
> > > > > > > Or do we want macros for both that do the same thing ?    
> > > > > >
> > > > > > I think it would make the code using it more readable.    
> > > > >
> > > > > Alrighty... so:
> > > > >
> > > > > LINKTABLE_START()
> > > > > LINKTABLE_END()
> > > > >
> > > > > SECTION_RANGE_START()
> > > > > SECTION_RANGE_END()
> > > > >
> > > > > And these macros do the exact same thing. Ie, nothing shared. Right?    
> > > >
> > > > Yeah I think so. Internally they would probably be aliased to the
> > > > same common definition (unless you had some type check or something),
> > > > but user would know about such details.    
> > > 
> > > What name should we use for such common macro definition ?  
> > 
> > 
> > Ah, not really sure. I guess the "link table" is some kind of
> > section range? I haven't actually looked closely at both of them
> > in the subsequent patches. It matters less if it's not expected
> > to be used as an API though.
> >   
> 
> OK well, going with LINUX_SECTION_START() so we'll have:
> 
> #define LINKTABLE_START		LINUX_SECTION_START
> #define LINKTABLE_END		LINUX_SECTION_END
> 
> #define SECTION_RANGE_START	LINUX_SECTION_START
> #define SECTION_RANGE_END	LINUX_SECTION_END
> 
> Is that OK?

I guess so, without having seen the updated, although I don't see why
you'd not just

#define LINKTABLE_START SECTION_RANGE_START

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-26 13:28                               ` Nicholas Piggin
  0 siblings, 0 replies; 480+ messages in thread
From: Nicholas Piggin @ 2016-08-26 13:28 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: benh, jani.nikula, masami.hiramatsu.pt, linux, linux-kbuild,
	linux-sh, luto, gnomes, jcmvbkbc, torvalds, akpm, dwmw2,
	xen-devel, anil.s.keshavamurthy, will.deacon, linux-ia64, x86,
	korea.drzix, mingo, andrew.cooper3, jgross, tglx, keescook,
	ananth, jpoimboe, rostedt, hpa, acme, arnd, davem,
	platform-driver-x86, jkosina, david.vrabel

On Fri, 26 Aug 2016 15:22:19 +0200
"Luis R. Rodriguez" <mcgrof@kernel.org> wrote:

> On Fri, Aug 26, 2016 at 05:33:38PM +1000, Nicholas Piggin wrote:
> > On Thu, 25 Aug 2016 23:38:44 -0700
> > "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:  
> > > > > > > Ah, thing is we use this for both linktables and section ranges.
> > > > > > > Or do we want macros for both that do the same thing ?    
> > > > > >
> > > > > > I think it would make the code using it more readable.    
> > > > >
> > > > > Alrighty... so:
> > > > >
> > > > > LINKTABLE_START()
> > > > > LINKTABLE_END()
> > > > >
> > > > > SECTION_RANGE_START()
> > > > > SECTION_RANGE_END()
> > > > >
> > > > > And these macros do the exact same thing. Ie, nothing shared. Right?    
> > > >
> > > > Yeah I think so. Internally they would probably be aliased to the
> > > > same common definition (unless you had some type check or something),
> > > > but user would know about such details.    
> > > 
> > > What name should we use for such common macro definition ?  
> > 
> > 
> > Ah, not really sure. I guess the "link table" is some kind of
> > section range? I haven't actually looked closely at both of them
> > in the subsequent patches. It matters less if it's not expected
> > to be used as an API though.
> >   
> 
> OK well, going with LINUX_SECTION_START() so we'll have:
> 
> #define LINKTABLE_START		LINUX_SECTION_START
> #define LINKTABLE_END		LINUX_SECTION_END
> 
> #define SECTION_RANGE_START	LINUX_SECTION_START
> #define SECTION_RANGE_END	LINUX_SECTION_END
> 
> Is that OK?

I guess so, without having seen the updated, although I don't see why
you'd not just

#define LINKTABLE_START SECTION_RANGE_START

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 04/16] generic-sections: add section core helpers
@ 2016-08-26 13:28                               ` Nicholas Piggin
  0 siblings, 0 replies; 480+ messages in thread
From: Nicholas Piggin @ 2016-08-26 13:28 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: benh, jani.nikula, masami.hiramatsu.pt, linux, linux-kbuild,
	linux-sh, luto, gnomes, jcmvbkbc, torvalds, akpm, dwmw2,
	xen-devel, anil.s.keshavamurthy, will.deacon, linux-ia64, x86,
	korea.drzix, mingo, andrew.cooper3, jgross, tglx, keescook,
	ananth, jpoimboe, rostedt, hpa, acme, arnd, davem,
	platform-driver-x86, jkosina, david.vrabel, James.Bottomley,
	realmz6, fontana, mpe, konrad.wilk, ananth, paulus,
	paul.gortmaker, pali.rohar, mchehab, ak, pebolle, chris, jbaron,
	markus.heiser, mmarek, rusty, linux-xtensa, tony.luck,
	catalin.marinas, jolsa, dvhart, msalter, linux-arm-kernel,
	ming.lei, linux, andriy.shevchenko, linux-arch, mcb30,
	heiko.carstens, gregkh, mhiramat, bp, sparclinux, alan

On Fri, 26 Aug 2016 15:22:19 +0200
"Luis R. Rodriguez" <mcgrof@kernel.org> wrote:

> On Fri, Aug 26, 2016 at 05:33:38PM +1000, Nicholas Piggin wrote:
> > On Thu, 25 Aug 2016 23:38:44 -0700
> > "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:  
> > > > > > > Ah, thing is we use this for both linktables and section ranges.
> > > > > > > Or do we want macros for both that do the same thing ?    
> > > > > >
> > > > > > I think it would make the code using it more readable.    
> > > > >
> > > > > Alrighty... so:
> > > > >
> > > > > LINKTABLE_START()
> > > > > LINKTABLE_END()
> > > > >
> > > > > SECTION_RANGE_START()
> > > > > SECTION_RANGE_END()
> > > > >
> > > > > And these macros do the exact same thing. Ie, nothing shared. Right?    
> > > >
> > > > Yeah I think so. Internally they would probably be aliased to the
> > > > same common definition (unless you had some type check or something),
> > > > but user would know about such details.    
> > > 
> > > What name should we use for such common macro definition ?  
> > 
> > 
> > Ah, not really sure. I guess the "link table" is some kind of
> > section range? I haven't actually looked closely at both of them
> > in the subsequent patches. It matters less if it's not expected
> > to be used as an API though.
> >   
> 
> OK well, going with LINUX_SECTION_START() so we'll have:
> 
> #define LINKTABLE_START		LINUX_SECTION_START
> #define LINKTABLE_END		LINUX_SECTION_END
> 
> #define SECTION_RANGE_START	LINUX_SECTION_START
> #define SECTION_RANGE_END	LINUX_SECTION_END
> 
> Is that OK?

I guess so, without having seen the updated, although I don't see why
you'd not just

#define LINKTABLE_START SECTION_RANGE_START

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 14/16] kprobes: move kprobe declarations to asm-generic/kprobes.h
  2016-08-23 16:31         ` Luis R. Rodriguez
  (?)
@ 2016-08-29 14:04           ` Masami Hiramatsu
  -1 siblings, 0 replies; 480+ messages in thread
From: Masami Hiramatsu @ 2016-08-29 14:04 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: hpa, tglx, mingo, jpoimboe, bp, linux, masami.hiramatsu.pt,
	jbaron, heiko.carstens, ananth, anil.s.keshavamurthy, davem,
	realmz6, x86, luto, keescook, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchen

On Tue, 23 Aug 2016 18:31:05 +0200
"Luis R. Rodriguez" <mcgrof@kernel.org> wrote:

> On Tue, Aug 23, 2016 at 12:11:40AM +0900, Masami Hiramatsu wrote:
> > On Fri, 19 Aug 2016 14:34:12 -0700
> > mcgrof@kernel.org wrote:
> > 
> > > From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> > > 
> > > Often all is needed is these small helpers, instead of compiler.h
> > > or a full kprobes.h. This is important for asm helpers, in fact even
> > > some asm/kprobes.h make use of these helpers... instead just keep a
> > > generic asm file with helpers useful for asm code with the least amount
> > > of clutter as possible.
> > > 
> > > Likewise we need now to also address what to do about this file for both
> > > when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
> > > for when architectures have CONFIG_HAVE_KPROBES but have disabled
> > > CONFIG_KPROBES.
> > > 
> > > Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
> > > this means most architecture code cannot include asm/kprobes.h safely.
> > > Correct this and add guards for architectures missing them. Additionally
> > > provide architectures that not have kprobes support with the default
> > > asm-generic solution. This lets us force asm/kprobes.h on the header
> > > include/linux/kprobes.h always, but most importantly we can now safely
> > > include just asm/kprobes.h on architecture code without bringing
> > > the full kitchen sink of header files.
> > > 
> > > Two architectures already provided a guard against CONFIG_KPROBES on
> > > its kprobes.h: sh, arch. The rest of the architectures needed gaurds
> > > added. We avoid including any not-needed headers on asm/kprobes.h
> > > unless kprobes have been enabled.
> > > 
> > > In a subsequent atomic change we can try now to remove compiler.h from
> > > include/linux/kprobes.h.
> > 
> > Hmm, this looks a bit overkill... I rather like move it into linux/table.h.
> 
> That's the thing, we can't reasonably expect every table to add an entry into
> table.h, this should be up to each user. Moving it to tables.h just prolongs
> what needs to be done. In this case the change is justifiable given kprobe
> annotations are required for some architectures early in architecture code, and
> including compiler.h on early architecture code blows up. There is no easy fix
> to this, and this this was *actually* the cleanest solution I could devise
> without much changes.

Aah, I misread your patch, it is asm-generic/kprobes.h, not asm/kprobes.h.
I think it is OK now.

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>

Thanks!

> 
>   Luis


-- 
Masami Hiramatsu <mhiramat@kernel.org>

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 14/16] kprobes: move kprobe declarations to asm-generic/kprobes.h
@ 2016-08-29 14:04           ` Masami Hiramatsu
  0 siblings, 0 replies; 480+ messages in thread
From: Masami Hiramatsu @ 2016-08-29 14:04 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: hpa, tglx, mingo, jpoimboe, bp, linux, masami.hiramatsu.pt,
	jbaron, heiko.carstens, ananth, anil.s.keshavamurthy, davem,
	realmz6, x86, luto, keescook, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchen

On Tue, 23 Aug 2016 18:31:05 +0200
"Luis R. Rodriguez" <mcgrof@kernel.org> wrote:

> On Tue, Aug 23, 2016 at 12:11:40AM +0900, Masami Hiramatsu wrote:
> > On Fri, 19 Aug 2016 14:34:12 -0700
> > mcgrof@kernel.org wrote:
> > 
> > > From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> > > 
> > > Often all is needed is these small helpers, instead of compiler.h
> > > or a full kprobes.h. This is important for asm helpers, in fact even
> > > some asm/kprobes.h make use of these helpers... instead just keep a
> > > generic asm file with helpers useful for asm code with the least amount
> > > of clutter as possible.
> > > 
> > > Likewise we need now to also address what to do about this file for both
> > > when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
> > > for when architectures have CONFIG_HAVE_KPROBES but have disabled
> > > CONFIG_KPROBES.
> > > 
> > > Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
> > > this means most architecture code cannot include asm/kprobes.h safely.
> > > Correct this and add guards for architectures missing them. Additionally
> > > provide architectures that not have kprobes support with the default
> > > asm-generic solution. This lets us force asm/kprobes.h on the header
> > > include/linux/kprobes.h always, but most importantly we can now safely
> > > include just asm/kprobes.h on architecture code without bringing
> > > the full kitchen sink of header files.
> > > 
> > > Two architectures already provided a guard against CONFIG_KPROBES on
> > > its kprobes.h: sh, arch. The rest of the architectures needed gaurds
> > > added. We avoid including any not-needed headers on asm/kprobes.h
> > > unless kprobes have been enabled.
> > > 
> > > In a subsequent atomic change we can try now to remove compiler.h from
> > > include/linux/kprobes.h.
> > 
> > Hmm, this looks a bit overkill... I rather like move it into linux/table.h.
> 
> That's the thing, we can't reasonably expect every table to add an entry into
> table.h, this should be up to each user. Moving it to tables.h just prolongs
> what needs to be done. In this case the change is justifiable given kprobe
> annotations are required for some architectures early in architecture code, and
> including compiler.h on early architecture code blows up. There is no easy fix
> to this, and this this was *actually* the cleanest solution I could devise
> without much changes.

Aah, I misread your patch, it is asm-generic/kprobes.h, not asm/kprobes.h.
I think it is OK now.

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>

Thanks!

> 
>   Luis


-- 
Masami Hiramatsu <mhiramat@kernel.org>

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 14/16] kprobes: move kprobe declarations to asm-generic/kprobes.h
@ 2016-08-29 14:04           ` Masami Hiramatsu
  0 siblings, 0 replies; 480+ messages in thread
From: Masami Hiramatsu @ 2016-08-29 14:04 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: hpa, tglx, mingo, jpoimboe, bp, linux, masami.hiramatsu.pt,
	jbaron, heiko.carstens, ananth, anil.s.keshavamurthy, davem,
	realmz6, x86, luto, keescook, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, ananth, pebolle,
	fontana, david.vrabel, konrad.wilk, mcb30, jgross,
	andrew.cooper3, andriy.shevchenko, paul.gortmaker, xen-devel, ak,
	pali.rohar, dvhart, platform-driver-x86, mmarek, linux, jkosina,
	korea.drzix, linux-kbuild, tony.luck, akpm, linux-ia64,
	linux-arm-kernel, linux-sh, sparclinux, catalin.marinas,
	will.deacon, rostedt, jani.nikula, mchehab, markus.heiser, acme,
	jolsa, msalter, chris, jcmvbkbc, linux-xtensa, paulus, mpe,
	James.Bottomley

On Tue, 23 Aug 2016 18:31:05 +0200
"Luis R. Rodriguez" <mcgrof@kernel.org> wrote:

> On Tue, Aug 23, 2016 at 12:11:40AM +0900, Masami Hiramatsu wrote:
> > On Fri, 19 Aug 2016 14:34:12 -0700
> > mcgrof@kernel.org wrote:
> > 
> > > From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> > > 
> > > Often all is needed is these small helpers, instead of compiler.h
> > > or a full kprobes.h. This is important for asm helpers, in fact even
> > > some asm/kprobes.h make use of these helpers... instead just keep a
> > > generic asm file with helpers useful for asm code with the least amount
> > > of clutter as possible.
> > > 
> > > Likewise we need now to also address what to do about this file for both
> > > when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
> > > for when architectures have CONFIG_HAVE_KPROBES but have disabled
> > > CONFIG_KPROBES.
> > > 
> > > Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
> > > this means most architecture code cannot include asm/kprobes.h safely.
> > > Correct this and add guards for architectures missing them. Additionally
> > > provide architectures that not have kprobes support with the default
> > > asm-generic solution. This lets us force asm/kprobes.h on the header
> > > include/linux/kprobes.h always, but most importantly we can now safely
> > > include just asm/kprobes.h on architecture code without bringing
> > > the full kitchen sink of header files.
> > > 
> > > Two architectures already provided a guard against CONFIG_KPROBES on
> > > its kprobes.h: sh, arch. The rest of the architectures needed gaurds
> > > added. We avoid including any not-needed headers on asm/kprobes.h
> > > unless kprobes have been enabled.
> > > 
> > > In a subsequent atomic change we can try now to remove compiler.h from
> > > include/linux/kprobes.h.
> > 
> > Hmm, this looks a bit overkill... I rather like move it into linux/table.h.
> 
> That's the thing, we can't reasonably expect every table to add an entry into
> table.h, this should be up to each user. Moving it to tables.h just prolongs
> what needs to be done. In this case the change is justifiable given kprobe
> annotations are required for some architectures early in architecture code, and
> including compiler.h on early architecture code blows up. There is no easy fix
> to this, and this this was *actually* the cleanest solution I could devise
> without much changes.

Aah, I misread your patch, it is asm-generic/kprobes.h, not asm/kprobes.h.
I think it is OK now.

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>

Thanks!

> 
>   Luis


-- 
Masami Hiramatsu <mhiramat@kernel.org>

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 14/16] kprobes: move kprobe declarations to asm-generic/kprobes.h
  2016-08-29 14:04           ` Masami Hiramatsu
  (?)
@ 2016-08-30 20:07             ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-30 20:07 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: Luis R. Rodriguez, hpa, tglx, mingo, jpoimboe, bp, linux,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross

On Mon, Aug 29, 2016 at 11:04:18PM +0900, Masami Hiramatsu wrote:
> On Tue, 23 Aug 2016 18:31:05 +0200
> "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> 
> > On Tue, Aug 23, 2016 at 12:11:40AM +0900, Masami Hiramatsu wrote:
> > > On Fri, 19 Aug 2016 14:34:12 -0700
> > > mcgrof@kernel.org wrote:
> > > 
> > > > From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> > > > 
> > > > Often all is needed is these small helpers, instead of compiler.h
> > > > or a full kprobes.h. This is important for asm helpers, in fact even
> > > > some asm/kprobes.h make use of these helpers... instead just keep a
> > > > generic asm file with helpers useful for asm code with the least amount
> > > > of clutter as possible.
> > > > 
> > > > Likewise we need now to also address what to do about this file for both
> > > > when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
> > > > for when architectures have CONFIG_HAVE_KPROBES but have disabled
> > > > CONFIG_KPROBES.
> > > > 
> > > > Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
> > > > this means most architecture code cannot include asm/kprobes.h safely.
> > > > Correct this and add guards for architectures missing them. Additionally
> > > > provide architectures that not have kprobes support with the default
> > > > asm-generic solution. This lets us force asm/kprobes.h on the header
> > > > include/linux/kprobes.h always, but most importantly we can now safely
> > > > include just asm/kprobes.h on architecture code without bringing
> > > > the full kitchen sink of header files.
> > > > 
> > > > Two architectures already provided a guard against CONFIG_KPROBES on
> > > > its kprobes.h: sh, arch. The rest of the architectures needed gaurds
> > > > added. We avoid including any not-needed headers on asm/kprobes.h
> > > > unless kprobes have been enabled.
> > > > 
> > > > In a subsequent atomic change we can try now to remove compiler.h from
> > > > include/linux/kprobes.h.
> > > 
> > > Hmm, this looks a bit overkill... I rather like move it into linux/table.h.
> > 
> > That's the thing, we can't reasonably expect every table to add an entry into
> > table.h, this should be up to each user. Moving it to tables.h just prolongs
> > what needs to be done. In this case the change is justifiable given kprobe
> > annotations are required for some architectures early in architecture code, and
> > including compiler.h on early architecture code blows up. There is no easy fix
> > to this, and this this was *actually* the cleanest solution I could devise
> > without much changes.
> 
> Aah, I misread your patch, it is asm-generic/kprobes.h, not asm/kprobes.h.
> I think it is OK now.
> 
> Acked-by: Masami Hiramatsu <mhiramat@kernel.org>

Thanks! Can you also review: patch 15:

kprobes: port .kprobes.text to section range

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 14/16] kprobes: move kprobe declarations to asm-generic/kprobes.h
@ 2016-08-30 20:07             ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-30 20:07 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: Luis R. Rodriguez, hpa, tglx, mingo, jpoimboe, bp, linux,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross

On Mon, Aug 29, 2016 at 11:04:18PM +0900, Masami Hiramatsu wrote:
> On Tue, 23 Aug 2016 18:31:05 +0200
> "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> 
> > On Tue, Aug 23, 2016 at 12:11:40AM +0900, Masami Hiramatsu wrote:
> > > On Fri, 19 Aug 2016 14:34:12 -0700
> > > mcgrof@kernel.org wrote:
> > > 
> > > > From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> > > > 
> > > > Often all is needed is these small helpers, instead of compiler.h
> > > > or a full kprobes.h. This is important for asm helpers, in fact even
> > > > some asm/kprobes.h make use of these helpers... instead just keep a
> > > > generic asm file with helpers useful for asm code with the least amount
> > > > of clutter as possible.
> > > > 
> > > > Likewise we need now to also address what to do about this file for both
> > > > when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
> > > > for when architectures have CONFIG_HAVE_KPROBES but have disabled
> > > > CONFIG_KPROBES.
> > > > 
> > > > Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
> > > > this means most architecture code cannot include asm/kprobes.h safely.
> > > > Correct this and add guards for architectures missing them. Additionally
> > > > provide architectures that not have kprobes support with the default
> > > > asm-generic solution. This lets us force asm/kprobes.h on the header
> > > > include/linux/kprobes.h always, but most importantly we can now safely
> > > > include just asm/kprobes.h on architecture code without bringing
> > > > the full kitchen sink of header files.
> > > > 
> > > > Two architectures already provided a guard against CONFIG_KPROBES on
> > > > its kprobes.h: sh, arch. The rest of the architectures needed gaurds
> > > > added. We avoid including any not-needed headers on asm/kprobes.h
> > > > unless kprobes have been enabled.
> > > > 
> > > > In a subsequent atomic change we can try now to remove compiler.h from
> > > > include/linux/kprobes.h.
> > > 
> > > Hmm, this looks a bit overkill... I rather like move it into linux/table.h.
> > 
> > That's the thing, we can't reasonably expect every table to add an entry into
> > table.h, this should be up to each user. Moving it to tables.h just prolongs
> > what needs to be done. In this case the change is justifiable given kprobe
> > annotations are required for some architectures early in architecture code, and
> > including compiler.h on early architecture code blows up. There is no easy fix
> > to this, and this this was *actually* the cleanest solution I could devise
> > without much changes.
> 
> Aah, I misread your patch, it is asm-generic/kprobes.h, not asm/kprobes.h.
> I think it is OK now.
> 
> Acked-by: Masami Hiramatsu <mhiramat@kernel.org>

Thanks! Can you also review: patch 15:

kprobes: port .kprobes.text to section range

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 14/16] kprobes: move kprobe declarations to asm-generic/kprobes.h
@ 2016-08-30 20:07             ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-30 20:07 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: Luis R. Rodriguez, hpa, tglx, mingo, jpoimboe, bp, linux,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, acme, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, paulus, mpe, James.Bottomley

On Mon, Aug 29, 2016 at 11:04:18PM +0900, Masami Hiramatsu wrote:
> On Tue, 23 Aug 2016 18:31:05 +0200
> "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> 
> > On Tue, Aug 23, 2016 at 12:11:40AM +0900, Masami Hiramatsu wrote:
> > > On Fri, 19 Aug 2016 14:34:12 -0700
> > > mcgrof@kernel.org wrote:
> > > 
> > > > From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> > > > 
> > > > Often all is needed is these small helpers, instead of compiler.h
> > > > or a full kprobes.h. This is important for asm helpers, in fact even
> > > > some asm/kprobes.h make use of these helpers... instead just keep a
> > > > generic asm file with helpers useful for asm code with the least amount
> > > > of clutter as possible.
> > > > 
> > > > Likewise we need now to also address what to do about this file for both
> > > > when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
> > > > for when architectures have CONFIG_HAVE_KPROBES but have disabled
> > > > CONFIG_KPROBES.
> > > > 
> > > > Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
> > > > this means most architecture code cannot include asm/kprobes.h safely.
> > > > Correct this and add guards for architectures missing them. Additionally
> > > > provide architectures that not have kprobes support with the default
> > > > asm-generic solution. This lets us force asm/kprobes.h on the header
> > > > include/linux/kprobes.h always, but most importantly we can now safely
> > > > include just asm/kprobes.h on architecture code without bringing
> > > > the full kitchen sink of header files.
> > > > 
> > > > Two architectures already provided a guard against CONFIG_KPROBES on
> > > > its kprobes.h: sh, arch. The rest of the architectures needed gaurds
> > > > added. We avoid including any not-needed headers on asm/kprobes.h
> > > > unless kprobes have been enabled.
> > > > 
> > > > In a subsequent atomic change we can try now to remove compiler.h from
> > > > include/linux/kprobes.h.
> > > 
> > > Hmm, this looks a bit overkill... I rather like move it into linux/table.h.
> > 
> > That's the thing, we can't reasonably expect every table to add an entry into
> > table.h, this should be up to each user. Moving it to tables.h just prolongs
> > what needs to be done. In this case the change is justifiable given kprobe
> > annotations are required for some architectures early in architecture code, and
> > including compiler.h on early architecture code blows up. There is no easy fix
> > to this, and this this was *actually* the cleanest solution I could devise
> > without much changes.
> 
> Aah, I misread your patch, it is asm-generic/kprobes.h, not asm/kprobes.h.
> I think it is OK now.
> 
> Acked-by: Masami Hiramatsu <mhiramat@kernel.org>

Thanks! Can you also review: patch 15:

kprobes: port .kprobes.text to section range

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 08/16] kbuild: enable option to force compile force-obj-y and force-lib-y
  2016-08-22 23:59     ` Luis R. Rodriguez
@ 2016-08-30 20:15       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-08-30 20:15 UTC (permalink / raw)
  To: Luis R. Rodriguez, Michal Marek
  Cc: gnomes, linux-ia64, Jiri Kosina, benh, Ming Lei, Heiko Carstens,
	platform-driver-x86, James Bottomley, Paul Gortmaker,
	Paul Mackerras, Michael Ellerman, H. Peter Anvin,
	Masami Hiramatsu, Mauro Carvalho Chehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, Russell King - ARM Linux,
	linux-sh, Will Deacon

On Tue, Aug 23, 2016 at 01:59:10AM +0200, Luis R. Rodriguez wrote:
> On Fri, Aug 19, 2016 at 03:10:33PM -0700, Kees Cook wrote:
> > On Fri, Aug 19, 2016 at 2:32 PM,  <mcgrof@kernel.org> wrote:
> > > diff --git a/init/Kconfig b/init/Kconfig
> > > index cac3f096050d..ef09e83b9196 100644
> > > --- a/init/Kconfig
> > > +++ b/init/Kconfig
> > > @@ -53,6 +53,28 @@ config CROSS_COMPILE
> > >           need to set this unless you want the configured kernel build
> > >           directory to select the cross-compiler automatically.
> > >
> > > +config BUILD_AVOID_BITROT
> > > +       bool "Enable force building of force-obj-y and force-lib-y"
> > 
> > Sorry to continue the bikeshedding on this, but if I encounter
> > something in a Makefile named "force-obj-y" I would expect it to
> > always be built, no matter what. But this is not the case: the
> > "force-" prefix is tied to this CONFIG_BUILD_AVOID_BITROT. This verb
> > usage is weird, as I'd expect an adjective, like "forceable-obj-y" or
> > something that describes that it CAN be built even with the CONFIG for
> > it is missing, etc.
> > 
> > Regardless, I defer to Michal on this, but I'm not a fan of "force"
> > being used when it's an optional action. :)
> 
> Sure, Michal let me know if forceable-obj-y and forceable-lib-y is the
> way to go.

Michal? Any preference ? Or how about opt-force-obj ?

  Luis

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v5 00/14] linux: generalize sections, ranges and linker tables
  2016-08-19 21:33   ` mcgrof
  (?)
@ 2016-12-22  2:37     ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:37 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Posting this for *after* the merge window.

This v5 addresses feedback from the last v4 series [0] about 4 months ago.
The first RFC series was posted just 1 year ago, last December 15 [1], its
been a long way coming. The largest amount of feedback from the v4 series came
from Nicholas Piggin, I've also made a few more minor changes and enhancements.

Because I have gone on different conferences talking about this work I've
jotted down in a white-paper form what this is all about and I've used it as
basis for a huge brush up on the documentation. I have not included the
paper into the tree as I think the documentation now stands for itself. The
paper may be useful for those wanted a huge verbose explanation to things
with much more in depth analysis and review of history [2].

I've split up the linker table patches in two groups to make it easier to
review, the first set (this) is for the kernel work, the second set is for the
tools/ userspace sandbox. If you would like to review all the changes in git
form you can yank them off of my linux-next 20161221-linker-tables-v5 branch on
kernel.org [3], please however note that the last patch on that tree was *not*
submitted upstream, it was used to force test 0-day and also Guenter's testbed
to force-enable and run the tests. You can disregard that patch unless you also
want to force test things :)

The biggest changes since v4 series worth noting:

  o Ended up using two dots (..) to separate the new sections to avoid conflicts
    with compiler generated sections, so we have: .text..rng.*, .data..tbl.*,
    etc.

  o Remove all the macro magic for section names. We now expect you to
    spell out each section manually. So no more SECTION_TEXT, for instance,
    for instance, we use just naked .text.

  o Adds a section linker table selftest driver. I have a debug out of tree
    patch used which was applied when testing which force enables the driver
    to be built in. This has been successfully run time tested against the
    following architectures:

    alpha      arc        arcv2       arm       arm64       blackfin    c6x
    cris       crisv32    frv         h8300     hexagon     i386        ia64
    m32r       m68k       m68k_nommu  metag     microblaze  mips_22     mips_24
    mips_25    mn10300    nios2       openrisc  parisc      parisc64    powerpc
    s390       score      sh          sparc32   sparc64     tile        um
    unicore32  x86_64     xtensa

    The only architecture that was not tested was avr32 and that is because
    linux-next fails to compile on it. I'd like to greatly thank Guenter Roeck
    for his help with testing.

  o A documentation revamp, to align what I hard originally written in the
    v4 series more in alignment with the the ELF specifications. Also properly
    document mark_rodata_ro().

  o Recruited Josh Poimboeuf and hpa as co-mainters of the general section
    stuff. For section ranges and linker tables it will be both me and hpa
    reviewing things. At Plumbers I spoke with Arnd and he would prefer changes
    to go in through each respective tree that needs each change, so no new
    tree is created. We'll just review and Ack/nack changes.

Happy holidays, and may the force be with you all...

Oh and lastly, a quick summary of the gains of having an API for all this.

First the obvious gains:

  o Allows us to just use plain C code to add new program specific
    ELF sections
  o Makes it less error prone to add new sections

Then the not so obvious immediate gains:

  o Helps simplify initialization code
  o Helps optionally avoid code bit-rot (see commit "kbuild: enable option to
    force compile force-obj-y and force-lib-y)
  o Enables link time ordering which can help make an extremely lightweight
    dependency annotations explicit (for this refer to the tools/linker-tables/
    example where I've demo'd simplfying Xen PV init code, which has caused
    tons of regressions over time due to the lack of explicit dependency
    annotations due to the sloppy Xen PV entry path; this is not going away
    any time soon)

Not so obvious long term gains:

  o Run time ordering customization are still possible (this is really long
    term but we already have one precedent in the kernel that does memmove()
    on entries on a section per some dependency heuristic.)
  o May help prevent use of dead code by either free'ing / nop'ing, no exec
    or whatever sections which we know should definitely not run.
  o Can easily increase the levels of initialization in the kernel without
    much changes (refer to tools/linker-tables/ for an example init with
    linker tables). I've seen a few cases where we've already run out of space
    to get init right in a few subsystems. This not only allows this but also
    allows subsystems to define their own custom levels of init if they wanted
    for their own things.
  o Synthetic functions: enables custom C / asm functions which could help
    add new functionality (see synth_init_or() on tools/linker-tables/drivers/synth/main.c)
    I've been hinted this can help with RAID6 support
  o Self modifying consts (see ps_shr() on tools/linker-tables/drivers/synth/main.c)

[0] https://lkml.kernel.org/r/1471642454-5679-1-git-send-email-mcgrof@kernel.org
[1] https://lkml.kernel.org/r/1450217797-19295-1-git-send-email-mcgrof@do-not-panic.com
[2] http://drvbp1.linux-foundation.org/~mcgrof/papers/2016/12/21/linker-tables-20161221.pdf
[3] https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h 161221-linker-tables-v5

Luis R. Rodriguez (14):
  generic-sections: add section core helpers
  xtensa: skip adding literal when SORT() is used
  ranges.h: add helpers to build and identify Linux section ranges
  tables.h: add linker table support
  kbuild: enable option to force compile force-obj-y and force-lib-y
  firmware/Makefile: force recompilation if makefile changes
  firmware: port built-in section to linker table
  jump_label: move guard #endif down where it belongs
  jump_label: port __jump_table to linker tables
  dynamic_debug: port to use linker tables
  kprobes: move kprobe declarations to asm-generic/kprobes.h
  kprobes: port .kprobes.text to section range
  kprobes: port blacklist kprobes to linker table
  lib: add linker tables test driver

 Documentation/index.rst                   |   1 +
 Documentation/kbuild/makefiles.txt        |  36 ++
 Documentation/sections/background.rst     | 105 ++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  19 +
 Documentation/sections/linker-tables.rst  | 227 +++++++++
 Documentation/sections/ranges.rst         |  74 +++
 Documentation/sections/section-core.rst   | 153 ++++++
 MAINTAINERS                               |  32 ++
 arch/alpha/include/asm/Kbuild             |   4 +
 arch/arc/include/asm/Kbuild               |   3 +
 arch/arc/include/asm/kprobes.h            |   6 +-
 arch/arc/kernel/vmlinux.lds.S             |   1 -
 arch/arm/include/asm/Kbuild               |   3 +
 arch/arm/include/asm/jump_label.h         |   6 +-
 arch/arm/include/asm/kprobes.h            |   4 +
 arch/arm/kernel/entry-armv.S              |   3 +-
 arch/arm/kernel/vmlinux-xip.lds.S         |   1 -
 arch/arm/kernel/vmlinux.lds.S             |   1 -
 arch/arm/probes/decode.h                  |   1 +
 arch/arm64/include/asm/Kbuild             |   3 +
 arch/arm64/include/asm/jump_label.h       |   6 +-
 arch/arm64/include/asm/kprobes.h          |   4 +
 arch/arm64/kernel/armv8_deprecated.c      |   1 +
 arch/arm64/kernel/insn.c                  |   1 +
 arch/arm64/kernel/probes/decode-insn.h    |   2 +
 arch/arm64/kernel/probes/kprobes.c        |   4 +-
 arch/arm64/kernel/vmlinux.lds.S           |   1 -
 arch/avr32/include/asm/Kbuild             |   3 +
 arch/avr32/include/asm/kprobes.h          |   7 +-
 arch/avr32/kernel/entry-avr32b.S          |  13 +-
 arch/avr32/kernel/vmlinux.lds.S           |   1 -
 arch/blackfin/include/asm/Kbuild          |   4 +
 arch/blackfin/kernel/vmlinux.lds.S        |   1 -
 arch/c6x/include/asm/Kbuild               |   3 +
 arch/c6x/include/asm/tables.h             |  26 +
 arch/c6x/kernel/vmlinux.lds.S             |   1 -
 arch/cris/include/asm/Kbuild              |   4 +
 arch/frv/include/asm/Kbuild               |   4 +
 arch/h8300/include/asm/Kbuild             |   4 +
 arch/hexagon/include/asm/Kbuild           |   4 +
 arch/hexagon/kernel/vmlinux.lds.S         |   1 -
 arch/ia64/include/asm/Kbuild              |   3 +
 arch/ia64/include/asm/kprobes.h           |  12 +-
 arch/ia64/kernel/jprobes.S                |   3 +-
 arch/ia64/kernel/vmlinux.lds.S            |   1 -
 arch/ia64/lib/flush.S                     |   6 +-
 arch/m32r/include/asm/Kbuild              |   4 +
 arch/m68k/include/asm/Kbuild              |   4 +
 arch/metag/include/asm/Kbuild             |   4 +
 arch/metag/kernel/vmlinux.lds.S           |   1 -
 arch/microblaze/include/asm/Kbuild        |   4 +
 arch/microblaze/kernel/vmlinux.lds.S      |   1 -
 arch/mips/include/asm/Kbuild              |   3 +
 arch/mips/include/asm/jump_label.h        |   6 +-
 arch/mips/include/asm/kprobes.h           |   6 +-
 arch/mips/kernel/vmlinux.lds.S            |   1 -
 arch/mn10300/include/asm/Kbuild           |   3 +
 arch/mn10300/include/asm/kprobes.h        |   7 +-
 arch/mn10300/kernel/vmlinux.lds.S         |   1 -
 arch/nios2/include/asm/Kbuild             |   4 +
 arch/nios2/kernel/vmlinux.lds.S           |   1 -
 arch/openrisc/include/asm/Kbuild          |   4 +
 arch/openrisc/kernel/vmlinux.lds.S        |   1 -
 arch/parisc/include/asm/Kbuild            |   4 +
 arch/parisc/kernel/vmlinux.lds.S          |   1 -
 arch/powerpc/include/asm/Kbuild           |   3 +
 arch/powerpc/include/asm/jump_label.h     |   8 +-
 arch/powerpc/include/asm/kprobes.h        |   3 +
 arch/powerpc/include/asm/ppc_asm.h        |   3 +-
 arch/powerpc/kernel/vmlinux.lds.S         |   3 +-
 arch/s390/include/asm/Kbuild              |   3 +
 arch/s390/include/asm/jump_label.h        |   6 +-
 arch/s390/include/asm/kprobes.h           |   7 +-
 arch/s390/kernel/entry.S                  |   5 +-
 arch/s390/kernel/kprobes.c                |   6 +-
 arch/s390/kernel/mcount.S                 |   3 +-
 arch/s390/kernel/vmlinux.lds.S            |   1 -
 arch/score/include/asm/Kbuild             |   4 +
 arch/score/kernel/vmlinux.lds.S           |   1 -
 arch/sh/include/asm/Kbuild                |   3 +
 arch/sh/include/asm/kprobes.h             |   5 +-
 arch/sh/kernel/vmlinux.lds.S              |   1 -
 arch/sparc/include/asm/Kbuild             |   3 +
 arch/sparc/include/asm/jump_label.h       |   6 +-
 arch/sparc/include/asm/kprobes.h          |  10 +-
 arch/sparc/kernel/vmlinux.lds.S           |   1 -
 arch/sparc/mm/ultra.S                     |   3 +-
 arch/tile/include/asm/Kbuild              |   3 +
 arch/tile/include/asm/jump_label.h        |   5 +-
 arch/tile/include/asm/kprobes.h           |   6 +-
 arch/tile/kernel/vmlinux.lds.S            |   1 -
 arch/um/include/asm/Kbuild                |   4 +
 arch/unicore32/include/asm/Kbuild         |   3 +
 arch/unicore32/include/asm/section-core.h |  19 +
 arch/x86/include/asm/Kbuild               |   3 +
 arch/x86/include/asm/asm.h                |   4 +-
 arch/x86/include/asm/jump_label.h         |  10 +-
 arch/x86/include/asm/kprobes.h            |   9 +-
 arch/x86/kernel/cpu/microcode/core.c      |   8 +-
 arch/x86/kernel/kprobes/core.c            |  11 +-
 arch/x86/kernel/vmlinux.lds.S             |   1 -
 arch/x86/tools/relocs.c                   |   4 +
 arch/xtensa/include/asm/Kbuild            |   4 +
 arch/xtensa/kernel/Makefile               |   8 +-
 drivers/base/firmware_class.c             |  12 +-
 firmware/Makefile                         |   6 +-
 include/asm-generic/kprobes.h             |  26 +
 include/asm-generic/ranges.h              |  93 ++++
 include/asm-generic/section-core.h        | 348 +++++++++++++
 include/asm-generic/sections.h            |   4 +-
 include/asm-generic/tables.h              |  48 ++
 include/asm-generic/vmlinux.lds.h         |  47 +-
 include/linux/compiler.h                  |   8 -
 include/linux/dynamic_debug.h             |   5 +-
 include/linux/init.h                      |  89 +++-
 include/linux/jump_label.h                |   8 +-
 include/linux/kprobes.h                   |  24 +-
 include/linux/ranges.h                    | 183 +++++++
 include/linux/sections.h                  |  87 ++++
 include/linux/tables.h                    | 683 +++++++++++++++++++++++++
 init/Kconfig                              |  22 +
 kernel/jump_label.c                       |  17 +-
 kernel/kprobes.c                          |  17 +-
 lib/Kconfig.debug                         |   6 +
 lib/Makefile                              |   1 +
 lib/dynamic_debug.c                       |  13 +-
 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 ++
 scripts/Makefile.build                    |   7 +-
 scripts/Makefile.clean                    |   2 +
 scripts/Makefile.lib                      |  11 +
 scripts/mod/modpost.c                     |   2 +-
 scripts/module-common.lds                 |   2 +
 scripts/recordmcount.c                    |   2 +-
 scripts/recordmcount.pl                   |   2 +-
 tools/objtool/special.c                   |   2 +-
 143 files changed, 3632 insertions(+), 200 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/linker-tables.rst
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/c6x/include/asm/tables.h
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/kprobes.h
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/asm-generic/tables.h
 create mode 100644 include/linux/ranges.h
 create mode 100644 include/linux/sections.h
 create mode 100644 include/linux/tables.h
 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

-- 
2.10.1


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v5 00/14] linux: generalize sections, ranges and linker tables
@ 2016-12-22  2:37     ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:37 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Posting this for *after* the merge window.

This v5 addresses feedback from the last v4 series [0] about 4 months ago.
The first RFC series was posted just 1 year ago, last December 15 [1], its
been a long way coming. The largest amount of feedback from the v4 series came
from Nicholas Piggin, I've also made a few more minor changes and enhancements.

Because I have gone on different conferences talking about this work I've
jotted down in a white-paper form what this is all about and I've used it as
basis for a huge brush up on the documentation. I have not included the
paper into the tree as I think the documentation now stands for itself. The
paper may be useful for those wanted a huge verbose explanation to things
with much more in depth analysis and review of history [2].

I've split up the linker table patches in two groups to make it easier to
review, the first set (this) is for the kernel work, the second set is for the
tools/ userspace sandbox. If you would like to review all the changes in git
form you can yank them off of my linux-next 20161221-linker-tables-v5 branch on
kernel.org [3], please however note that the last patch on that tree was *not*
submitted upstream, it was used to force test 0-day and also Guenter's testbed
to force-enable and run the tests. You can disregard that patch unless you also
want to force test things :)

The biggest changes since v4 series worth noting:

  o Ended up using two dots (..) to separate the new sections to avoid conflicts
    with compiler generated sections, so we have: .text..rng.*, .data..tbl.*,
    etc.

  o Remove all the macro magic for section names. We now expect you to
    spell out each section manually. So no more SECTION_TEXT, for instance,
    for instance, we use just naked .text.

  o Adds a section linker table selftest driver. I have a debug out of tree
    patch used which was applied when testing which force enables the driver
    to be built in. This has been successfully run time tested against the
    following architectures:

    alpha      arc        arcv2       arm       arm64       blackfin    c6x
    cris       crisv32    frv         h8300     hexagon     i386        ia64
    m32r       m68k       m68k_nommu  metag     microblaze  mips_22     mips_24
    mips_25    mn10300    nios2       openrisc  parisc      parisc64    powerpc
    s390       score      sh          sparc32   sparc64     tile        um
    unicore32  x86_64     xtensa

    The only architecture that was not tested was avr32 and that is because
    linux-next fails to compile on it. I'd like to greatly thank Guenter Roeck
    for his help with testing.

  o A documentation revamp, to align what I hard originally written in the
    v4 series more in alignment with the the ELF specifications. Also properly
    document mark_rodata_ro().

  o Recruited Josh Poimboeuf and hpa as co-mainters of the general section
    stuff. For section ranges and linker tables it will be both me and hpa
    reviewing things. At Plumbers I spoke with Arnd and he would prefer changes
    to go in through each respective tree that needs each change, so no new
    tree is created. We'll just review and Ack/nack changes.

Happy holidays, and may the force be with you all...

Oh and lastly, a quick summary of the gains of having an API for all this.

First the obvious gains:

  o Allows us to just use plain C code to add new program specific
    ELF sections
  o Makes it less error prone to add new sections

Then the not so obvious immediate gains:

  o Helps simplify initialization code
  o Helps optionally avoid code bit-rot (see commit "kbuild: enable option to
    force compile force-obj-y and force-lib-y)
  o Enables link time ordering which can help make an extremely lightweight
    dependency annotations explicit (for this refer to the tools/linker-tables/
    example where I've demo'd simplfying Xen PV init code, which has caused
    tons of regressions over time due to the lack of explicit dependency
    annotations due to the sloppy Xen PV entry path; this is not going away
    any time soon)

Not so obvious long term gains:

  o Run time ordering customization are still possible (this is really long
    term but we already have one precedent in the kernel that does memmove()
    on entries on a section per some dependency heuristic.)
  o May help prevent use of dead code by either free'ing / nop'ing, no exec
    or whatever sections which we know should definitely not run.
  o Can easily increase the levels of initialization in the kernel without
    much changes (refer to tools/linker-tables/ for an example init with
    linker tables). I've seen a few cases where we've already run out of space
    to get init right in a few subsystems. This not only allows this but also
    allows subsystems to define their own custom levels of init if they wanted
    for their own things.
  o Synthetic functions: enables custom C / asm functions which could help
    add new functionality (see synth_init_or() on tools/linker-tables/drivers/synth/main.c)
    I've been hinted this can help with RAID6 support
  o Self modifying consts (see ps_shr() on tools/linker-tables/drivers/synth/main.c)

[0] https://lkml.kernel.org/r/1471642454-5679-1-git-send-email-mcgrof@kernel.org
[1] https://lkml.kernel.org/r/1450217797-19295-1-git-send-email-mcgrof@do-not-panic.com
[2] http://drvbp1.linux-foundation.org/~mcgrof/papers/2016/12/21/linker-tables-20161221.pdf
[3] https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h=20161221-linker-tables-v5

Luis R. Rodriguez (14):
  generic-sections: add section core helpers
  xtensa: skip adding literal when SORT() is used
  ranges.h: add helpers to build and identify Linux section ranges
  tables.h: add linker table support
  kbuild: enable option to force compile force-obj-y and force-lib-y
  firmware/Makefile: force recompilation if makefile changes
  firmware: port built-in section to linker table
  jump_label: move guard #endif down where it belongs
  jump_label: port __jump_table to linker tables
  dynamic_debug: port to use linker tables
  kprobes: move kprobe declarations to asm-generic/kprobes.h
  kprobes: port .kprobes.text to section range
  kprobes: port blacklist kprobes to linker table
  lib: add linker tables test driver

 Documentation/index.rst                   |   1 +
 Documentation/kbuild/makefiles.txt        |  36 ++
 Documentation/sections/background.rst     | 105 ++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  19 +
 Documentation/sections/linker-tables.rst  | 227 +++++++++
 Documentation/sections/ranges.rst         |  74 +++
 Documentation/sections/section-core.rst   | 153 ++++++
 MAINTAINERS                               |  32 ++
 arch/alpha/include/asm/Kbuild             |   4 +
 arch/arc/include/asm/Kbuild               |   3 +
 arch/arc/include/asm/kprobes.h            |   6 +-
 arch/arc/kernel/vmlinux.lds.S             |   1 -
 arch/arm/include/asm/Kbuild               |   3 +
 arch/arm/include/asm/jump_label.h         |   6 +-
 arch/arm/include/asm/kprobes.h            |   4 +
 arch/arm/kernel/entry-armv.S              |   3 +-
 arch/arm/kernel/vmlinux-xip.lds.S         |   1 -
 arch/arm/kernel/vmlinux.lds.S             |   1 -
 arch/arm/probes/decode.h                  |   1 +
 arch/arm64/include/asm/Kbuild             |   3 +
 arch/arm64/include/asm/jump_label.h       |   6 +-
 arch/arm64/include/asm/kprobes.h          |   4 +
 arch/arm64/kernel/armv8_deprecated.c      |   1 +
 arch/arm64/kernel/insn.c                  |   1 +
 arch/arm64/kernel/probes/decode-insn.h    |   2 +
 arch/arm64/kernel/probes/kprobes.c        |   4 +-
 arch/arm64/kernel/vmlinux.lds.S           |   1 -
 arch/avr32/include/asm/Kbuild             |   3 +
 arch/avr32/include/asm/kprobes.h          |   7 +-
 arch/avr32/kernel/entry-avr32b.S          |  13 +-
 arch/avr32/kernel/vmlinux.lds.S           |   1 -
 arch/blackfin/include/asm/Kbuild          |   4 +
 arch/blackfin/kernel/vmlinux.lds.S        |   1 -
 arch/c6x/include/asm/Kbuild               |   3 +
 arch/c6x/include/asm/tables.h             |  26 +
 arch/c6x/kernel/vmlinux.lds.S             |   1 -
 arch/cris/include/asm/Kbuild              |   4 +
 arch/frv/include/asm/Kbuild               |   4 +
 arch/h8300/include/asm/Kbuild             |   4 +
 arch/hexagon/include/asm/Kbuild           |   4 +
 arch/hexagon/kernel/vmlinux.lds.S         |   1 -
 arch/ia64/include/asm/Kbuild              |   3 +
 arch/ia64/include/asm/kprobes.h           |  12 +-
 arch/ia64/kernel/jprobes.S                |   3 +-
 arch/ia64/kernel/vmlinux.lds.S            |   1 -
 arch/ia64/lib/flush.S                     |   6 +-
 arch/m32r/include/asm/Kbuild              |   4 +
 arch/m68k/include/asm/Kbuild              |   4 +
 arch/metag/include/asm/Kbuild             |   4 +
 arch/metag/kernel/vmlinux.lds.S           |   1 -
 arch/microblaze/include/asm/Kbuild        |   4 +
 arch/microblaze/kernel/vmlinux.lds.S      |   1 -
 arch/mips/include/asm/Kbuild              |   3 +
 arch/mips/include/asm/jump_label.h        |   6 +-
 arch/mips/include/asm/kprobes.h           |   6 +-
 arch/mips/kernel/vmlinux.lds.S            |   1 -
 arch/mn10300/include/asm/Kbuild           |   3 +
 arch/mn10300/include/asm/kprobes.h        |   7 +-
 arch/mn10300/kernel/vmlinux.lds.S         |   1 -
 arch/nios2/include/asm/Kbuild             |   4 +
 arch/nios2/kernel/vmlinux.lds.S           |   1 -
 arch/openrisc/include/asm/Kbuild          |   4 +
 arch/openrisc/kernel/vmlinux.lds.S        |   1 -
 arch/parisc/include/asm/Kbuild            |   4 +
 arch/parisc/kernel/vmlinux.lds.S          |   1 -
 arch/powerpc/include/asm/Kbuild           |   3 +
 arch/powerpc/include/asm/jump_label.h     |   8 +-
 arch/powerpc/include/asm/kprobes.h        |   3 +
 arch/powerpc/include/asm/ppc_asm.h        |   3 +-
 arch/powerpc/kernel/vmlinux.lds.S         |   3 +-
 arch/s390/include/asm/Kbuild              |   3 +
 arch/s390/include/asm/jump_label.h        |   6 +-
 arch/s390/include/asm/kprobes.h           |   7 +-
 arch/s390/kernel/entry.S                  |   5 +-
 arch/s390/kernel/kprobes.c                |   6 +-
 arch/s390/kernel/mcount.S                 |   3 +-
 arch/s390/kernel/vmlinux.lds.S            |   1 -
 arch/score/include/asm/Kbuild             |   4 +
 arch/score/kernel/vmlinux.lds.S           |   1 -
 arch/sh/include/asm/Kbuild                |   3 +
 arch/sh/include/asm/kprobes.h             |   5 +-
 arch/sh/kernel/vmlinux.lds.S              |   1 -
 arch/sparc/include/asm/Kbuild             |   3 +
 arch/sparc/include/asm/jump_label.h       |   6 +-
 arch/sparc/include/asm/kprobes.h          |  10 +-
 arch/sparc/kernel/vmlinux.lds.S           |   1 -
 arch/sparc/mm/ultra.S                     |   3 +-
 arch/tile/include/asm/Kbuild              |   3 +
 arch/tile/include/asm/jump_label.h        |   5 +-
 arch/tile/include/asm/kprobes.h           |   6 +-
 arch/tile/kernel/vmlinux.lds.S            |   1 -
 arch/um/include/asm/Kbuild                |   4 +
 arch/unicore32/include/asm/Kbuild         |   3 +
 arch/unicore32/include/asm/section-core.h |  19 +
 arch/x86/include/asm/Kbuild               |   3 +
 arch/x86/include/asm/asm.h                |   4 +-
 arch/x86/include/asm/jump_label.h         |  10 +-
 arch/x86/include/asm/kprobes.h            |   9 +-
 arch/x86/kernel/cpu/microcode/core.c      |   8 +-
 arch/x86/kernel/kprobes/core.c            |  11 +-
 arch/x86/kernel/vmlinux.lds.S             |   1 -
 arch/x86/tools/relocs.c                   |   4 +
 arch/xtensa/include/asm/Kbuild            |   4 +
 arch/xtensa/kernel/Makefile               |   8 +-
 drivers/base/firmware_class.c             |  12 +-
 firmware/Makefile                         |   6 +-
 include/asm-generic/kprobes.h             |  26 +
 include/asm-generic/ranges.h              |  93 ++++
 include/asm-generic/section-core.h        | 348 +++++++++++++
 include/asm-generic/sections.h            |   4 +-
 include/asm-generic/tables.h              |  48 ++
 include/asm-generic/vmlinux.lds.h         |  47 +-
 include/linux/compiler.h                  |   8 -
 include/linux/dynamic_debug.h             |   5 +-
 include/linux/init.h                      |  89 +++-
 include/linux/jump_label.h                |   8 +-
 include/linux/kprobes.h                   |  24 +-
 include/linux/ranges.h                    | 183 +++++++
 include/linux/sections.h                  |  87 ++++
 include/linux/tables.h                    | 683 +++++++++++++++++++++++++
 init/Kconfig                              |  22 +
 kernel/jump_label.c                       |  17 +-
 kernel/kprobes.c                          |  17 +-
 lib/Kconfig.debug                         |   6 +
 lib/Makefile                              |   1 +
 lib/dynamic_debug.c                       |  13 +-
 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 ++
 scripts/Makefile.build                    |   7 +-
 scripts/Makefile.clean                    |   2 +
 scripts/Makefile.lib                      |  11 +
 scripts/mod/modpost.c                     |   2 +-
 scripts/module-common.lds                 |   2 +
 scripts/recordmcount.c                    |   2 +-
 scripts/recordmcount.pl                   |   2 +-
 tools/objtool/special.c                   |   2 +-
 143 files changed, 3632 insertions(+), 200 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/linker-tables.rst
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/c6x/include/asm/tables.h
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/kprobes.h
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/asm-generic/tables.h
 create mode 100644 include/linux/ranges.h
 create mode 100644 include/linux/sections.h
 create mode 100644 include/linux/tables.h
 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

-- 
2.10.1


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v5 00/14] linux: generalize sections, ranges and linker tables
@ 2016-12-22  2:37     ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:37 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

Posting this for *after* the merge window.

This v5 addresses feedback from the last v4 series [0] about 4 months ago.
The first RFC series was posted just 1 year ago, last December 15 [1], its
been a long way coming. The largest amount of feedback from the v4 series came
from Nicholas Piggin, I've also made a few more minor changes and enhancements.

Because I have gone on different conferences talking about this work I've
jotted down in a white-paper form what this is all about and I've used it as
basis for a huge brush up on the documentation. I have not included the
paper into the tree as I think the documentation now stands for itself. The
paper may be useful for those wanted a huge verbose explanation to things
with much more in depth analysis and review of history [2].

I've split up the linker table patches in two groups to make it easier to
review, the first set (this) is for the kernel work, the second set is for the
tools/ userspace sandbox. If you would like to review all the changes in git
form you can yank them off of my linux-next 20161221-linker-tables-v5 branch on
kernel.org [3], please however note that the last patch on that tree was *not*
submitted upstream, it was used to force test 0-day and also Guenter's testbed
to force-enable and run the tests. You can disregard that patch unless you also
want to force test things :)

The biggest changes since v4 series worth noting:

  o Ended up using two dots (..) to separate the new sections to avoid conflicts
    with compiler generated sections, so we have: .text..rng.*, .data..tbl.*,
    etc.

  o Remove all the macro magic for section names. We now expect you to
    spell out each section manually. So no more SECTION_TEXT, for instance,
    for instance, we use just naked .text.

  o Adds a section linker table selftest driver. I have a debug out of tree
    patch used which was applied when testing which force enables the driver
    to be built in. This has been successfully run time tested against the
    following architectures:

    alpha      arc        arcv2       arm       arm64       blackfin    c6x
    cris       crisv32    frv         h8300     hexagon     i386        ia64
    m32r       m68k       m68k_nommu  metag     microblaze  mips_22     mips_24
    mips_25    mn10300    nios2       openrisc  parisc      parisc64    powerpc
    s390       score      sh          sparc32   sparc64     tile        um
    unicore32  x86_64     xtensa

    The only architecture that was not tested was avr32 and that is because
    linux-next fails to compile on it. I'd like to greatly thank Guenter Roeck
    for his help with testing.

  o A documentation revamp, to align what I hard originally written in the
    v4 series more in alignment with the the ELF specifications. Also properly
    document mark_rodata_ro().

  o Recruited Josh Poimboeuf and hpa as co-mainters of the general section
    stuff. For section ranges and linker tables it will be both me and hpa
    reviewing things. At Plumbers I spoke with Arnd and he would prefer changes
    to go in through each respective tree that needs each change, so no new
    tree is created. We'll just review and Ack/nack changes.

Happy holidays, and may the force be with you all...

Oh and lastly, a quick summary of the gains of having an API for all this.

First the obvious gains:

  o Allows us to just use plain C code to add new program specific
    ELF sections
  o Makes it less error prone to add new sections

Then the not so obvious immediate gains:

  o Helps simplify initialization code
  o Helps optionally avoid code bit-rot (see commit "kbuild: enable option to
    force compile force-obj-y and force-lib-y)
  o Enables link time ordering which can help make an extremely lightweight
    dependency annotations explicit (for this refer to the tools/linker-tables/
    example where I've demo'd simplfying Xen PV init code, which has caused
    tons of regressions over time due to the lack of explicit dependency
    annotations due to the sloppy Xen PV entry path; this is not going away
    any time soon)

Not so obvious long term gains:

  o Run time ordering customization are still possible (this is really long
    term but we already have one precedent in the kernel that does memmove()
    on entries on a section per some dependency heuristic.)
  o May help prevent use of dead code by either free'ing / nop'ing, no exec
    or whatever sections which we know should definitely not run.
  o Can easily increase the levels of initialization in the kernel without
    much changes (refer to tools/linker-tables/ for an example init with
    linker tables). I've seen a few cases where we've already run out of space
    to get init right in a few subsystems. This not only allows this but also
    allows subsystems to define their own custom levels of init if they wanted
    for their own things.
  o Synthetic functions: enables custom C / asm functions which could help
    add new functionality (see synth_init_or() on tools/linker-tables/drivers/synth/main.c)
    I've been hinted this can help with RAID6 support
  o Self modifying consts (see ps_shr() on tools/linker-tables/drivers/synth/main.c)

[0] https://lkml.kernel.org/r/1471642454-5679-1-git-send-email-mcgrof@kernel.org
[1] https://lkml.kernel.org/r/1450217797-19295-1-git-send-email-mcgrof@do-not-panic.com
[2] http://drvbp1.linux-foundation.org/~mcgrof/papers/2016/12/21/linker-tables-20161221.pdf
[3] https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h=20161221-linker-tables-v5

Luis R. Rodriguez (14):
  generic-sections: add section core helpers
  xtensa: skip adding literal when SORT() is used
  ranges.h: add helpers to build and identify Linux section ranges
  tables.h: add linker table support
  kbuild: enable option to force compile force-obj-y and force-lib-y
  firmware/Makefile: force recompilation if makefile changes
  firmware: port built-in section to linker table
  jump_label: move guard #endif down where it belongs
  jump_label: port __jump_table to linker tables
  dynamic_debug: port to use linker tables
  kprobes: move kprobe declarations to asm-generic/kprobes.h
  kprobes: port .kprobes.text to section range
  kprobes: port blacklist kprobes to linker table
  lib: add linker tables test driver

 Documentation/index.rst                   |   1 +
 Documentation/kbuild/makefiles.txt        |  36 ++
 Documentation/sections/background.rst     | 105 ++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  19 +
 Documentation/sections/linker-tables.rst  | 227 +++++++++
 Documentation/sections/ranges.rst         |  74 +++
 Documentation/sections/section-core.rst   | 153 ++++++
 MAINTAINERS                               |  32 ++
 arch/alpha/include/asm/Kbuild             |   4 +
 arch/arc/include/asm/Kbuild               |   3 +
 arch/arc/include/asm/kprobes.h            |   6 +-
 arch/arc/kernel/vmlinux.lds.S             |   1 -
 arch/arm/include/asm/Kbuild               |   3 +
 arch/arm/include/asm/jump_label.h         |   6 +-
 arch/arm/include/asm/kprobes.h            |   4 +
 arch/arm/kernel/entry-armv.S              |   3 +-
 arch/arm/kernel/vmlinux-xip.lds.S         |   1 -
 arch/arm/kernel/vmlinux.lds.S             |   1 -
 arch/arm/probes/decode.h                  |   1 +
 arch/arm64/include/asm/Kbuild             |   3 +
 arch/arm64/include/asm/jump_label.h       |   6 +-
 arch/arm64/include/asm/kprobes.h          |   4 +
 arch/arm64/kernel/armv8_deprecated.c      |   1 +
 arch/arm64/kernel/insn.c                  |   1 +
 arch/arm64/kernel/probes/decode-insn.h    |   2 +
 arch/arm64/kernel/probes/kprobes.c        |   4 +-
 arch/arm64/kernel/vmlinux.lds.S           |   1 -
 arch/avr32/include/asm/Kbuild             |   3 +
 arch/avr32/include/asm/kprobes.h          |   7 +-
 arch/avr32/kernel/entry-avr32b.S          |  13 +-
 arch/avr32/kernel/vmlinux.lds.S           |   1 -
 arch/blackfin/include/asm/Kbuild          |   4 +
 arch/blackfin/kernel/vmlinux.lds.S        |   1 -
 arch/c6x/include/asm/Kbuild               |   3 +
 arch/c6x/include/asm/tables.h             |  26 +
 arch/c6x/kernel/vmlinux.lds.S             |   1 -
 arch/cris/include/asm/Kbuild              |   4 +
 arch/frv/include/asm/Kbuild               |   4 +
 arch/h8300/include/asm/Kbuild             |   4 +
 arch/hexagon/include/asm/Kbuild           |   4 +
 arch/hexagon/kernel/vmlinux.lds.S         |   1 -
 arch/ia64/include/asm/Kbuild              |   3 +
 arch/ia64/include/asm/kprobes.h           |  12 +-
 arch/ia64/kernel/jprobes.S                |   3 +-
 arch/ia64/kernel/vmlinux.lds.S            |   1 -
 arch/ia64/lib/flush.S                     |   6 +-
 arch/m32r/include/asm/Kbuild              |   4 +
 arch/m68k/include/asm/Kbuild              |   4 +
 arch/metag/include/asm/Kbuild             |   4 +
 arch/metag/kernel/vmlinux.lds.S           |   1 -
 arch/microblaze/include/asm/Kbuild        |   4 +
 arch/microblaze/kernel/vmlinux.lds.S      |   1 -
 arch/mips/include/asm/Kbuild              |   3 +
 arch/mips/include/asm/jump_label.h        |   6 +-
 arch/mips/include/asm/kprobes.h           |   6 +-
 arch/mips/kernel/vmlinux.lds.S            |   1 -
 arch/mn10300/include/asm/Kbuild           |   3 +
 arch/mn10300/include/asm/kprobes.h        |   7 +-
 arch/mn10300/kernel/vmlinux.lds.S         |   1 -
 arch/nios2/include/asm/Kbuild             |   4 +
 arch/nios2/kernel/vmlinux.lds.S           |   1 -
 arch/openrisc/include/asm/Kbuild          |   4 +
 arch/openrisc/kernel/vmlinux.lds.S        |   1 -
 arch/parisc/include/asm/Kbuild            |   4 +
 arch/parisc/kernel/vmlinux.lds.S          |   1 -
 arch/powerpc/include/asm/Kbuild           |   3 +
 arch/powerpc/include/asm/jump_label.h     |   8 +-
 arch/powerpc/include/asm/kprobes.h        |   3 +
 arch/powerpc/include/asm/ppc_asm.h        |   3 +-
 arch/powerpc/kernel/vmlinux.lds.S         |   3 +-
 arch/s390/include/asm/Kbuild              |   3 +
 arch/s390/include/asm/jump_label.h        |   6 +-
 arch/s390/include/asm/kprobes.h           |   7 +-
 arch/s390/kernel/entry.S                  |   5 +-
 arch/s390/kernel/kprobes.c                |   6 +-
 arch/s390/kernel/mcount.S                 |   3 +-
 arch/s390/kernel/vmlinux.lds.S            |   1 -
 arch/score/include/asm/Kbuild             |   4 +
 arch/score/kernel/vmlinux.lds.S           |   1 -
 arch/sh/include/asm/Kbuild                |   3 +
 arch/sh/include/asm/kprobes.h             |   5 +-
 arch/sh/kernel/vmlinux.lds.S              |   1 -
 arch/sparc/include/asm/Kbuild             |   3 +
 arch/sparc/include/asm/jump_label.h       |   6 +-
 arch/sparc/include/asm/kprobes.h          |  10 +-
 arch/sparc/kernel/vmlinux.lds.S           |   1 -
 arch/sparc/mm/ultra.S                     |   3 +-
 arch/tile/include/asm/Kbuild              |   3 +
 arch/tile/include/asm/jump_label.h        |   5 +-
 arch/tile/include/asm/kprobes.h           |   6 +-
 arch/tile/kernel/vmlinux.lds.S            |   1 -
 arch/um/include/asm/Kbuild                |   4 +
 arch/unicore32/include/asm/Kbuild         |   3 +
 arch/unicore32/include/asm/section-core.h |  19 +
 arch/x86/include/asm/Kbuild               |   3 +
 arch/x86/include/asm/asm.h                |   4 +-
 arch/x86/include/asm/jump_label.h         |  10 +-
 arch/x86/include/asm/kprobes.h            |   9 +-
 arch/x86/kernel/cpu/microcode/core.c      |   8 +-
 arch/x86/kernel/kprobes/core.c            |  11 +-
 arch/x86/kernel/vmlinux.lds.S             |   1 -
 arch/x86/tools/relocs.c                   |   4 +
 arch/xtensa/include/asm/Kbuild            |   4 +
 arch/xtensa/kernel/Makefile               |   8 +-
 drivers/base/firmware_class.c             |  12 +-
 firmware/Makefile                         |   6 +-
 include/asm-generic/kprobes.h             |  26 +
 include/asm-generic/ranges.h              |  93 ++++
 include/asm-generic/section-core.h        | 348 +++++++++++++
 include/asm-generic/sections.h            |   4 +-
 include/asm-generic/tables.h              |  48 ++
 include/asm-generic/vmlinux.lds.h         |  47 +-
 include/linux/compiler.h                  |   8 -
 include/linux/dynamic_debug.h             |   5 +-
 include/linux/init.h                      |  89 +++-
 include/linux/jump_label.h                |   8 +-
 include/linux/kprobes.h                   |  24 +-
 include/linux/ranges.h                    | 183 +++++++
 include/linux/sections.h                  |  87 ++++
 include/linux/tables.h                    | 683 +++++++++++++++++++++++++
 init/Kconfig                              |  22 +
 kernel/jump_label.c                       |  17 +-
 kernel/kprobes.c                          |  17 +-
 lib/Kconfig.debug                         |   6 +
 lib/Makefile                              |   1 +
 lib/dynamic_debug.c                       |  13 +-
 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 ++
 scripts/Makefile.build                    |   7 +-
 scripts/Makefile.clean                    |   2 +
 scripts/Makefile.lib                      |  11 +
 scripts/mod/modpost.c                     |   2 +-
 scripts/module-common.lds                 |   2 +
 scripts/recordmcount.c                    |   2 +-
 scripts/recordmcount.pl                   |   2 +-
 tools/objtool/special.c                   |   2 +-
 143 files changed, 3632 insertions(+), 200 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/linker-tables.rst
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/c6x/include/asm/tables.h
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/kprobes.h
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/asm-generic/tables.h
 create mode 100644 include/linux/ranges.h
 create mode 100644 include/linux/sections.h
 create mode 100644 include/linux/tables.h
 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

-- 
2.10.1


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v5 01/14] generic-sections: add section core helpers
  2016-12-22  2:37     ` Luis R. Rodriguez
                         ` (2 preceding siblings ...)
  (?)
@ 2016-12-22  2:37       ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:37 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="windows-1254", Size: 47014 bytes --]

Linux makes extensive use of custom ELF header sections,
documentation for these are well scatterred. Unify this
documentation in a central place and provide helpers to
build custom Linux sections.

This also generalizes sections code to enable avoiding
modifying the linker scripts when we want to add new
custom Linux sections. In order to make this generally
useful we need to ensure all architectures can make use of
core section helpers but that they can also override should
this be needed. Instead of relying on section.h this adds
a sections-core.h since this will be targetted to be safe
to be used on asm code, linker scripts and C code.

v5:

o Huge documentation revamp based on a careful review of the ELF
  specifications. Includes documentation now also about usage of
  two dots (..) when prefixing ELF program specific sections.

o Replace macros for sections names in favor of just using
  the section names explicitly in the linker script. This is
  perhaps more work to grep but this is what folks seem to
  currently prefer.

o Fix .text and .rodata documentation to explain memory protection
  strategies which architectures can embrace upon initialization
  (documents CONFIG_DEBUG_RODATA and mark_rodata_ro())

o Skip the 'Linux section ordering' documentation section, we'll instead
  add this on subsequent patch which will expand on it considerably

o Dropped tree on MAINTAINERS -- as per discussions with Arnd, hpa and
  Josh, its easier to just let changes for sections go in through the
  respective tree that needs the changes.

o Fix typos on documentation

o Dropped SECTION_ALL(), __SECTION_CORE(), SECTION_CORE_ALL() macros
  since we are favoring using explicit section names. These are
  useless if we are being explicit.

o Drop LINUX_SECTION_SIZE(), LINUX_SECTION_EMPTY() in favor of having
  section ranges and linker tables define their own, to avoid confusion
  and make code more readable.

o Add __define_initcall() documentation and a small section describing
  our current initcall levels. This should help also clarify what was
  meant about keeping backward compatiblity.

v4:

o Port to shiny new sphinx documentation format

o fix a unicore32 build, turns out this actually fixes unicore32
  defconfig builds which were failing for a long while. unicore32
  does not seem to grok well the type passed on a section declaration,
  this ignores it.

o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
  this was causing final linker issues with blackfin -- this is
  a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
  being metatag. metatag is not supported on 0-day so I cannot confirm
  compilation there.

o Added SECTION_CORE() for C code, used later by __LINUX_RANGE()

o Since SECTION_CORE() is defined for linker script and C code, share
  the same helper and just use a __stringify() for the C code as is done
  for the other C helpers.

o move generic sections to asm-generic/section-core.h instead.
  PowerPC compilation blows up if asm/jump_labels.h gets
  section.h included, fixing this is not in any way easy.
  The list of issues are endless. Moving new data to a new
  simple file resolves this.

o since things are now in asm-generic/section-core.h the
  guard changes on asm-generic/sections.h and each architecture
  sections.h are no longer needed

o Give generic sections some maintainer love, that change is
  Acked-by Arnd Bergmann, Josh and hpa.

o A few checkpatch.pl style fixes

o As suggested by James Hogan use generic-y to copy generic
  header files on architectures that do not have a sections.h
  instead of writing a simple file only to include the generic one.

v3:

o add missing sections.h for architectures that did not
  have it

o move generic sections to asm-generic/sections.h

o add generic asm helpers section_type(), section_type_asmtype(),
  push_section_type() -- these helpers enable easy use for
  for later declaring and using of custom linux sections using
  more standard APIs in both C code, asm code (C asm calls, or
  asm files), enabling future standardized section types to
  be more immediately accessible to asm code, not just C code.
  Note for ASM_CMD_SEP we use by default "\n", architectures needed
  to override can do so on their own sections.h prior to inclusion
  of asm-generic/sections.h

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/index.rst                   |   1 +
 Documentation/sections/background.rst     | 105 ++++++++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  17 ++
 Documentation/sections/section-core.rst   | 148 ++++++++++++++
 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/Kbuild               |   1 +
 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/section-core.h |  19 ++
 arch/x86/include/asm/Kbuild               |   1 +
 arch/xtensa/include/asm/Kbuild            |   1 +
 include/asm-generic/section-core.h        | 307 ++++++++++++++++++++++++++++++
 include/asm-generic/sections.h            |   2 +
 include/asm-generic/vmlinux.lds.h         |   1 +
 include/linux/init.h                      |  89 +++++++--
 include/linux/sections.h                  |  87 +++++++++
 42 files changed, 809 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/linux/sections.h

diff --git a/Documentation/index.rst b/Documentation/index.rst
index cb5d77699c60..71e0305c036d 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -57,6 +57,7 @@ needed).
    media/index
    gpu/index
    security/index
+   sections/index
    sound/index
    crypto/index
 
diff --git a/Documentation/sections/background.rst b/Documentation/sections/background.rst
new file mode 100644
index 000000000000..0ecf9104aaa2
--- /dev/null
+++ b/Documentation/sections/background.rst
@@ -0,0 +1,105 @@
+===========
+ELF section background
+===========
+
+About
+==+
+The purpose of this chapter is to help those not familiar with ELF to brush up
+the latest ELF specifications in order to help understand how Linux uses and
+defines its own ELF sections.
+
+Standardized ELF
+========
+
+The first publication documenting ELF was UNIX System Laboratories' (USL)
+*System V Release 4 Application Binary Interface* (`SRV4 ABI`_) specification.
+Originally ELF was only a small part of the SRV4 ABI, with time however new
+specifications only put focus on ELF, such was the case of the *TIS Portable
+Formats Specification version 1.2* (`TIS 1.2`_). As of TIS 1.2, ELF was
+supplemented with processor specific ELF addendums, available on the *Linux
+Foundation referenced specification page* (`LF ref page`_). The latest ELF
+specification is the *System V Application Binary Interface - DRAFT - 24 April
+2001* (`gabi4`_).
+
+.. _SRV4 ABI: http://www.sco.com/developers/devspecs/gabi41.pdf
+.. _TIS 1.2: https://refspecs.linuxbase.org/elf/elf.pdf
+.. _LF ref page: https://refspecs.linuxbase.org/
+.. _gabi4: https://refspecs.linuxbase.org/elf/gabi4+/contents.html
+
+ELF views on Linux
+=========
+
+There are two views which can be used for inspecting data in an ELF file, a
+Linking view, and an Execution view. A Section Header Table enables one to
+describe an object using the Linking view while a Program Header Table enables
+one to describe an object using the Execution view. The views are not mutually
+exclusive. For intance, vmlinux can be viewed under both views, ``readelf -S
+vmlinux`` for the Linking view, and ``readelf -l vmlinux`` for the Execution
+view.  In Linux only the vmlinux file will have an Execution view, even modules
+lack an Execution view given that vmlinux is the only file that describes how
+the the kernel runs from the start.  All other Linux kernel object files have
+an available Linking view.
+
+Under the Linking view, the Section Header Table describes all available
+sections. The Section Header Table is an array of ELF section header data
+structures. If on a 32-bit system this is ``struct elf32_shd``, if on a 64-bit
+this is ``struct elf64_shdr``. Sections are only visible on object files that
+have a Linking view, since all Linux kernel files have Linking view, all kernel
+objects have ELF sections.
+
+Limitations on ELF sections
+=============+
+We provide a summary on the limitations of ELF sections. Refer to the public
+ELF specifications for details. Note that 64-bit limitations may depend
+on processor specific section attributes to be used, refer to your processsor
+specification if unsure.
+
+Its worth ellaborating on the limitations on the name of an ELF section:
+ELF section names are stored as strings as per the ELF specification, and
+as can be expected, these don't have explicit limitations. The implicit
+limitation then depends on the size of an ELF object file and ELF section.
+
+If using really large kernels or objects with large amounts of sections one
+would still need to be sure that ELF loader in charge of loading the Linux
+kernel is properly updated to handle coping with the latest ELF extensions.
+
+   .. flat-table:: Limitations on ELF Sections
+
+      * - Section attribute
+        - 32-bit
+        - 64-bit
+
+      * - ELF section name
+        - Size of an ELF section
+        - Size of an ELF section
+
+      * - Size of an ELF section
+        - 4 GiB
+        - 16 EiB
+
+      * - Max number of sections in an object file
+        - 4 GiEntries (4294967296)
+        - 16 EiEntries (18446744073709551616)
+
+Program specific ELF sections
+==============+
+The ELF specification allows for a section type to be specified as
+*Program specific section*, defined as ``SHT_PROGBITS``. This sections type
+enables programs to customize sections for their own use. In assembly this
+specified ``@progbits`` on most architectures, on ARM this is ``%progbits``.
+
+``SHT_PROGBITS`` is used by Linux for defining and using Linux ELF sections.
+
+Special ELF Sections
+==========
+
+The ELF specification defines *Special ELF Sections* on chapter 4 (`gabi4
+ch4`_). These are defined as sections which hold program and control
+information. Of these sections, a few have the section type as
+``SHT_PROGBITS``. This enables Linux to *further customize* use of the section
+beyond what the ELF specification suggests.
+
+.. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
new file mode 100644
index 000000000000..faa1c57595e1
--- /dev/null
+++ b/Documentation/sections/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel ELF sections'
+html_search_language = 'en'
diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
new file mode 100644
index 000000000000..f37511ef05e7
--- /dev/null
+++ b/Documentation/sections/index.rst
@@ -0,0 +1,17 @@
+============+Linux Kernel ELF sections
+============+
+This book documents the different ELF sections used on the Linux kernel.
+We start off by providing references to how ELF was standardized, references
+to the standards on ELF sections, review limitations of ELF sections, and
+finally how Linux uses ELF sections in the Linux kernel. Certain important
+Linux ELF sections are documented carefully: we describe the goal of the
+ELF section, and address concurrency considerations when applicable. A few
+common a set of Linux helpers for ELF sections are also documented.
+
+.. toctree::
+   :maxdepth: 4
+
+   background
+   section-core
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
new file mode 100644
index 000000000000..ac5815a0d9b3
--- /dev/null
+++ b/Documentation/sections/section-core.rst
@@ -0,0 +1,148 @@
+=================+Linux ELF program specific sections
+=================+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux ELF program specific sections
+
+Linux linker script
+=========+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux linker script
+
+Memory protection
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Memory protection
+
+mark_rodata_ro
+-----------------------
+.. kernel-doc:: include/linux/init.h
+   :functions: mark_rodata_ro
+
+.rodata
+-------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .rodata
+
+.text
+-----
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .text
+
+.data
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .data
+
+Linux .init\* sections
+===========
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux init sections
+
+.init.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.text
+
+.init.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.data
+
+.init.rodata
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.rodata
+
+Initcall levels
+---------------
+.. kernel-doc:: include/linux/init.h
+   :doc: Initcall levels
+
+.initcall
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .initcall
+
+__define_initcall
+-----------------
+.. kernel-doc:: include/linux/init.h
+   :functions: __define_initcall
+
+Linux .exit\* sections
+===========
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux exit sections
+
+.exit.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.text
+
+.exit.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.data
+
+.exitcall.exit
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exitcall.exit
+
+Linux .ref\* sections
+==========+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux references to init sections
+
+.ref.text
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.text
+
+.ref.data
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.data
+
+.ref.rodata
+-----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.rodata
+
+Generic Linux kernel section helpers
+==================
+
+Introduction
+-------------
+.. kernel-doc:: include/linux/sections.h
+   :doc: Introduction
+
+LINUX_SECTION_ALIGNMENT
+-----------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_ALIGNMENT
+
+LINUX_SECTION_START
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_START
+
+LINUX_SECTION_END
+-----------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_END
+
+DECLARE_LINUX_SECTION
+---------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION
+
+DECLARE_LINUX_SECTION_RO
+------------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION_RO
diff --git a/MAINTAINERS b/MAINTAINERS
index d0b2b50705bd..308826f5094b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5422,6 +5422,18 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTIONS
+M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
+M:	Josh Poimboeuf <jpoimboe@redhat.com>
+M:	"H. Peter Anvin" <hpa@zytor.com>
+L:	linux-arch@vger.kernel.org
+L:	linux-kernel@vger.kernel.org
+S:	Supported
+F:	include/asm-generic/section-core.h
+F:	include/asm-generic/sections.h
+F:	include/asm-generic/vmlinux.lds.h
+F:	Documentation/sections/section-core.rst
+
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index bf8475ce85ee..5422827f1585 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += section-core.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index c332604606dd..7b2cb3dea5fc 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index efb21757d41f..9b69a22a9ae1 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += unaligned.h
 
 generated-y += mach-types.h
 generated-y += unistd-nr.h
+generic-y += section-core.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 8365a84c2640..00ace5e826f1 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 241b9b9729d8..f2c3b656a0e7 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 2fb67b59d188..bf20541bcf21 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -47,3 +47,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 64465e7e2245..38127ce747be 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -62,3 +62,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 1778805f6380..385cd88a9d9e 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += types.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 1fa084cf1a43..46d7c599d9b8 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 373cb23301e3..1ec04ec1c82b 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -75,3 +75,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index db8ddabc6bd2..37d7bfae7619 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -60,3 +60,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 502a91d8dbbd..672c6d5da18c 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 860e440611c9..6111e1523750 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1f2e5d31cb24..1277b45bf4f9 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -34,3 +34,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 167150c701d1..b1011375cd7a 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -55,3 +55,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index b0ae88c9fed9..c6c2cf6edc98 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 45b0d6568270..a67d3177f3ca 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -20,3 +20,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 1c8dd0f5cd5d..f8145bc85835 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index d63330e88379..c9c7cb82b00f 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 2832f031fb11..86175e701869 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -71,3 +71,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 91f53c07f410..18a9d4c5ead7 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -28,3 +28,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 5c4fbc80dc6c..4322d9746cdb 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
+generic-y += section-core.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 8aea32fe8bd2..63a1c2924b91 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index a05218ff3fe4..f089a264cd38 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 751c3373a92c..7b0356dca562 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 0569bfac4afb..438f86573dc5 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 2d1f5638974c..fb6b831c1fba 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 052f7f6d0551..580bd5ff828f 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -26,3 +26,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
new file mode 100644
index 000000000000..0b9c68429a1a
--- /dev/null
+++ b/arch/unicore32/include/asm/section-core.h
@@ -0,0 +1,19 @@
+#ifndef __UNICORE_SECTION_CORE_ASM_H__
+#define __UNICORE_SECTION_CORE_ASM_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/.
+ */
+
+/* Unicore32 has known to not work properly with the type set, so ignore it */
+
+#define __set_section_core_type(___section, ___core, ___name,		\
+				___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags
+
+#include <asm-generic/section-core.h>
+
+#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 2b892e2313a9..af975f21eeee 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
+generic-y += section-core.h
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index b7fbaa56b51a..7879c31e66a7 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..bb16befc4251
--- /dev/null
+++ b/include/asm-generic/section-core.h
@@ -0,0 +1,307 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Linux ELF program specific sections
+ *
+ * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and
+ * definition of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
+ * sections. This chaper is dedicated to documenting Linux program specific
+ * sections and helpers available to make use of these easier to implement and
+ * use.
+ *
+ * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
+ */
+
+/**
+ * DOC: Linux linker script
+ *
+ * Linux uses a custom linker script to build the vmlinux binary, it uses it to
+ * strategically place and define Linux ELF sections.  Each architecture needs
+ * to implement its own linker script, it is expected to reside in
+ * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
+ * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
+ * as well as some helpers documented in this chapter.
+ *
+ * In assembly it is common practice to use dots (``.``) in labels to avoid
+ * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
+ * name but not a C symbol. Historically then, two dots are used (``..``)
+ * have been used in linker scripts when adding program specific sections
+ * when there are concerns to avoid clashes with compiler generated sections.
+ */
+
+/**
+ * DOC: Memory protection
+ *
+ * Linux allows architectures which support memory protection features to
+ * take advantage of them by letting architectures define and enable
+ * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.
+ * mark_rodata_ro() can be used for instance to mark specific sections as
+ * read-only or non-executable.
+ *
+ * Linux typically follows a convention to have the .rodata ELF section follow
+ * after the .text ELF section, it does this to help architectures which
+ * support memory protection to mark both .text and .rodata as read-only in
+ * one shot.
+ *
+ * For more details refer to mark_rodata_ro().
+ */
+
+/**
+ * DOC: .rodata
+ *
+ * ELF section used for data which must be protected from write access.
+ */
+
+/**
+ * DOC: .text
+ *
+ * ELF section name used for code (functions) used during regular
+ * kernel run time.
+ */
+
+/**
+ * DOC: .data
+ *
+ * ELF section used for read-write data.
+ */
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: .init.text
+ *
+ * ELF section for code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+
+/**
+ * DOC: .init.data
+ *
+ * ELF section used for data structures used only during boot or driver
+ * initialization.
+ */
+
+/**
+ * DOC: .init.rodata
+ *
+ * ELF section used for read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+
+/**
+ * DOC: .initcall
+ *
+ * ELF section used for subsystem init calls. There are init levels
+ * representing different functionality in the kernel. For more details
+ * refer to __define_initcall().
+ */
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: .exit.text
+ *
+ * ELF section used to for code (functions) used only during module unload.
+ */
+
+/**
+ * DOC: .exit.data
+ *
+ * ELF section used to for data structures used only during module
+ * unload.
+ */
+
+/**
+ * DOC: .exitcall.exit
+ *
+ * ELF section used for exit routines, order is important and maintained by
+ * link order.
+ */
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: .ref.text
+ *
+ * ELF section used to annotate code (functions) which has been vetteed as
+ * valid for its reference or use of other code (functions) or data structures
+ * which are part of the init sections.
+ */
+
+/**
+ * DOC: .ref.data
+ *
+ * ELF section used for data structures which have been vetteed for its
+ * reference or use of other code (functions) or data structures part of the
+ * init sections.
+ */
+
+/**
+ * DOC: .ref.rodata
+ *
+ * ELF section used to annotate const code (functions) const data structures
+ * which has been vetteed for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section..___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section..__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifndef LINKER_SCRIPT
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align\x16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 4df64a1fc09e..b145ae8d9cbe 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_GENERIC_SECTIONS_H_
 #define _ASM_GENERIC_SECTIONS_H_
 
+#include <asm/section-core.h>
+
 /* References to section boundaries */
 
 #include <linux/compiler.h>
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 0968d13b3885..483f60c451f9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -55,6 +55,7 @@
 #endif
 
 #include <linux/export.h>
+#include <asm/section-core.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
diff --git a/include/linux/init.h b/include/linux/init.h
index 885c3e6d0f9d..116e3262332a 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -130,6 +130,24 @@ int __init init_rootfs(void);
 extern bool rodata_enabled;
 #endif
 #ifdef CONFIG_DEBUG_RODATA
+/**
+ * mark_rodata_ro - implemement memory protection for ELF sections
+ *
+ * Architectures which support memory protection define a kernel configuration
+ * entry for CONFIG_DEBUG_RODATA, enable it in and implement mark_rodata_ro().
+ * mark_rodata_ro() should strive to adjust the .rodata and .text ELF sections
+ * with read-only memory protection to prevent modifications of these sections
+ * after bootup. It can also try to use memory protection to prevent execution
+ * on the .rodata ELF section.
+ *
+ * In order to help architectures set both .text and .rodata as read-only with
+ * memory protections in one shot Linux has typically followed the convention
+ * to have the .rodata ELF section follow the .text ELF section on the vmlinux
+ * linker script.
+ *
+ * Linux calls mark_rodata_ro() after freeing .init code and prior to calling
+ * the first init userspace process.
+ */
 void mark_rodata_ro(void);
 #endif
 
@@ -140,25 +158,70 @@ extern bool initcall_debug;
 #endif
   
 #ifndef MODULE
+/**
+ * DOC: Initcall levels
+ *
+ * When Linux boots the kernel do_initcalls() iterates over each Linux
+ * initialization level ID and calls all routines embedded on each level ID.
+ * Prior to v2.5.2.3 Linux had only one init level onto which all init
+ * functions folded onto using __initcall(). After v2.5.2.4 Linux split up
+ * initcalls into 7 separate initcall subsection levels, each level describing
+ * different functionality part of the kernel (commit `9d6ba121b7e17085`_
+ * (v2.5.2.3 -> v2.5.2.4)). In order to remain backward compatible __initcall()
+ * calls were left mapped to device_initcall().
+ *
+ * Each init level consists of a dedicated ELF section, init functions are
+ * associated to an init level by linking it into the respective level's
+ * ELF section.
+ *
+ * Lower order init levels run prior to higher order init levels. Ordering
+ * inside each initcall level is determined by respective link order.
+ *
+ * .. _9d6ba121b7e17085: https://git.kernel.org/cgit/linux/kernel/git/history/history.git/commit/?id6ba121b7e17085c95139233686b27a4d4c650e
+ */
 
 #ifndef __ASSEMBLY__
 
-/*
- * initcalls are now grouped by functionality into separate
- * subsections. Ordering inside the subsections is determined
- * by link order. 
- * For backwards compatibility, initcall() puts the call in 
- * the device init subsection.
+/**
+ * __define_initcall - wrapper for definiting init levels
  *
- * The `id' arg to __define_initcall() is needed so that multiple initcalls
- * can point at the same handler without causing duplicate-symbol build errors.
+ * @fn: init routine
+ * @id: init level
  *
- * Initcalls are run by placing pointers in initcall sections that the
- * kernel iterates at runtime. The linker can do dead code / data elimination
- * and remove that completely, so the initcall sections have to be marked
- * as KEEP() in the linker script.
+ * Defines a kernel initialization level. A respective linker script entry
+ * is required to ensure the init level is accounted for and to ensure symbols
+ * exist for iterating over all functions in the init level. A init level
+ * represents a series of functionality in the kernel.
+ *
+ * Ordering within an initialization level is determined by link order, so
+ * for instance if a Makefile had::
+ *
+ *	obj-y += foo.o
+ *	obj-y += bar.o
+ *
+ * And foo.c::
+ *
+ *	subsys_initcall(foo_init);
+ *
+ * And bar.c had::
+ *
+ *	subsys_initcall(bar_init);
+ *
+ * foo_init() would be called prior to bar_init().
+ *
+ * Note that @id in __define_initcall() also enables multiple initcalls
+ * to be created using the same handler for different init levels without
+ * causing duplicate-symbol build errors.
+ *
+ * Initcalls are run by placing start symbols to initcall levels inside ELF
+ * sections, the kernel in turn uses these symbols to iterate over each init
+ * level at runtime with do_initcall_level(). The end of each init level is
+ * marked by the subsequent's symbol's start address until we reach the symbol
+ * ``__initcall_end``. The linker can do dead code / data elimination and each
+ * init level start symbol could be removed completely in this process, to
+ * avoid this each init level start symbols must be marked as 'KEEP()' in the
+ * linker script to avoid any linker optimization heuristic on initcalls.
  */
-
 #define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
 	__attribute__((__section__(".initcall" #id ".init"))) = fn;
diff --git a/include/linux/sections.h b/include/linux/sections.h
new file mode 100644
index 000000000000..6771c727bcd1
--- /dev/null
+++ b/include/linux/sections.h
@@ -0,0 +1,87 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_CORE(section, core, name, level)			\
+	#section ".." #core "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
-- 
2.10.1

--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 01/14] generic-sections: add section core helpers
@ 2016-12-22  2:37       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:37 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Linux makes extensive use of custom ELF header sections,
documentation for these are well scatterred. Unify this
documentation in a central place and provide helpers to
build custom Linux sections.

This also generalizes sections code to enable avoiding
modifying the linker scripts when we want to add new
custom Linux sections. In order to make this generally
useful we need to ensure all architectures can make use of
core section helpers but that they can also override should
this be needed. Instead of relying on section.h this adds
a sections-core.h since this will be targetted to be safe
to be used on asm code, linker scripts and C code.

v5:

o Huge documentation revamp based on a careful review of the ELF
  specifications. Includes documentation now also about usage of
  two dots (..) when prefixing ELF program specific sections.

o Replace macros for sections names in favor of just using
  the section names explicitly in the linker script. This is
  perhaps more work to grep but this is what folks seem to
  currently prefer.

o Fix .text and .rodata documentation to explain memory protection
  strategies which architectures can embrace upon initialization
  (documents CONFIG_DEBUG_RODATA and mark_rodata_ro())

o Skip the 'Linux section ordering' documentation section, we'll instead
  add this on subsequent patch which will expand on it considerably

o Dropped tree on MAINTAINERS -- as per discussions with Arnd, hpa and
  Josh, its easier to just let changes for sections go in through the
  respective tree that needs the changes.

o Fix typos on documentation

o Dropped SECTION_ALL(), __SECTION_CORE(), SECTION_CORE_ALL() macros
  since we are favoring using explicit section names. These are
  useless if we are being explicit.

o Drop LINUX_SECTION_SIZE(), LINUX_SECTION_EMPTY() in favor of having
  section ranges and linker tables define their own, to avoid confusion
  and make code more readable.

o Add __define_initcall() documentation and a small section describing
  our current initcall levels. This should help also clarify what was
  meant about keeping backward compatiblity.

v4:

o Port to shiny new sphinx documentation format

o fix a unicore32 build, turns out this actually fixes unicore32
  defconfig builds which were failing for a long while. unicore32
  does not seem to grok well the type passed on a section declaration,
  this ignores it.

o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
  this was causing final linker issues with blackfin -- this is
  a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
  being metatag. metatag is not supported on 0-day so I cannot confirm
  compilation there.

o Added SECTION_CORE() for C code, used later by __LINUX_RANGE()

o Since SECTION_CORE() is defined for linker script and C code, share
  the same helper and just use a __stringify() for the C code as is done
  for the other C helpers.

o move generic sections to asm-generic/section-core.h instead.
  PowerPC compilation blows up if asm/jump_labels.h gets
  section.h included, fixing this is not in any way easy.
  The list of issues are endless. Moving new data to a new
  simple file resolves this.

o since things are now in asm-generic/section-core.h the
  guard changes on asm-generic/sections.h and each architecture
  sections.h are no longer needed

o Give generic sections some maintainer love, that change is
  Acked-by Arnd Bergmann, Josh and hpa.

o A few checkpatch.pl style fixes

o As suggested by James Hogan use generic-y to copy generic
  header files on architectures that do not have a sections.h
  instead of writing a simple file only to include the generic one.

v3:

o add missing sections.h for architectures that did not
  have it

o move generic sections to asm-generic/sections.h

o add generic asm helpers section_type(), section_type_asmtype(),
  push_section_type() -- these helpers enable easy use for
  for later declaring and using of custom linux sections using
  more standard APIs in both C code, asm code (C asm calls, or
  asm files), enabling future standardized section types to
  be more immediately accessible to asm code, not just C code.
  Note for ASM_CMD_SEP we use by default "\n", architectures needed
  to override can do so on their own sections.h prior to inclusion
  of asm-generic/sections.h

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/index.rst                   |   1 +
 Documentation/sections/background.rst     | 105 ++++++++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  17 ++
 Documentation/sections/section-core.rst   | 148 ++++++++++++++
 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/Kbuild               |   1 +
 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/section-core.h |  19 ++
 arch/x86/include/asm/Kbuild               |   1 +
 arch/xtensa/include/asm/Kbuild            |   1 +
 include/asm-generic/section-core.h        | 307 ++++++++++++++++++++++++++++++
 include/asm-generic/sections.h            |   2 +
 include/asm-generic/vmlinux.lds.h         |   1 +
 include/linux/init.h                      |  89 +++++++--
 include/linux/sections.h                  |  87 +++++++++
 42 files changed, 809 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/linux/sections.h

diff --git a/Documentation/index.rst b/Documentation/index.rst
index cb5d77699c60..71e0305c036d 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -57,6 +57,7 @@ needed).
    media/index
    gpu/index
    security/index
+   sections/index
    sound/index
    crypto/index
 
diff --git a/Documentation/sections/background.rst b/Documentation/sections/background.rst
new file mode 100644
index 000000000000..0ecf9104aaa2
--- /dev/null
+++ b/Documentation/sections/background.rst
@@ -0,0 +1,105 @@
+======================
+ELF section background
+======================
+
+About
+=====
+
+The purpose of this chapter is to help those not familiar with ELF to brush up
+the latest ELF specifications in order to help understand how Linux uses and
+defines its own ELF sections.
+
+Standardized ELF
+================
+
+The first publication documenting ELF was UNIX System Laboratories' (USL)
+*System V Release 4 Application Binary Interface* (`SRV4 ABI`_) specification.
+Originally ELF was only a small part of the SRV4 ABI, with time however new
+specifications only put focus on ELF, such was the case of the *TIS Portable
+Formats Specification version 1.2* (`TIS 1.2`_). As of TIS 1.2, ELF was
+supplemented with processor specific ELF addendums, available on the *Linux
+Foundation referenced specification page* (`LF ref page`_). The latest ELF
+specification is the *System V Application Binary Interface - DRAFT - 24 April
+2001* (`gabi4`_).
+
+.. _SRV4 ABI: http://www.sco.com/developers/devspecs/gabi41.pdf
+.. _TIS 1.2: https://refspecs.linuxbase.org/elf/elf.pdf
+.. _LF ref page: https://refspecs.linuxbase.org/
+.. _gabi4: https://refspecs.linuxbase.org/elf/gabi4+/contents.html
+
+ELF views on Linux
+==================
+
+There are two views which can be used for inspecting data in an ELF file, a
+Linking view, and an Execution view. A Section Header Table enables one to
+describe an object using the Linking view while a Program Header Table enables
+one to describe an object using the Execution view. The views are not mutually
+exclusive. For intance, vmlinux can be viewed under both views, ``readelf -S
+vmlinux`` for the Linking view, and ``readelf -l vmlinux`` for the Execution
+view.  In Linux only the vmlinux file will have an Execution view, even modules
+lack an Execution view given that vmlinux is the only file that describes how
+the the kernel runs from the start.  All other Linux kernel object files have
+an available Linking view.
+
+Under the Linking view, the Section Header Table describes all available
+sections. The Section Header Table is an array of ELF section header data
+structures. If on a 32-bit system this is ``struct elf32_shd``, if on a 64-bit
+this is ``struct elf64_shdr``. Sections are only visible on object files that
+have a Linking view, since all Linux kernel files have Linking view, all kernel
+objects have ELF sections.
+
+Limitations on ELF sections
+===========================
+
+We provide a summary on the limitations of ELF sections. Refer to the public
+ELF specifications for details. Note that 64-bit limitations may depend
+on processor specific section attributes to be used, refer to your processsor
+specification if unsure.
+
+Its worth ellaborating on the limitations on the name of an ELF section:
+ELF section names are stored as strings as per the ELF specification, and
+as can be expected, these don't have explicit limitations. The implicit
+limitation then depends on the size of an ELF object file and ELF section.
+
+If using really large kernels or objects with large amounts of sections one
+would still need to be sure that ELF loader in charge of loading the Linux
+kernel is properly updated to handle coping with the latest ELF extensions.
+
+   .. flat-table:: Limitations on ELF Sections
+
+      * - Section attribute
+        - 32-bit
+        - 64-bit
+
+      * - ELF section name
+        - Size of an ELF section
+        - Size of an ELF section
+
+      * - Size of an ELF section
+        - 4 GiB
+        - 16 EiB
+
+      * - Max number of sections in an object file
+        - 4 GiEntries (4294967296)
+        - 16 EiEntries (18446744073709551616)
+
+Program specific ELF sections
+=============================
+
+The ELF specification allows for a section type to be specified as
+*Program specific section*, defined as ``SHT_PROGBITS``. This sections type
+enables programs to customize sections for their own use. In assembly this
+specified ``@progbits`` on most architectures, on ARM this is ``%progbits``.
+
+``SHT_PROGBITS`` is used by Linux for defining and using Linux ELF sections.
+
+Special ELF Sections
+====================
+
+The ELF specification defines *Special ELF Sections* on chapter 4 (`gabi4
+ch4`_). These are defined as sections which hold program and control
+information. Of these sections, a few have the section type as
+``SHT_PROGBITS``. This enables Linux to *further customize* use of the section
+beyond what the ELF specification suggests.
+
+.. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
new file mode 100644
index 000000000000..faa1c57595e1
--- /dev/null
+++ b/Documentation/sections/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel ELF sections'
+html_search_language = 'en'
diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
new file mode 100644
index 000000000000..f37511ef05e7
--- /dev/null
+++ b/Documentation/sections/index.rst
@@ -0,0 +1,17 @@
+=========================
+Linux Kernel ELF sections
+=========================
+
+This book documents the different ELF sections used on the Linux kernel.
+We start off by providing references to how ELF was standardized, references
+to the standards on ELF sections, review limitations of ELF sections, and
+finally how Linux uses ELF sections in the Linux kernel. Certain important
+Linux ELF sections are documented carefully: we describe the goal of the
+ELF section, and address concurrency considerations when applicable. A few
+common a set of Linux helpers for ELF sections are also documented.
+
+.. toctree::
+   :maxdepth: 4
+
+   background
+   section-core
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
new file mode 100644
index 000000000000..ac5815a0d9b3
--- /dev/null
+++ b/Documentation/sections/section-core.rst
@@ -0,0 +1,148 @@
+===================================
+Linux ELF program specific sections
+===================================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux ELF program specific sections
+
+Linux linker script
+===================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux linker script
+
+Memory protection
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Memory protection
+
+mark_rodata_ro
+-----------------------
+.. kernel-doc:: include/linux/init.h
+   :functions: mark_rodata_ro
+
+.rodata
+-------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .rodata
+
+.text
+-----
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .text
+
+.data
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .data
+
+Linux .init\* sections
+======================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux init sections
+
+.init.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.text
+
+.init.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.data
+
+.init.rodata
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.rodata
+
+Initcall levels
+---------------
+.. kernel-doc:: include/linux/init.h
+   :doc: Initcall levels
+
+.initcall
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .initcall
+
+__define_initcall
+-----------------
+.. kernel-doc:: include/linux/init.h
+   :functions: __define_initcall
+
+Linux .exit\* sections
+======================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux exit sections
+
+.exit.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.text
+
+.exit.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.data
+
+.exitcall.exit
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exitcall.exit
+
+Linux .ref\* sections
+=====================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux references to init sections
+
+.ref.text
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.text
+
+.ref.data
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.data
+
+.ref.rodata
+-----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.rodata
+
+Generic Linux kernel section helpers
+====================================
+
+Introduction
+-------------
+.. kernel-doc:: include/linux/sections.h
+   :doc: Introduction
+
+LINUX_SECTION_ALIGNMENT
+-----------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_ALIGNMENT
+
+LINUX_SECTION_START
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_START
+
+LINUX_SECTION_END
+-----------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_END
+
+DECLARE_LINUX_SECTION
+---------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION
+
+DECLARE_LINUX_SECTION_RO
+------------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION_RO
diff --git a/MAINTAINERS b/MAINTAINERS
index d0b2b50705bd..308826f5094b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5422,6 +5422,18 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTIONS
+M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
+M:	Josh Poimboeuf <jpoimboe@redhat.com>
+M:	"H. Peter Anvin" <hpa@zytor.com>
+L:	linux-arch@vger.kernel.org
+L:	linux-kernel@vger.kernel.org
+S:	Supported
+F:	include/asm-generic/section-core.h
+F:	include/asm-generic/sections.h
+F:	include/asm-generic/vmlinux.lds.h
+F:	Documentation/sections/section-core.rst
+
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index bf8475ce85ee..5422827f1585 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += section-core.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index c332604606dd..7b2cb3dea5fc 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index efb21757d41f..9b69a22a9ae1 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += unaligned.h
 
 generated-y += mach-types.h
 generated-y += unistd-nr.h
+generic-y += section-core.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 8365a84c2640..00ace5e826f1 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 241b9b9729d8..f2c3b656a0e7 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 2fb67b59d188..bf20541bcf21 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -47,3 +47,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 64465e7e2245..38127ce747be 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -62,3 +62,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 1778805f6380..385cd88a9d9e 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += types.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 1fa084cf1a43..46d7c599d9b8 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 373cb23301e3..1ec04ec1c82b 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -75,3 +75,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index db8ddabc6bd2..37d7bfae7619 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -60,3 +60,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 502a91d8dbbd..672c6d5da18c 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 860e440611c9..6111e1523750 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1f2e5d31cb24..1277b45bf4f9 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -34,3 +34,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 167150c701d1..b1011375cd7a 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -55,3 +55,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index b0ae88c9fed9..c6c2cf6edc98 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 45b0d6568270..a67d3177f3ca 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -20,3 +20,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 1c8dd0f5cd5d..f8145bc85835 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index d63330e88379..c9c7cb82b00f 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 2832f031fb11..86175e701869 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -71,3 +71,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 91f53c07f410..18a9d4c5ead7 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -28,3 +28,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 5c4fbc80dc6c..4322d9746cdb 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
+generic-y += section-core.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 8aea32fe8bd2..63a1c2924b91 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index a05218ff3fe4..f089a264cd38 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 751c3373a92c..7b0356dca562 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 0569bfac4afb..438f86573dc5 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 2d1f5638974c..fb6b831c1fba 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 052f7f6d0551..580bd5ff828f 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -26,3 +26,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
new file mode 100644
index 000000000000..0b9c68429a1a
--- /dev/null
+++ b/arch/unicore32/include/asm/section-core.h
@@ -0,0 +1,19 @@
+#ifndef __UNICORE_SECTION_CORE_ASM_H__
+#define __UNICORE_SECTION_CORE_ASM_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/.
+ */
+
+/* Unicore32 has known to not work properly with the type set, so ignore it */
+
+#define __set_section_core_type(___section, ___core, ___name,		\
+				___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags
+
+#include <asm-generic/section-core.h>
+
+#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 2b892e2313a9..af975f21eeee 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
+generic-y += section-core.h
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index b7fbaa56b51a..7879c31e66a7 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..bb16befc4251
--- /dev/null
+++ b/include/asm-generic/section-core.h
@@ -0,0 +1,307 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Linux ELF program specific sections
+ *
+ * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and
+ * definition of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
+ * sections. This chaper is dedicated to documenting Linux program specific
+ * sections and helpers available to make use of these easier to implement and
+ * use.
+ *
+ * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
+ */
+
+/**
+ * DOC: Linux linker script
+ *
+ * Linux uses a custom linker script to build the vmlinux binary, it uses it to
+ * strategically place and define Linux ELF sections.  Each architecture needs
+ * to implement its own linker script, it is expected to reside in
+ * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
+ * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
+ * as well as some helpers documented in this chapter.
+ *
+ * In assembly it is common practice to use dots (``.``) in labels to avoid
+ * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
+ * name but not a C symbol. Historically then, two dots are used (``..``)
+ * have been used in linker scripts when adding program specific sections
+ * when there are concerns to avoid clashes with compiler generated sections.
+ */
+
+/**
+ * DOC: Memory protection
+ *
+ * Linux allows architectures which support memory protection features to
+ * take advantage of them by letting architectures define and enable
+ * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.
+ * mark_rodata_ro() can be used for instance to mark specific sections as
+ * read-only or non-executable.
+ *
+ * Linux typically follows a convention to have the .rodata ELF section follow
+ * after the .text ELF section, it does this to help architectures which
+ * support memory protection to mark both .text and .rodata as read-only in
+ * one shot.
+ *
+ * For more details refer to mark_rodata_ro().
+ */
+
+/**
+ * DOC: .rodata
+ *
+ * ELF section used for data which must be protected from write access.
+ */
+
+/**
+ * DOC: .text
+ *
+ * ELF section name used for code (functions) used during regular
+ * kernel run time.
+ */
+
+/**
+ * DOC: .data
+ *
+ * ELF section used for read-write data.
+ */
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: .init.text
+ *
+ * ELF section for code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+
+/**
+ * DOC: .init.data
+ *
+ * ELF section used for data structures used only during boot or driver
+ * initialization.
+ */
+
+/**
+ * DOC: .init.rodata
+ *
+ * ELF section used for read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+
+/**
+ * DOC: .initcall
+ *
+ * ELF section used for subsystem init calls. There are init levels
+ * representing different functionality in the kernel. For more details
+ * refer to __define_initcall().
+ */
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: .exit.text
+ *
+ * ELF section used to for code (functions) used only during module unload.
+ */
+
+/**
+ * DOC: .exit.data
+ *
+ * ELF section used to for data structures used only during module
+ * unload.
+ */
+
+/**
+ * DOC: .exitcall.exit
+ *
+ * ELF section used for exit routines, order is important and maintained by
+ * link order.
+ */
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: .ref.text
+ *
+ * ELF section used to annotate code (functions) which has been vetteed as
+ * valid for its reference or use of other code (functions) or data structures
+ * which are part of the init sections.
+ */
+
+/**
+ * DOC: .ref.data
+ *
+ * ELF section used for data structures which have been vetteed for its
+ * reference or use of other code (functions) or data structures part of the
+ * init sections.
+ */
+
+/**
+ * DOC: .ref.rodata
+ *
+ * ELF section used to annotate const code (functions) const data structures
+ * which has been vetteed for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section..___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section..__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifndef LINKER_SCRIPT
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align=16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 4df64a1fc09e..b145ae8d9cbe 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_GENERIC_SECTIONS_H_
 #define _ASM_GENERIC_SECTIONS_H_
 
+#include <asm/section-core.h>
+
 /* References to section boundaries */
 
 #include <linux/compiler.h>
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 0968d13b3885..483f60c451f9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -55,6 +55,7 @@
 #endif
 
 #include <linux/export.h>
+#include <asm/section-core.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
diff --git a/include/linux/init.h b/include/linux/init.h
index 885c3e6d0f9d..116e3262332a 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -130,6 +130,24 @@ int __init init_rootfs(void);
 extern bool rodata_enabled;
 #endif
 #ifdef CONFIG_DEBUG_RODATA
+/**
+ * mark_rodata_ro - implemement memory protection for ELF sections
+ *
+ * Architectures which support memory protection define a kernel configuration
+ * entry for CONFIG_DEBUG_RODATA, enable it in and implement mark_rodata_ro().
+ * mark_rodata_ro() should strive to adjust the .rodata and .text ELF sections
+ * with read-only memory protection to prevent modifications of these sections
+ * after bootup. It can also try to use memory protection to prevent execution
+ * on the .rodata ELF section.
+ *
+ * In order to help architectures set both .text and .rodata as read-only with
+ * memory protections in one shot Linux has typically followed the convention
+ * to have the .rodata ELF section follow the .text ELF section on the vmlinux
+ * linker script.
+ *
+ * Linux calls mark_rodata_ro() after freeing .init code and prior to calling
+ * the first init userspace process.
+ */
 void mark_rodata_ro(void);
 #endif
 
@@ -140,25 +158,70 @@ extern bool initcall_debug;
 #endif
   
 #ifndef MODULE
+/**
+ * DOC: Initcall levels
+ *
+ * When Linux boots the kernel do_initcalls() iterates over each Linux
+ * initialization level ID and calls all routines embedded on each level ID.
+ * Prior to v2.5.2.3 Linux had only one init level onto which all init
+ * functions folded onto using __initcall(). After v2.5.2.4 Linux split up
+ * initcalls into 7 separate initcall subsection levels, each level describing
+ * different functionality part of the kernel (commit `9d6ba121b7e17085`_
+ * (v2.5.2.3 -> v2.5.2.4)). In order to remain backward compatible __initcall()
+ * calls were left mapped to device_initcall().
+ *
+ * Each init level consists of a dedicated ELF section, init functions are
+ * associated to an init level by linking it into the respective level's
+ * ELF section.
+ *
+ * Lower order init levels run prior to higher order init levels. Ordering
+ * inside each initcall level is determined by respective link order.
+ *
+ * .. _9d6ba121b7e17085: https://git.kernel.org/cgit/linux/kernel/git/history/history.git/commit/?id=9d6ba121b7e17085c95139233686b27a4d4c650e
+ */
 
 #ifndef __ASSEMBLY__
 
-/*
- * initcalls are now grouped by functionality into separate
- * subsections. Ordering inside the subsections is determined
- * by link order. 
- * For backwards compatibility, initcall() puts the call in 
- * the device init subsection.
+/**
+ * __define_initcall - wrapper for definiting init levels
  *
- * The `id' arg to __define_initcall() is needed so that multiple initcalls
- * can point at the same handler without causing duplicate-symbol build errors.
+ * @fn: init routine
+ * @id: init level
  *
- * Initcalls are run by placing pointers in initcall sections that the
- * kernel iterates at runtime. The linker can do dead code / data elimination
- * and remove that completely, so the initcall sections have to be marked
- * as KEEP() in the linker script.
+ * Defines a kernel initialization level. A respective linker script entry
+ * is required to ensure the init level is accounted for and to ensure symbols
+ * exist for iterating over all functions in the init level. A init level
+ * represents a series of functionality in the kernel.
+ *
+ * Ordering within an initialization level is determined by link order, so
+ * for instance if a Makefile had::
+ *
+ *	obj-y += foo.o
+ *	obj-y += bar.o
+ *
+ * And foo.c::
+ *
+ *	subsys_initcall(foo_init);
+ *
+ * And bar.c had::
+ *
+ *	subsys_initcall(bar_init);
+ *
+ * foo_init() would be called prior to bar_init().
+ *
+ * Note that @id in __define_initcall() also enables multiple initcalls
+ * to be created using the same handler for different init levels without
+ * causing duplicate-symbol build errors.
+ *
+ * Initcalls are run by placing start symbols to initcall levels inside ELF
+ * sections, the kernel in turn uses these symbols to iterate over each init
+ * level at runtime with do_initcall_level(). The end of each init level is
+ * marked by the subsequent's symbol's start address until we reach the symbol
+ * ``__initcall_end``. The linker can do dead code / data elimination and each
+ * init level start symbol could be removed completely in this process, to
+ * avoid this each init level start symbols must be marked as 'KEEP()' in the
+ * linker script to avoid any linker optimization heuristic on initcalls.
  */
-
 #define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
 	__attribute__((__section__(".initcall" #id ".init"))) = fn;
diff --git a/include/linux/sections.h b/include/linux/sections.h
new file mode 100644
index 000000000000..6771c727bcd1
--- /dev/null
+++ b/include/linux/sections.h
@@ -0,0 +1,87 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_CORE(section, core, name, level)			\
+	#section ".." #core "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 01/14] generic-sections: add section core helpers
@ 2016-12-22  2:37       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:37 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

Linux makes extensive use of custom ELF header sections,
documentation for these are well scatterred. Unify this
documentation in a central place and provide helpers to
build custom Linux sections.

This also generalizes sections code to enable avoiding
modifying the linker scripts when we want to add new
custom Linux sections. In order to make this generally
useful we need to ensure all architectures can make use of
core section helpers but that they can also override should
this be needed. Instead of relying on section.h this adds
a sections-core.h since this will be targetted to be safe
to be used on asm code, linker scripts and C code.

v5:

o Huge documentation revamp based on a careful review of the ELF
  specifications. Includes documentation now also about usage of
  two dots (..) when prefixing ELF program specific sections.

o Replace macros for sections names in favor of just using
  the section names explicitly in the linker script. This is
  perhaps more work to grep but this is what folks seem to
  currently prefer.

o Fix .text and .rodata documentation to explain memory protection
  strategies which architectures can embrace upon initialization
  (documents CONFIG_DEBUG_RODATA and mark_rodata_ro())

o Skip the 'Linux section ordering' documentation section, we'll instead
  add this on subsequent patch which will expand on it considerably

o Dropped tree on MAINTAINERS -- as per discussions with Arnd, hpa and
  Josh, its easier to just let changes for sections go in through the
  respective tree that needs the changes.

o Fix typos on documentation

o Dropped SECTION_ALL(), __SECTION_CORE(), SECTION_CORE_ALL() macros
  since we are favoring using explicit section names. These are
  useless if we are being explicit.

o Drop LINUX_SECTION_SIZE(), LINUX_SECTION_EMPTY() in favor of having
  section ranges and linker tables define their own, to avoid confusion
  and make code more readable.

o Add __define_initcall() documentation and a small section describing
  our current initcall levels. This should help also clarify what was
  meant about keeping backward compatiblity.

v4:

o Port to shiny new sphinx documentation format

o fix a unicore32 build, turns out this actually fixes unicore32
  defconfig builds which were failing for a long while. unicore32
  does not seem to grok well the type passed on a section declaration,
  this ignores it.

o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
  this was causing final linker issues with blackfin -- this is
  a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
  being metatag. metatag is not supported on 0-day so I cannot confirm
  compilation there.

o Added SECTION_CORE() for C code, used later by __LINUX_RANGE()

o Since SECTION_CORE() is defined for linker script and C code, share
  the same helper and just use a __stringify() for the C code as is done
  for the other C helpers.

o move generic sections to asm-generic/section-core.h instead.
  PowerPC compilation blows up if asm/jump_labels.h gets
  section.h included, fixing this is not in any way easy.
  The list of issues are endless. Moving new data to a new
  simple file resolves this.

o since things are now in asm-generic/section-core.h the
  guard changes on asm-generic/sections.h and each architecture
  sections.h are no longer needed

o Give generic sections some maintainer love, that change is
  Acked-by Arnd Bergmann, Josh and hpa.

o A few checkpatch.pl style fixes

o As suggested by James Hogan use generic-y to copy generic
  header files on architectures that do not have a sections.h
  instead of writing a simple file only to include the generic one.

v3:

o add missing sections.h for architectures that did not
  have it

o move generic sections to asm-generic/sections.h

o add generic asm helpers section_type(), section_type_asmtype(),
  push_section_type() -- these helpers enable easy use for
  for later declaring and using of custom linux sections using
  more standard APIs in both C code, asm code (C asm calls, or
  asm files), enabling future standardized section types to
  be more immediately accessible to asm code, not just C code.
  Note for ASM_CMD_SEP we use by default "\n", architectures needed
  to override can do so on their own sections.h prior to inclusion
  of asm-generic/sections.h

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/index.rst                   |   1 +
 Documentation/sections/background.rst     | 105 ++++++++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  17 ++
 Documentation/sections/section-core.rst   | 148 ++++++++++++++
 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/Kbuild               |   1 +
 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/section-core.h |  19 ++
 arch/x86/include/asm/Kbuild               |   1 +
 arch/xtensa/include/asm/Kbuild            |   1 +
 include/asm-generic/section-core.h        | 307 ++++++++++++++++++++++++++++++
 include/asm-generic/sections.h            |   2 +
 include/asm-generic/vmlinux.lds.h         |   1 +
 include/linux/init.h                      |  89 +++++++--
 include/linux/sections.h                  |  87 +++++++++
 42 files changed, 809 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/linux/sections.h

diff --git a/Documentation/index.rst b/Documentation/index.rst
index cb5d77699c60..71e0305c036d 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -57,6 +57,7 @@ needed).
    media/index
    gpu/index
    security/index
+   sections/index
    sound/index
    crypto/index
 
diff --git a/Documentation/sections/background.rst b/Documentation/sections/background.rst
new file mode 100644
index 000000000000..0ecf9104aaa2
--- /dev/null
+++ b/Documentation/sections/background.rst
@@ -0,0 +1,105 @@
+======================
+ELF section background
+======================
+
+About
+=====
+
+The purpose of this chapter is to help those not familiar with ELF to brush up
+the latest ELF specifications in order to help understand how Linux uses and
+defines its own ELF sections.
+
+Standardized ELF
+================
+
+The first publication documenting ELF was UNIX System Laboratories' (USL)
+*System V Release 4 Application Binary Interface* (`SRV4 ABI`_) specification.
+Originally ELF was only a small part of the SRV4 ABI, with time however new
+specifications only put focus on ELF, such was the case of the *TIS Portable
+Formats Specification version 1.2* (`TIS 1.2`_). As of TIS 1.2, ELF was
+supplemented with processor specific ELF addendums, available on the *Linux
+Foundation referenced specification page* (`LF ref page`_). The latest ELF
+specification is the *System V Application Binary Interface - DRAFT - 24 April
+2001* (`gabi4`_).
+
+.. _SRV4 ABI: http://www.sco.com/developers/devspecs/gabi41.pdf
+.. _TIS 1.2: https://refspecs.linuxbase.org/elf/elf.pdf
+.. _LF ref page: https://refspecs.linuxbase.org/
+.. _gabi4: https://refspecs.linuxbase.org/elf/gabi4+/contents.html
+
+ELF views on Linux
+==================
+
+There are two views which can be used for inspecting data in an ELF file, a
+Linking view, and an Execution view. A Section Header Table enables one to
+describe an object using the Linking view while a Program Header Table enables
+one to describe an object using the Execution view. The views are not mutually
+exclusive. For intance, vmlinux can be viewed under both views, ``readelf -S
+vmlinux`` for the Linking view, and ``readelf -l vmlinux`` for the Execution
+view.  In Linux only the vmlinux file will have an Execution view, even modules
+lack an Execution view given that vmlinux is the only file that describes how
+the the kernel runs from the start.  All other Linux kernel object files have
+an available Linking view.
+
+Under the Linking view, the Section Header Table describes all available
+sections. The Section Header Table is an array of ELF section header data
+structures. If on a 32-bit system this is ``struct elf32_shd``, if on a 64-bit
+this is ``struct elf64_shdr``. Sections are only visible on object files that
+have a Linking view, since all Linux kernel files have Linking view, all kernel
+objects have ELF sections.
+
+Limitations on ELF sections
+===========================
+
+We provide a summary on the limitations of ELF sections. Refer to the public
+ELF specifications for details. Note that 64-bit limitations may depend
+on processor specific section attributes to be used, refer to your processsor
+specification if unsure.
+
+Its worth ellaborating on the limitations on the name of an ELF section:
+ELF section names are stored as strings as per the ELF specification, and
+as can be expected, these don't have explicit limitations. The implicit
+limitation then depends on the size of an ELF object file and ELF section.
+
+If using really large kernels or objects with large amounts of sections one
+would still need to be sure that ELF loader in charge of loading the Linux
+kernel is properly updated to handle coping with the latest ELF extensions.
+
+   .. flat-table:: Limitations on ELF Sections
+
+      * - Section attribute
+        - 32-bit
+        - 64-bit
+
+      * - ELF section name
+        - Size of an ELF section
+        - Size of an ELF section
+
+      * - Size of an ELF section
+        - 4 GiB
+        - 16 EiB
+
+      * - Max number of sections in an object file
+        - 4 GiEntries (4294967296)
+        - 16 EiEntries (18446744073709551616)
+
+Program specific ELF sections
+=============================
+
+The ELF specification allows for a section type to be specified as
+*Program specific section*, defined as ``SHT_PROGBITS``. This sections type
+enables programs to customize sections for their own use. In assembly this
+specified ``@progbits`` on most architectures, on ARM this is ``%progbits``.
+
+``SHT_PROGBITS`` is used by Linux for defining and using Linux ELF sections.
+
+Special ELF Sections
+====================
+
+The ELF specification defines *Special ELF Sections* on chapter 4 (`gabi4
+ch4`_). These are defined as sections which hold program and control
+information. Of these sections, a few have the section type as
+``SHT_PROGBITS``. This enables Linux to *further customize* use of the section
+beyond what the ELF specification suggests.
+
+.. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
new file mode 100644
index 000000000000..faa1c57595e1
--- /dev/null
+++ b/Documentation/sections/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel ELF sections'
+html_search_language = 'en'
diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
new file mode 100644
index 000000000000..f37511ef05e7
--- /dev/null
+++ b/Documentation/sections/index.rst
@@ -0,0 +1,17 @@
+=========================
+Linux Kernel ELF sections
+=========================
+
+This book documents the different ELF sections used on the Linux kernel.
+We start off by providing references to how ELF was standardized, references
+to the standards on ELF sections, review limitations of ELF sections, and
+finally how Linux uses ELF sections in the Linux kernel. Certain important
+Linux ELF sections are documented carefully: we describe the goal of the
+ELF section, and address concurrency considerations when applicable. A few
+common a set of Linux helpers for ELF sections are also documented.
+
+.. toctree::
+   :maxdepth: 4
+
+   background
+   section-core
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
new file mode 100644
index 000000000000..ac5815a0d9b3
--- /dev/null
+++ b/Documentation/sections/section-core.rst
@@ -0,0 +1,148 @@
+===================================
+Linux ELF program specific sections
+===================================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux ELF program specific sections
+
+Linux linker script
+===================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux linker script
+
+Memory protection
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Memory protection
+
+mark_rodata_ro
+-----------------------
+.. kernel-doc:: include/linux/init.h
+   :functions: mark_rodata_ro
+
+.rodata
+-------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .rodata
+
+.text
+-----
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .text
+
+.data
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .data
+
+Linux .init\* sections
+======================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux init sections
+
+.init.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.text
+
+.init.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.data
+
+.init.rodata
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.rodata
+
+Initcall levels
+---------------
+.. kernel-doc:: include/linux/init.h
+   :doc: Initcall levels
+
+.initcall
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .initcall
+
+__define_initcall
+-----------------
+.. kernel-doc:: include/linux/init.h
+   :functions: __define_initcall
+
+Linux .exit\* sections
+======================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux exit sections
+
+.exit.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.text
+
+.exit.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.data
+
+.exitcall.exit
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exitcall.exit
+
+Linux .ref\* sections
+=====================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux references to init sections
+
+.ref.text
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.text
+
+.ref.data
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.data
+
+.ref.rodata
+-----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.rodata
+
+Generic Linux kernel section helpers
+====================================
+
+Introduction
+-------------
+.. kernel-doc:: include/linux/sections.h
+   :doc: Introduction
+
+LINUX_SECTION_ALIGNMENT
+-----------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_ALIGNMENT
+
+LINUX_SECTION_START
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_START
+
+LINUX_SECTION_END
+-----------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_END
+
+DECLARE_LINUX_SECTION
+---------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION
+
+DECLARE_LINUX_SECTION_RO
+------------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION_RO
diff --git a/MAINTAINERS b/MAINTAINERS
index d0b2b50705bd..308826f5094b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5422,6 +5422,18 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTIONS
+M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
+M:	Josh Poimboeuf <jpoimboe@redhat.com>
+M:	"H. Peter Anvin" <hpa@zytor.com>
+L:	linux-arch@vger.kernel.org
+L:	linux-kernel@vger.kernel.org
+S:	Supported
+F:	include/asm-generic/section-core.h
+F:	include/asm-generic/sections.h
+F:	include/asm-generic/vmlinux.lds.h
+F:	Documentation/sections/section-core.rst
+
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index bf8475ce85ee..5422827f1585 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += section-core.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index c332604606dd..7b2cb3dea5fc 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index efb21757d41f..9b69a22a9ae1 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += unaligned.h
 
 generated-y += mach-types.h
 generated-y += unistd-nr.h
+generic-y += section-core.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 8365a84c2640..00ace5e826f1 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 241b9b9729d8..f2c3b656a0e7 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 2fb67b59d188..bf20541bcf21 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -47,3 +47,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 64465e7e2245..38127ce747be 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -62,3 +62,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 1778805f6380..385cd88a9d9e 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += types.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 1fa084cf1a43..46d7c599d9b8 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 373cb23301e3..1ec04ec1c82b 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -75,3 +75,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index db8ddabc6bd2..37d7bfae7619 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -60,3 +60,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 502a91d8dbbd..672c6d5da18c 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 860e440611c9..6111e1523750 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1f2e5d31cb24..1277b45bf4f9 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -34,3 +34,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 167150c701d1..b1011375cd7a 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -55,3 +55,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index b0ae88c9fed9..c6c2cf6edc98 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 45b0d6568270..a67d3177f3ca 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -20,3 +20,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 1c8dd0f5cd5d..f8145bc85835 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index d63330e88379..c9c7cb82b00f 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 2832f031fb11..86175e701869 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -71,3 +71,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 91f53c07f410..18a9d4c5ead7 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -28,3 +28,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 5c4fbc80dc6c..4322d9746cdb 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
+generic-y += section-core.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 8aea32fe8bd2..63a1c2924b91 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index a05218ff3fe4..f089a264cd38 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 751c3373a92c..7b0356dca562 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 0569bfac4afb..438f86573dc5 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 2d1f5638974c..fb6b831c1fba 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 052f7f6d0551..580bd5ff828f 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -26,3 +26,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
new file mode 100644
index 000000000000..0b9c68429a1a
--- /dev/null
+++ b/arch/unicore32/include/asm/section-core.h
@@ -0,0 +1,19 @@
+#ifndef __UNICORE_SECTION_CORE_ASM_H__
+#define __UNICORE_SECTION_CORE_ASM_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/.
+ */
+
+/* Unicore32 has known to not work properly with the type set, so ignore it */
+
+#define __set_section_core_type(___section, ___core, ___name,		\
+				___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags
+
+#include <asm-generic/section-core.h>
+
+#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 2b892e2313a9..af975f21eeee 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
+generic-y += section-core.h
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index b7fbaa56b51a..7879c31e66a7 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..bb16befc4251
--- /dev/null
+++ b/include/asm-generic/section-core.h
@@ -0,0 +1,307 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Linux ELF program specific sections
+ *
+ * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and
+ * definition of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
+ * sections. This chaper is dedicated to documenting Linux program specific
+ * sections and helpers available to make use of these easier to implement and
+ * use.
+ *
+ * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
+ */
+
+/**
+ * DOC: Linux linker script
+ *
+ * Linux uses a custom linker script to build the vmlinux binary, it uses it to
+ * strategically place and define Linux ELF sections.  Each architecture needs
+ * to implement its own linker script, it is expected to reside in
+ * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
+ * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
+ * as well as some helpers documented in this chapter.
+ *
+ * In assembly it is common practice to use dots (``.``) in labels to avoid
+ * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
+ * name but not a C symbol. Historically then, two dots are used (``..``)
+ * have been used in linker scripts when adding program specific sections
+ * when there are concerns to avoid clashes with compiler generated sections.
+ */
+
+/**
+ * DOC: Memory protection
+ *
+ * Linux allows architectures which support memory protection features to
+ * take advantage of them by letting architectures define and enable
+ * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.
+ * mark_rodata_ro() can be used for instance to mark specific sections as
+ * read-only or non-executable.
+ *
+ * Linux typically follows a convention to have the .rodata ELF section follow
+ * after the .text ELF section, it does this to help architectures which
+ * support memory protection to mark both .text and .rodata as read-only in
+ * one shot.
+ *
+ * For more details refer to mark_rodata_ro().
+ */
+
+/**
+ * DOC: .rodata
+ *
+ * ELF section used for data which must be protected from write access.
+ */
+
+/**
+ * DOC: .text
+ *
+ * ELF section name used for code (functions) used during regular
+ * kernel run time.
+ */
+
+/**
+ * DOC: .data
+ *
+ * ELF section used for read-write data.
+ */
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: .init.text
+ *
+ * ELF section for code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+
+/**
+ * DOC: .init.data
+ *
+ * ELF section used for data structures used only during boot or driver
+ * initialization.
+ */
+
+/**
+ * DOC: .init.rodata
+ *
+ * ELF section used for read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+
+/**
+ * DOC: .initcall
+ *
+ * ELF section used for subsystem init calls. There are init levels
+ * representing different functionality in the kernel. For more details
+ * refer to __define_initcall().
+ */
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: .exit.text
+ *
+ * ELF section used to for code (functions) used only during module unload.
+ */
+
+/**
+ * DOC: .exit.data
+ *
+ * ELF section used to for data structures used only during module
+ * unload.
+ */
+
+/**
+ * DOC: .exitcall.exit
+ *
+ * ELF section used for exit routines, order is important and maintained by
+ * link order.
+ */
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: .ref.text
+ *
+ * ELF section used to annotate code (functions) which has been vetteed as
+ * valid for its reference or use of other code (functions) or data structures
+ * which are part of the init sections.
+ */
+
+/**
+ * DOC: .ref.data
+ *
+ * ELF section used for data structures which have been vetteed for its
+ * reference or use of other code (functions) or data structures part of the
+ * init sections.
+ */
+
+/**
+ * DOC: .ref.rodata
+ *
+ * ELF section used to annotate const code (functions) const data structures
+ * which has been vetteed for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section..___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section..__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifndef LINKER_SCRIPT
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align=16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 4df64a1fc09e..b145ae8d9cbe 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_GENERIC_SECTIONS_H_
 #define _ASM_GENERIC_SECTIONS_H_
 
+#include <asm/section-core.h>
+
 /* References to section boundaries */
 
 #include <linux/compiler.h>
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 0968d13b3885..483f60c451f9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -55,6 +55,7 @@
 #endif
 
 #include <linux/export.h>
+#include <asm/section-core.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
diff --git a/include/linux/init.h b/include/linux/init.h
index 885c3e6d0f9d..116e3262332a 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -130,6 +130,24 @@ int __init init_rootfs(void);
 extern bool rodata_enabled;
 #endif
 #ifdef CONFIG_DEBUG_RODATA
+/**
+ * mark_rodata_ro - implemement memory protection for ELF sections
+ *
+ * Architectures which support memory protection define a kernel configuration
+ * entry for CONFIG_DEBUG_RODATA, enable it in and implement mark_rodata_ro().
+ * mark_rodata_ro() should strive to adjust the .rodata and .text ELF sections
+ * with read-only memory protection to prevent modifications of these sections
+ * after bootup. It can also try to use memory protection to prevent execution
+ * on the .rodata ELF section.
+ *
+ * In order to help architectures set both .text and .rodata as read-only with
+ * memory protections in one shot Linux has typically followed the convention
+ * to have the .rodata ELF section follow the .text ELF section on the vmlinux
+ * linker script.
+ *
+ * Linux calls mark_rodata_ro() after freeing .init code and prior to calling
+ * the first init userspace process.
+ */
 void mark_rodata_ro(void);
 #endif
 
@@ -140,25 +158,70 @@ extern bool initcall_debug;
 #endif
   
 #ifndef MODULE
+/**
+ * DOC: Initcall levels
+ *
+ * When Linux boots the kernel do_initcalls() iterates over each Linux
+ * initialization level ID and calls all routines embedded on each level ID.
+ * Prior to v2.5.2.3 Linux had only one init level onto which all init
+ * functions folded onto using __initcall(). After v2.5.2.4 Linux split up
+ * initcalls into 7 separate initcall subsection levels, each level describing
+ * different functionality part of the kernel (commit `9d6ba121b7e17085`_
+ * (v2.5.2.3 -> v2.5.2.4)). In order to remain backward compatible __initcall()
+ * calls were left mapped to device_initcall().
+ *
+ * Each init level consists of a dedicated ELF section, init functions are
+ * associated to an init level by linking it into the respective level's
+ * ELF section.
+ *
+ * Lower order init levels run prior to higher order init levels. Ordering
+ * inside each initcall level is determined by respective link order.
+ *
+ * .. _9d6ba121b7e17085: https://git.kernel.org/cgit/linux/kernel/git/history/history.git/commit/?id=9d6ba121b7e17085c95139233686b27a4d4c650e
+ */
 
 #ifndef __ASSEMBLY__
 
-/*
- * initcalls are now grouped by functionality into separate
- * subsections. Ordering inside the subsections is determined
- * by link order. 
- * For backwards compatibility, initcall() puts the call in 
- * the device init subsection.
+/**
+ * __define_initcall - wrapper for definiting init levels
  *
- * The `id' arg to __define_initcall() is needed so that multiple initcalls
- * can point at the same handler without causing duplicate-symbol build errors.
+ * @fn: init routine
+ * @id: init level
  *
- * Initcalls are run by placing pointers in initcall sections that the
- * kernel iterates at runtime. The linker can do dead code / data elimination
- * and remove that completely, so the initcall sections have to be marked
- * as KEEP() in the linker script.
+ * Defines a kernel initialization level. A respective linker script entry
+ * is required to ensure the init level is accounted for and to ensure symbols
+ * exist for iterating over all functions in the init level. A init level
+ * represents a series of functionality in the kernel.
+ *
+ * Ordering within an initialization level is determined by link order, so
+ * for instance if a Makefile had::
+ *
+ *	obj-y += foo.o
+ *	obj-y += bar.o
+ *
+ * And foo.c::
+ *
+ *	subsys_initcall(foo_init);
+ *
+ * And bar.c had::
+ *
+ *	subsys_initcall(bar_init);
+ *
+ * foo_init() would be called prior to bar_init().
+ *
+ * Note that @id in __define_initcall() also enables multiple initcalls
+ * to be created using the same handler for different init levels without
+ * causing duplicate-symbol build errors.
+ *
+ * Initcalls are run by placing start symbols to initcall levels inside ELF
+ * sections, the kernel in turn uses these symbols to iterate over each init
+ * level at runtime with do_initcall_level(). The end of each init level is
+ * marked by the subsequent's symbol's start address until we reach the symbol
+ * ``__initcall_end``. The linker can do dead code / data elimination and each
+ * init level start symbol could be removed completely in this process, to
+ * avoid this each init level start symbols must be marked as 'KEEP()' in the
+ * linker script to avoid any linker optimization heuristic on initcalls.
  */
-
 #define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
 	__attribute__((__section__(".initcall" #id ".init"))) = fn;
diff --git a/include/linux/sections.h b/include/linux/sections.h
new file mode 100644
index 000000000000..6771c727bcd1
--- /dev/null
+++ b/include/linux/sections.h
@@ -0,0 +1,87 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_CORE(section, core, name, level)			\
+	#section ".." #core "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 01/14] generic-sections: add section core helpers
@ 2016-12-22  2:37       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:37 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="windows-1254", Size: 47016 bytes --]

Linux makes extensive use of custom ELF header sections,
documentation for these are well scatterred. Unify this
documentation in a central place and provide helpers to
build custom Linux sections.

This also generalizes sections code to enable avoiding
modifying the linker scripts when we want to add new
custom Linux sections. In order to make this generally
useful we need to ensure all architectures can make use of
core section helpers but that they can also override should
this be needed. Instead of relying on section.h this adds
a sections-core.h since this will be targetted to be safe
to be used on asm code, linker scripts and C code.

v5:

o Huge documentation revamp based on a careful review of the ELF
  specifications. Includes documentation now also about usage of
  two dots (..) when prefixing ELF program specific sections.

o Replace macros for sections names in favor of just using
  the section names explicitly in the linker script. This is
  perhaps more work to grep but this is what folks seem to
  currently prefer.

o Fix .text and .rodata documentation to explain memory protection
  strategies which architectures can embrace upon initialization
  (documents CONFIG_DEBUG_RODATA and mark_rodata_ro())

o Skip the 'Linux section ordering' documentation section, we'll instead
  add this on subsequent patch which will expand on it considerably

o Dropped tree on MAINTAINERS -- as per discussions with Arnd, hpa and
  Josh, its easier to just let changes for sections go in through the
  respective tree that needs the changes.

o Fix typos on documentation

o Dropped SECTION_ALL(), __SECTION_CORE(), SECTION_CORE_ALL() macros
  since we are favoring using explicit section names. These are
  useless if we are being explicit.

o Drop LINUX_SECTION_SIZE(), LINUX_SECTION_EMPTY() in favor of having
  section ranges and linker tables define their own, to avoid confusion
  and make code more readable.

o Add __define_initcall() documentation and a small section describing
  our current initcall levels. This should help also clarify what was
  meant about keeping backward compatiblity.

v4:

o Port to shiny new sphinx documentation format

o fix a unicore32 build, turns out this actually fixes unicore32
  defconfig builds which were failing for a long while. unicore32
  does not seem to grok well the type passed on a section declaration,
  this ignores it.

o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
  this was causing final linker issues with blackfin -- this is
  a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
  being metatag. metatag is not supported on 0-day so I cannot confirm
  compilation there.

o Added SECTION_CORE() for C code, used later by __LINUX_RANGE()

o Since SECTION_CORE() is defined for linker script and C code, share
  the same helper and just use a __stringify() for the C code as is done
  for the other C helpers.

o move generic sections to asm-generic/section-core.h instead.
  PowerPC compilation blows up if asm/jump_labels.h gets
  section.h included, fixing this is not in any way easy.
  The list of issues are endless. Moving new data to a new
  simple file resolves this.

o since things are now in asm-generic/section-core.h the
  guard changes on asm-generic/sections.h and each architecture
  sections.h are no longer needed

o Give generic sections some maintainer love, that change is
  Acked-by Arnd Bergmann, Josh and hpa.

o A few checkpatch.pl style fixes

o As suggested by James Hogan use generic-y to copy generic
  header files on architectures that do not have a sections.h
  instead of writing a simple file only to include the generic one.

v3:

o add missing sections.h for architectures that did not
  have it

o move generic sections to asm-generic/sections.h

o add generic asm helpers section_type(), section_type_asmtype(),
  push_section_type() -- these helpers enable easy use for
  for later declaring and using of custom linux sections using
  more standard APIs in both C code, asm code (C asm calls, or
  asm files), enabling future standardized section types to
  be more immediately accessible to asm code, not just C code.
  Note for ASM_CMD_SEP we use by default "\n", architectures needed
  to override can do so on their own sections.h prior to inclusion
  of asm-generic/sections.h

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/index.rst                   |   1 +
 Documentation/sections/background.rst     | 105 ++++++++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  17 ++
 Documentation/sections/section-core.rst   | 148 ++++++++++++++
 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/Kbuild               |   1 +
 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/section-core.h |  19 ++
 arch/x86/include/asm/Kbuild               |   1 +
 arch/xtensa/include/asm/Kbuild            |   1 +
 include/asm-generic/section-core.h        | 307 ++++++++++++++++++++++++++++++
 include/asm-generic/sections.h            |   2 +
 include/asm-generic/vmlinux.lds.h         |   1 +
 include/linux/init.h                      |  89 +++++++--
 include/linux/sections.h                  |  87 +++++++++
 42 files changed, 809 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/linux/sections.h

diff --git a/Documentation/index.rst b/Documentation/index.rst
index cb5d77699c60..71e0305c036d 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -57,6 +57,7 @@ needed).
    media/index
    gpu/index
    security/index
+   sections/index
    sound/index
    crypto/index
 
diff --git a/Documentation/sections/background.rst b/Documentation/sections/background.rst
new file mode 100644
index 000000000000..0ecf9104aaa2
--- /dev/null
+++ b/Documentation/sections/background.rst
@@ -0,0 +1,105 @@
+===========
+ELF section background
+===========
+
+About
+==+
+The purpose of this chapter is to help those not familiar with ELF to brush up
+the latest ELF specifications in order to help understand how Linux uses and
+defines its own ELF sections.
+
+Standardized ELF
+========
+
+The first publication documenting ELF was UNIX System Laboratories' (USL)
+*System V Release 4 Application Binary Interface* (`SRV4 ABI`_) specification.
+Originally ELF was only a small part of the SRV4 ABI, with time however new
+specifications only put focus on ELF, such was the case of the *TIS Portable
+Formats Specification version 1.2* (`TIS 1.2`_). As of TIS 1.2, ELF was
+supplemented with processor specific ELF addendums, available on the *Linux
+Foundation referenced specification page* (`LF ref page`_). The latest ELF
+specification is the *System V Application Binary Interface - DRAFT - 24 April
+2001* (`gabi4`_).
+
+.. _SRV4 ABI: http://www.sco.com/developers/devspecs/gabi41.pdf
+.. _TIS 1.2: https://refspecs.linuxbase.org/elf/elf.pdf
+.. _LF ref page: https://refspecs.linuxbase.org/
+.. _gabi4: https://refspecs.linuxbase.org/elf/gabi4+/contents.html
+
+ELF views on Linux
+=========
+
+There are two views which can be used for inspecting data in an ELF file, a
+Linking view, and an Execution view. A Section Header Table enables one to
+describe an object using the Linking view while a Program Header Table enables
+one to describe an object using the Execution view. The views are not mutually
+exclusive. For intance, vmlinux can be viewed under both views, ``readelf -S
+vmlinux`` for the Linking view, and ``readelf -l vmlinux`` for the Execution
+view.  In Linux only the vmlinux file will have an Execution view, even modules
+lack an Execution view given that vmlinux is the only file that describes how
+the the kernel runs from the start.  All other Linux kernel object files have
+an available Linking view.
+
+Under the Linking view, the Section Header Table describes all available
+sections. The Section Header Table is an array of ELF section header data
+structures. If on a 32-bit system this is ``struct elf32_shd``, if on a 64-bit
+this is ``struct elf64_shdr``. Sections are only visible on object files that
+have a Linking view, since all Linux kernel files have Linking view, all kernel
+objects have ELF sections.
+
+Limitations on ELF sections
+=============+
+We provide a summary on the limitations of ELF sections. Refer to the public
+ELF specifications for details. Note that 64-bit limitations may depend
+on processor specific section attributes to be used, refer to your processsor
+specification if unsure.
+
+Its worth ellaborating on the limitations on the name of an ELF section:
+ELF section names are stored as strings as per the ELF specification, and
+as can be expected, these don't have explicit limitations. The implicit
+limitation then depends on the size of an ELF object file and ELF section.
+
+If using really large kernels or objects with large amounts of sections one
+would still need to be sure that ELF loader in charge of loading the Linux
+kernel is properly updated to handle coping with the latest ELF extensions.
+
+   .. flat-table:: Limitations on ELF Sections
+
+      * - Section attribute
+        - 32-bit
+        - 64-bit
+
+      * - ELF section name
+        - Size of an ELF section
+        - Size of an ELF section
+
+      * - Size of an ELF section
+        - 4 GiB
+        - 16 EiB
+
+      * - Max number of sections in an object file
+        - 4 GiEntries (4294967296)
+        - 16 EiEntries (18446744073709551616)
+
+Program specific ELF sections
+==============+
+The ELF specification allows for a section type to be specified as
+*Program specific section*, defined as ``SHT_PROGBITS``. This sections type
+enables programs to customize sections for their own use. In assembly this
+specified ``@progbits`` on most architectures, on ARM this is ``%progbits``.
+
+``SHT_PROGBITS`` is used by Linux for defining and using Linux ELF sections.
+
+Special ELF Sections
+==========
+
+The ELF specification defines *Special ELF Sections* on chapter 4 (`gabi4
+ch4`_). These are defined as sections which hold program and control
+information. Of these sections, a few have the section type as
+``SHT_PROGBITS``. This enables Linux to *further customize* use of the section
+beyond what the ELF specification suggests.
+
+.. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
new file mode 100644
index 000000000000..faa1c57595e1
--- /dev/null
+++ b/Documentation/sections/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel ELF sections'
+html_search_language = 'en'
diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
new file mode 100644
index 000000000000..f37511ef05e7
--- /dev/null
+++ b/Documentation/sections/index.rst
@@ -0,0 +1,17 @@
+============+Linux Kernel ELF sections
+============+
+This book documents the different ELF sections used on the Linux kernel.
+We start off by providing references to how ELF was standardized, references
+to the standards on ELF sections, review limitations of ELF sections, and
+finally how Linux uses ELF sections in the Linux kernel. Certain important
+Linux ELF sections are documented carefully: we describe the goal of the
+ELF section, and address concurrency considerations when applicable. A few
+common a set of Linux helpers for ELF sections are also documented.
+
+.. toctree::
+   :maxdepth: 4
+
+   background
+   section-core
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
new file mode 100644
index 000000000000..ac5815a0d9b3
--- /dev/null
+++ b/Documentation/sections/section-core.rst
@@ -0,0 +1,148 @@
+=================+Linux ELF program specific sections
+=================+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux ELF program specific sections
+
+Linux linker script
+=========+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux linker script
+
+Memory protection
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Memory protection
+
+mark_rodata_ro
+-----------------------
+.. kernel-doc:: include/linux/init.h
+   :functions: mark_rodata_ro
+
+.rodata
+-------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .rodata
+
+.text
+-----
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .text
+
+.data
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .data
+
+Linux .init\* sections
+===========
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux init sections
+
+.init.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.text
+
+.init.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.data
+
+.init.rodata
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.rodata
+
+Initcall levels
+---------------
+.. kernel-doc:: include/linux/init.h
+   :doc: Initcall levels
+
+.initcall
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .initcall
+
+__define_initcall
+-----------------
+.. kernel-doc:: include/linux/init.h
+   :functions: __define_initcall
+
+Linux .exit\* sections
+===========
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux exit sections
+
+.exit.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.text
+
+.exit.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.data
+
+.exitcall.exit
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exitcall.exit
+
+Linux .ref\* sections
+==========+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux references to init sections
+
+.ref.text
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.text
+
+.ref.data
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.data
+
+.ref.rodata
+-----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.rodata
+
+Generic Linux kernel section helpers
+==================
+
+Introduction
+-------------
+.. kernel-doc:: include/linux/sections.h
+   :doc: Introduction
+
+LINUX_SECTION_ALIGNMENT
+-----------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_ALIGNMENT
+
+LINUX_SECTION_START
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_START
+
+LINUX_SECTION_END
+-----------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_END
+
+DECLARE_LINUX_SECTION
+---------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION
+
+DECLARE_LINUX_SECTION_RO
+------------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION_RO
diff --git a/MAINTAINERS b/MAINTAINERS
index d0b2b50705bd..308826f5094b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5422,6 +5422,18 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTIONS
+M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
+M:	Josh Poimboeuf <jpoimboe@redhat.com>
+M:	"H. Peter Anvin" <hpa@zytor.com>
+L:	linux-arch@vger.kernel.org
+L:	linux-kernel@vger.kernel.org
+S:	Supported
+F:	include/asm-generic/section-core.h
+F:	include/asm-generic/sections.h
+F:	include/asm-generic/vmlinux.lds.h
+F:	Documentation/sections/section-core.rst
+
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index bf8475ce85ee..5422827f1585 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += section-core.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index c332604606dd..7b2cb3dea5fc 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index efb21757d41f..9b69a22a9ae1 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += unaligned.h
 
 generated-y += mach-types.h
 generated-y += unistd-nr.h
+generic-y += section-core.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 8365a84c2640..00ace5e826f1 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 241b9b9729d8..f2c3b656a0e7 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 2fb67b59d188..bf20541bcf21 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -47,3 +47,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 64465e7e2245..38127ce747be 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -62,3 +62,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 1778805f6380..385cd88a9d9e 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += types.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 1fa084cf1a43..46d7c599d9b8 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 373cb23301e3..1ec04ec1c82b 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -75,3 +75,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index db8ddabc6bd2..37d7bfae7619 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -60,3 +60,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 502a91d8dbbd..672c6d5da18c 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 860e440611c9..6111e1523750 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1f2e5d31cb24..1277b45bf4f9 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -34,3 +34,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 167150c701d1..b1011375cd7a 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -55,3 +55,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index b0ae88c9fed9..c6c2cf6edc98 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 45b0d6568270..a67d3177f3ca 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -20,3 +20,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 1c8dd0f5cd5d..f8145bc85835 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index d63330e88379..c9c7cb82b00f 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 2832f031fb11..86175e701869 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -71,3 +71,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 91f53c07f410..18a9d4c5ead7 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -28,3 +28,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 5c4fbc80dc6c..4322d9746cdb 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
+generic-y += section-core.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 8aea32fe8bd2..63a1c2924b91 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index a05218ff3fe4..f089a264cd38 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 751c3373a92c..7b0356dca562 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 0569bfac4afb..438f86573dc5 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 2d1f5638974c..fb6b831c1fba 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 052f7f6d0551..580bd5ff828f 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -26,3 +26,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
new file mode 100644
index 000000000000..0b9c68429a1a
--- /dev/null
+++ b/arch/unicore32/include/asm/section-core.h
@@ -0,0 +1,19 @@
+#ifndef __UNICORE_SECTION_CORE_ASM_H__
+#define __UNICORE_SECTION_CORE_ASM_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/.
+ */
+
+/* Unicore32 has known to not work properly with the type set, so ignore it */
+
+#define __set_section_core_type(___section, ___core, ___name,		\
+				___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags
+
+#include <asm-generic/section-core.h>
+
+#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 2b892e2313a9..af975f21eeee 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
+generic-y += section-core.h
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index b7fbaa56b51a..7879c31e66a7 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..bb16befc4251
--- /dev/null
+++ b/include/asm-generic/section-core.h
@@ -0,0 +1,307 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Linux ELF program specific sections
+ *
+ * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and
+ * definition of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
+ * sections. This chaper is dedicated to documenting Linux program specific
+ * sections and helpers available to make use of these easier to implement and
+ * use.
+ *
+ * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
+ */
+
+/**
+ * DOC: Linux linker script
+ *
+ * Linux uses a custom linker script to build the vmlinux binary, it uses it to
+ * strategically place and define Linux ELF sections.  Each architecture needs
+ * to implement its own linker script, it is expected to reside in
+ * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
+ * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
+ * as well as some helpers documented in this chapter.
+ *
+ * In assembly it is common practice to use dots (``.``) in labels to avoid
+ * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
+ * name but not a C symbol. Historically then, two dots are used (``..``)
+ * have been used in linker scripts when adding program specific sections
+ * when there are concerns to avoid clashes with compiler generated sections.
+ */
+
+/**
+ * DOC: Memory protection
+ *
+ * Linux allows architectures which support memory protection features to
+ * take advantage of them by letting architectures define and enable
+ * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.
+ * mark_rodata_ro() can be used for instance to mark specific sections as
+ * read-only or non-executable.
+ *
+ * Linux typically follows a convention to have the .rodata ELF section follow
+ * after the .text ELF section, it does this to help architectures which
+ * support memory protection to mark both .text and .rodata as read-only in
+ * one shot.
+ *
+ * For more details refer to mark_rodata_ro().
+ */
+
+/**
+ * DOC: .rodata
+ *
+ * ELF section used for data which must be protected from write access.
+ */
+
+/**
+ * DOC: .text
+ *
+ * ELF section name used for code (functions) used during regular
+ * kernel run time.
+ */
+
+/**
+ * DOC: .data
+ *
+ * ELF section used for read-write data.
+ */
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: .init.text
+ *
+ * ELF section for code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+
+/**
+ * DOC: .init.data
+ *
+ * ELF section used for data structures used only during boot or driver
+ * initialization.
+ */
+
+/**
+ * DOC: .init.rodata
+ *
+ * ELF section used for read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+
+/**
+ * DOC: .initcall
+ *
+ * ELF section used for subsystem init calls. There are init levels
+ * representing different functionality in the kernel. For more details
+ * refer to __define_initcall().
+ */
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: .exit.text
+ *
+ * ELF section used to for code (functions) used only during module unload.
+ */
+
+/**
+ * DOC: .exit.data
+ *
+ * ELF section used to for data structures used only during module
+ * unload.
+ */
+
+/**
+ * DOC: .exitcall.exit
+ *
+ * ELF section used for exit routines, order is important and maintained by
+ * link order.
+ */
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: .ref.text
+ *
+ * ELF section used to annotate code (functions) which has been vetteed as
+ * valid for its reference or use of other code (functions) or data structures
+ * which are part of the init sections.
+ */
+
+/**
+ * DOC: .ref.data
+ *
+ * ELF section used for data structures which have been vetteed for its
+ * reference or use of other code (functions) or data structures part of the
+ * init sections.
+ */
+
+/**
+ * DOC: .ref.rodata
+ *
+ * ELF section used to annotate const code (functions) const data structures
+ * which has been vetteed for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section..___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section..__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifndef LINKER_SCRIPT
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align\x16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 4df64a1fc09e..b145ae8d9cbe 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_GENERIC_SECTIONS_H_
 #define _ASM_GENERIC_SECTIONS_H_
 
+#include <asm/section-core.h>
+
 /* References to section boundaries */
 
 #include <linux/compiler.h>
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 0968d13b3885..483f60c451f9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -55,6 +55,7 @@
 #endif
 
 #include <linux/export.h>
+#include <asm/section-core.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
diff --git a/include/linux/init.h b/include/linux/init.h
index 885c3e6d0f9d..116e3262332a 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -130,6 +130,24 @@ int __init init_rootfs(void);
 extern bool rodata_enabled;
 #endif
 #ifdef CONFIG_DEBUG_RODATA
+/**
+ * mark_rodata_ro - implemement memory protection for ELF sections
+ *
+ * Architectures which support memory protection define a kernel configuration
+ * entry for CONFIG_DEBUG_RODATA, enable it in and implement mark_rodata_ro().
+ * mark_rodata_ro() should strive to adjust the .rodata and .text ELF sections
+ * with read-only memory protection to prevent modifications of these sections
+ * after bootup. It can also try to use memory protection to prevent execution
+ * on the .rodata ELF section.
+ *
+ * In order to help architectures set both .text and .rodata as read-only with
+ * memory protections in one shot Linux has typically followed the convention
+ * to have the .rodata ELF section follow the .text ELF section on the vmlinux
+ * linker script.
+ *
+ * Linux calls mark_rodata_ro() after freeing .init code and prior to calling
+ * the first init userspace process.
+ */
 void mark_rodata_ro(void);
 #endif
 
@@ -140,25 +158,70 @@ extern bool initcall_debug;
 #endif
   
 #ifndef MODULE
+/**
+ * DOC: Initcall levels
+ *
+ * When Linux boots the kernel do_initcalls() iterates over each Linux
+ * initialization level ID and calls all routines embedded on each level ID.
+ * Prior to v2.5.2.3 Linux had only one init level onto which all init
+ * functions folded onto using __initcall(). After v2.5.2.4 Linux split up
+ * initcalls into 7 separate initcall subsection levels, each level describing
+ * different functionality part of the kernel (commit `9d6ba121b7e17085`_
+ * (v2.5.2.3 -> v2.5.2.4)). In order to remain backward compatible __initcall()
+ * calls were left mapped to device_initcall().
+ *
+ * Each init level consists of a dedicated ELF section, init functions are
+ * associated to an init level by linking it into the respective level's
+ * ELF section.
+ *
+ * Lower order init levels run prior to higher order init levels. Ordering
+ * inside each initcall level is determined by respective link order.
+ *
+ * .. _9d6ba121b7e17085: https://git.kernel.org/cgit/linux/kernel/git/history/history.git/commit/?id6ba121b7e17085c95139233686b27a4d4c650e
+ */
 
 #ifndef __ASSEMBLY__
 
-/*
- * initcalls are now grouped by functionality into separate
- * subsections. Ordering inside the subsections is determined
- * by link order. 
- * For backwards compatibility, initcall() puts the call in 
- * the device init subsection.
+/**
+ * __define_initcall - wrapper for definiting init levels
  *
- * The `id' arg to __define_initcall() is needed so that multiple initcalls
- * can point at the same handler without causing duplicate-symbol build errors.
+ * @fn: init routine
+ * @id: init level
  *
- * Initcalls are run by placing pointers in initcall sections that the
- * kernel iterates at runtime. The linker can do dead code / data elimination
- * and remove that completely, so the initcall sections have to be marked
- * as KEEP() in the linker script.
+ * Defines a kernel initialization level. A respective linker script entry
+ * is required to ensure the init level is accounted for and to ensure symbols
+ * exist for iterating over all functions in the init level. A init level
+ * represents a series of functionality in the kernel.
+ *
+ * Ordering within an initialization level is determined by link order, so
+ * for instance if a Makefile had::
+ *
+ *	obj-y += foo.o
+ *	obj-y += bar.o
+ *
+ * And foo.c::
+ *
+ *	subsys_initcall(foo_init);
+ *
+ * And bar.c had::
+ *
+ *	subsys_initcall(bar_init);
+ *
+ * foo_init() would be called prior to bar_init().
+ *
+ * Note that @id in __define_initcall() also enables multiple initcalls
+ * to be created using the same handler for different init levels without
+ * causing duplicate-symbol build errors.
+ *
+ * Initcalls are run by placing start symbols to initcall levels inside ELF
+ * sections, the kernel in turn uses these symbols to iterate over each init
+ * level at runtime with do_initcall_level(). The end of each init level is
+ * marked by the subsequent's symbol's start address until we reach the symbol
+ * ``__initcall_end``. The linker can do dead code / data elimination and each
+ * init level start symbol could be removed completely in this process, to
+ * avoid this each init level start symbols must be marked as 'KEEP()' in the
+ * linker script to avoid any linker optimization heuristic on initcalls.
  */
-
 #define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
 	__attribute__((__section__(".initcall" #id ".init"))) = fn;
diff --git a/include/linux/sections.h b/include/linux/sections.h
new file mode 100644
index 000000000000..6771c727bcd1
--- /dev/null
+++ b/include/linux/sections.h
@@ -0,0 +1,87 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_CORE(section, core, name, level)			\
+	#section ".." #core "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
-- 
2.10.1

--
To unsubscribe from this list: send the line "unsubscribe sparclinux" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 01/14] generic-sections: add section core helpers
@ 2016-12-22  2:37       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:37 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Linux makes extensive use of custom ELF header sections,
documentation for these are well scatterred. Unify this
documentation in a central place and provide helpers to
build custom Linux sections.

This also generalizes sections code to enable avoiding
modifying the linker scripts when we want to add new
custom Linux sections. In order to make this generally
useful we need to ensure all architectures can make use of
core section helpers but that they can also override should
this be needed. Instead of relying on section.h this adds
a sections-core.h since this will be targetted to be safe
to be used on asm code, linker scripts and C code.

v5:

o Huge documentation revamp based on a careful review of the ELF
  specifications. Includes documentation now also about usage of
  two dots (..) when prefixing ELF program specific sections.

o Replace macros for sections names in favor of just using
  the section names explicitly in the linker script. This is
  perhaps more work to grep but this is what folks seem to
  currently prefer.

o Fix .text and .rodata documentation to explain memory protection
  strategies which architectures can embrace upon initialization
  (documents CONFIG_DEBUG_RODATA and mark_rodata_ro())

o Skip the 'Linux section ordering' documentation section, we'll instead
  add this on subsequent patch which will expand on it considerably

o Dropped tree on MAINTAINERS -- as per discussions with Arnd, hpa and
  Josh, its easier to just let changes for sections go in through the
  respective tree that needs the changes.

o Fix typos on documentation

o Dropped SECTION_ALL(), __SECTION_CORE(), SECTION_CORE_ALL() macros
  since we are favoring using explicit section names. These are
  useless if we are being explicit.

o Drop LINUX_SECTION_SIZE(), LINUX_SECTION_EMPTY() in favor of having
  section ranges and linker tables define their own, to avoid confusion
  and make code more readable.

o Add __define_initcall() documentation and a small section describing
  our current initcall levels. This should help also clarify what was
  meant about keeping backward compatiblity.

v4:

o Port to shiny new sphinx documentation format

o fix a unicore32 build, turns out this actually fixes unicore32
  defconfig builds which were failing for a long while. unicore32
  does not seem to grok well the type passed on a section declaration,
  this ignores it.

o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
  this was causing final linker issues with blackfin -- this is
  a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
  being metatag. metatag is not supported on 0-day so I cannot confirm
  compilation there.

o Added SECTION_CORE() for C code, used later by __LINUX_RANGE()

o Since SECTION_CORE() is defined for linker script and C code, share
  the same helper and just use a __stringify() for the C code as is done
  for the other C helpers.

o move generic sections to asm-generic/section-core.h instead.
  PowerPC compilation blows up if asm/jump_labels.h gets
  section.h included, fixing this is not in any way easy.
  The list of issues are endless. Moving new data to a new
  simple file resolves this.

o since things are now in asm-generic/section-core.h the
  guard changes on asm-generic/sections.h and each architecture
  sections.h are no longer needed

o Give generic sections some maintainer love, that change is
  Acked-by Arnd Bergmann, Josh and hpa.

o A few checkpatch.pl style fixes

o As suggested by James Hogan use generic-y to copy generic
  header files on architectures that do not have a sections.h
  instead of writing a simple file only to include the generic one.

v3:

o add missing sections.h for architectures that did not
  have it

o move generic sections to asm-generic/sections.h

o add generic asm helpers section_type(), section_type_asmtype(),
  push_section_type() -- these helpers enable easy use for
  for later declaring and using of custom linux sections using
  more standard APIs in both C code, asm code (C asm calls, or
  asm files), enabling future standardized section types to
  be more immediately accessible to asm code, not just C code.
  Note for ASM_CMD_SEP we use by default "\n", architectures needed
  to override can do so on their own sections.h prior to inclusion
  of asm-generic/sections.h

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/index.rst                   |   1 +
 Documentation/sections/background.rst     | 105 ++++++++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  17 ++
 Documentation/sections/section-core.rst   | 148 ++++++++++++++
 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/Kbuild               |   1 +
 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/section-core.h |  19 ++
 arch/x86/include/asm/Kbuild               |   1 +
 arch/xtensa/include/asm/Kbuild            |   1 +
 include/asm-generic/section-core.h        | 307 ++++++++++++++++++++++++++++++
 include/asm-generic/sections.h            |   2 +
 include/asm-generic/vmlinux.lds.h         |   1 +
 include/linux/init.h                      |  89 +++++++--
 include/linux/sections.h                  |  87 +++++++++
 42 files changed, 809 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/linux/sections.h

diff --git a/Documentation/index.rst b/Documentation/index.rst
index cb5d77699c60..71e0305c036d 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -57,6 +57,7 @@ needed).
    media/index
    gpu/index
    security/index
+   sections/index
    sound/index
    crypto/index
 
diff --git a/Documentation/sections/background.rst b/Documentation/sections/background.rst
new file mode 100644
index 000000000000..0ecf9104aaa2
--- /dev/null
+++ b/Documentation/sections/background.rst
@@ -0,0 +1,105 @@
+===========
+ELF section background
+===========
+
+About
+==+
+The purpose of this chapter is to help those not familiar with ELF to brush up
+the latest ELF specifications in order to help understand how Linux uses and
+defines its own ELF sections.
+
+Standardized ELF
+========
+
+The first publication documenting ELF was UNIX System Laboratories' (USL)
+*System V Release 4 Application Binary Interface* (`SRV4 ABI`_) specification.
+Originally ELF was only a small part of the SRV4 ABI, with time however new
+specifications only put focus on ELF, such was the case of the *TIS Portable
+Formats Specification version 1.2* (`TIS 1.2`_). As of TIS 1.2, ELF was
+supplemented with processor specific ELF addendums, available on the *Linux
+Foundation referenced specification page* (`LF ref page`_). The latest ELF
+specification is the *System V Application Binary Interface - DRAFT - 24 April
+2001* (`gabi4`_).
+
+.. _SRV4 ABI: http://www.sco.com/developers/devspecs/gabi41.pdf
+.. _TIS 1.2: https://refspecs.linuxbase.org/elf/elf.pdf
+.. _LF ref page: https://refspecs.linuxbase.org/
+.. _gabi4: https://refspecs.linuxbase.org/elf/gabi4+/contents.html
+
+ELF views on Linux
+=========
+
+There are two views which can be used for inspecting data in an ELF file, a
+Linking view, and an Execution view. A Section Header Table enables one to
+describe an object using the Linking view while a Program Header Table enables
+one to describe an object using the Execution view. The views are not mutually
+exclusive. For intance, vmlinux can be viewed under both views, ``readelf -S
+vmlinux`` for the Linking view, and ``readelf -l vmlinux`` for the Execution
+view.  In Linux only the vmlinux file will have an Execution view, even modules
+lack an Execution view given that vmlinux is the only file that describes how
+the the kernel runs from the start.  All other Linux kernel object files have
+an available Linking view.
+
+Under the Linking view, the Section Header Table describes all available
+sections. The Section Header Table is an array of ELF section header data
+structures. If on a 32-bit system this is ``struct elf32_shd``, if on a 64-bit
+this is ``struct elf64_shdr``. Sections are only visible on object files that
+have a Linking view, since all Linux kernel files have Linking view, all kernel
+objects have ELF sections.
+
+Limitations on ELF sections
+=============+
+We provide a summary on the limitations of ELF sections. Refer to the public
+ELF specifications for details. Note that 64-bit limitations may depend
+on processor specific section attributes to be used, refer to your processsor
+specification if unsure.
+
+Its worth ellaborating on the limitations on the name of an ELF section:
+ELF section names are stored as strings as per the ELF specification, and
+as can be expected, these don't have explicit limitations. The implicit
+limitation then depends on the size of an ELF object file and ELF section.
+
+If using really large kernels or objects with large amounts of sections one
+would still need to be sure that ELF loader in charge of loading the Linux
+kernel is properly updated to handle coping with the latest ELF extensions.
+
+   .. flat-table:: Limitations on ELF Sections
+
+      * - Section attribute
+        - 32-bit
+        - 64-bit
+
+      * - ELF section name
+        - Size of an ELF section
+        - Size of an ELF section
+
+      * - Size of an ELF section
+        - 4 GiB
+        - 16 EiB
+
+      * - Max number of sections in an object file
+        - 4 GiEntries (4294967296)
+        - 16 EiEntries (18446744073709551616)
+
+Program specific ELF sections
+==============+
+The ELF specification allows for a section type to be specified as
+*Program specific section*, defined as ``SHT_PROGBITS``. This sections type
+enables programs to customize sections for their own use. In assembly this
+specified ``@progbits`` on most architectures, on ARM this is ``%progbits``.
+
+``SHT_PROGBITS`` is used by Linux for defining and using Linux ELF sections.
+
+Special ELF Sections
+==========
+
+The ELF specification defines *Special ELF Sections* on chapter 4 (`gabi4
+ch4`_). These are defined as sections which hold program and control
+information. Of these sections, a few have the section type as
+``SHT_PROGBITS``. This enables Linux to *further customize* use of the section
+beyond what the ELF specification suggests.
+
+.. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
new file mode 100644
index 000000000000..faa1c57595e1
--- /dev/null
+++ b/Documentation/sections/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel ELF sections'
+html_search_language = 'en'
diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
new file mode 100644
index 000000000000..f37511ef05e7
--- /dev/null
+++ b/Documentation/sections/index.rst
@@ -0,0 +1,17 @@
+============+Linux Kernel ELF sections
+============+
+This book documents the different ELF sections used on the Linux kernel.
+We start off by providing references to how ELF was standardized, references
+to the standards on ELF sections, review limitations of ELF sections, and
+finally how Linux uses ELF sections in the Linux kernel. Certain important
+Linux ELF sections are documented carefully: we describe the goal of the
+ELF section, and address concurrency considerations when applicable. A few
+common a set of Linux helpers for ELF sections are also documented.
+
+.. toctree::
+   :maxdepth: 4
+
+   background
+   section-core
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
new file mode 100644
index 000000000000..ac5815a0d9b3
--- /dev/null
+++ b/Documentation/sections/section-core.rst
@@ -0,0 +1,148 @@
+=================+Linux ELF program specific sections
+=================+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux ELF program specific sections
+
+Linux linker script
+=========+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux linker script
+
+Memory protection
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Memory protection
+
+mark_rodata_ro
+-----------------------
+.. kernel-doc:: include/linux/init.h
+   :functions: mark_rodata_ro
+
+.rodata
+-------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .rodata
+
+.text
+-----
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .text
+
+.data
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .data
+
+Linux .init\* sections
+===========
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux init sections
+
+.init.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.text
+
+.init.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.data
+
+.init.rodata
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.rodata
+
+Initcall levels
+---------------
+.. kernel-doc:: include/linux/init.h
+   :doc: Initcall levels
+
+.initcall
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .initcall
+
+__define_initcall
+-----------------
+.. kernel-doc:: include/linux/init.h
+   :functions: __define_initcall
+
+Linux .exit\* sections
+===========
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux exit sections
+
+.exit.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.text
+
+.exit.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.data
+
+.exitcall.exit
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exitcall.exit
+
+Linux .ref\* sections
+==========+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux references to init sections
+
+.ref.text
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.text
+
+.ref.data
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.data
+
+.ref.rodata
+-----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.rodata
+
+Generic Linux kernel section helpers
+==================
+
+Introduction
+-------------
+.. kernel-doc:: include/linux/sections.h
+   :doc: Introduction
+
+LINUX_SECTION_ALIGNMENT
+-----------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_ALIGNMENT
+
+LINUX_SECTION_START
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_START
+
+LINUX_SECTION_END
+-----------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_END
+
+DECLARE_LINUX_SECTION
+---------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION
+
+DECLARE_LINUX_SECTION_RO
+------------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION_RO
diff --git a/MAINTAINERS b/MAINTAINERS
index d0b2b50705bd..308826f5094b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5422,6 +5422,18 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTIONS
+M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
+M:	Josh Poimboeuf <jpoimboe@redhat.com>
+M:	"H. Peter Anvin" <hpa@zytor.com>
+L:	linux-arch@vger.kernel.org
+L:	linux-kernel@vger.kernel.org
+S:	Supported
+F:	include/asm-generic/section-core.h
+F:	include/asm-generic/sections.h
+F:	include/asm-generic/vmlinux.lds.h
+F:	Documentation/sections/section-core.rst
+
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index bf8475ce85ee..5422827f1585 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += section-core.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index c332604606dd..7b2cb3dea5fc 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index efb21757d41f..9b69a22a9ae1 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += unaligned.h
 
 generated-y += mach-types.h
 generated-y += unistd-nr.h
+generic-y += section-core.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 8365a84c2640..00ace5e826f1 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 241b9b9729d8..f2c3b656a0e7 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 2fb67b59d188..bf20541bcf21 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -47,3 +47,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 64465e7e2245..38127ce747be 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -62,3 +62,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 1778805f6380..385cd88a9d9e 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += types.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 1fa084cf1a43..46d7c599d9b8 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 373cb23301e3..1ec04ec1c82b 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -75,3 +75,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index db8ddabc6bd2..37d7bfae7619 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -60,3 +60,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 502a91d8dbbd..672c6d5da18c 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 860e440611c9..6111e1523750 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1f2e5d31cb24..1277b45bf4f9 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -34,3 +34,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 167150c701d1..b1011375cd7a 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -55,3 +55,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index b0ae88c9fed9..c6c2cf6edc98 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 45b0d6568270..a67d3177f3ca 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -20,3 +20,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 1c8dd0f5cd5d..f8145bc85835 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index d63330e88379..c9c7cb82b00f 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 2832f031fb11..86175e701869 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -71,3 +71,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 91f53c07f410..18a9d4c5ead7 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -28,3 +28,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 5c4fbc80dc6c..4322d9746cdb 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
+generic-y += section-core.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 8aea32fe8bd2..63a1c2924b91 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index a05218ff3fe4..f089a264cd38 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 751c3373a92c..7b0356dca562 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 0569bfac4afb..438f86573dc5 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 2d1f5638974c..fb6b831c1fba 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 052f7f6d0551..580bd5ff828f 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -26,3 +26,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
new file mode 100644
index 000000000000..0b9c68429a1a
--- /dev/null
+++ b/arch/unicore32/include/asm/section-core.h
@@ -0,0 +1,19 @@
+#ifndef __UNICORE_SECTION_CORE_ASM_H__
+#define __UNICORE_SECTION_CORE_ASM_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/.
+ */
+
+/* Unicore32 has known to not work properly with the type set, so ignore it */
+
+#define __set_section_core_type(___section, ___core, ___name,		\
+				___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags
+
+#include <asm-generic/section-core.h>
+
+#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 2b892e2313a9..af975f21eeee 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
+generic-y += section-core.h
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index b7fbaa56b51a..7879c31e66a7 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..bb16befc4251
--- /dev/null
+++ b/include/asm-generic/section-core.h
@@ -0,0 +1,307 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Linux ELF program specific sections
+ *
+ * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and
+ * definition of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
+ * sections. This chaper is dedicated to documenting Linux program specific
+ * sections and helpers available to make use of these easier to implement and
+ * use.
+ *
+ * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
+ */
+
+/**
+ * DOC: Linux linker script
+ *
+ * Linux uses a custom linker script to build the vmlinux binary, it uses it to
+ * strategically place and define Linux ELF sections.  Each architecture needs
+ * to implement its own linker script, it is expected to reside in
+ * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
+ * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
+ * as well as some helpers documented in this chapter.
+ *
+ * In assembly it is common practice to use dots (``.``) in labels to avoid
+ * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
+ * name but not a C symbol. Historically then, two dots are used (``..``)
+ * have been used in linker scripts when adding program specific sections
+ * when there are concerns to avoid clashes with compiler generated sections.
+ */
+
+/**
+ * DOC: Memory protection
+ *
+ * Linux allows architectures which support memory protection features to
+ * take advantage of them by letting architectures define and enable
+ * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.
+ * mark_rodata_ro() can be used for instance to mark specific sections as
+ * read-only or non-executable.
+ *
+ * Linux typically follows a convention to have the .rodata ELF section follow
+ * after the .text ELF section, it does this to help architectures which
+ * support memory protection to mark both .text and .rodata as read-only in
+ * one shot.
+ *
+ * For more details refer to mark_rodata_ro().
+ */
+
+/**
+ * DOC: .rodata
+ *
+ * ELF section used for data which must be protected from write access.
+ */
+
+/**
+ * DOC: .text
+ *
+ * ELF section name used for code (functions) used during regular
+ * kernel run time.
+ */
+
+/**
+ * DOC: .data
+ *
+ * ELF section used for read-write data.
+ */
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: .init.text
+ *
+ * ELF section for code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+
+/**
+ * DOC: .init.data
+ *
+ * ELF section used for data structures used only during boot or driver
+ * initialization.
+ */
+
+/**
+ * DOC: .init.rodata
+ *
+ * ELF section used for read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+
+/**
+ * DOC: .initcall
+ *
+ * ELF section used for subsystem init calls. There are init levels
+ * representing different functionality in the kernel. For more details
+ * refer to __define_initcall().
+ */
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: .exit.text
+ *
+ * ELF section used to for code (functions) used only during module unload.
+ */
+
+/**
+ * DOC: .exit.data
+ *
+ * ELF section used to for data structures used only during module
+ * unload.
+ */
+
+/**
+ * DOC: .exitcall.exit
+ *
+ * ELF section used for exit routines, order is important and maintained by
+ * link order.
+ */
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: .ref.text
+ *
+ * ELF section used to annotate code (functions) which has been vetteed as
+ * valid for its reference or use of other code (functions) or data structures
+ * which are part of the init sections.
+ */
+
+/**
+ * DOC: .ref.data
+ *
+ * ELF section used for data structures which have been vetteed for its
+ * reference or use of other code (functions) or data structures part of the
+ * init sections.
+ */
+
+/**
+ * DOC: .ref.rodata
+ *
+ * ELF section used to annotate const code (functions) const data structures
+ * which has been vetteed for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section..___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section..__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifndef LINKER_SCRIPT
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align\x16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 4df64a1fc09e..b145ae8d9cbe 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_GENERIC_SECTIONS_H_
 #define _ASM_GENERIC_SECTIONS_H_
 
+#include <asm/section-core.h>
+
 /* References to section boundaries */
 
 #include <linux/compiler.h>
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 0968d13b3885..483f60c451f9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -55,6 +55,7 @@
 #endif
 
 #include <linux/export.h>
+#include <asm/section-core.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
diff --git a/include/linux/init.h b/include/linux/init.h
index 885c3e6d0f9d..116e3262332a 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -130,6 +130,24 @@ int __init init_rootfs(void);
 extern bool rodata_enabled;
 #endif
 #ifdef CONFIG_DEBUG_RODATA
+/**
+ * mark_rodata_ro - implemement memory protection for ELF sections
+ *
+ * Architectures which support memory protection define a kernel configuration
+ * entry for CONFIG_DEBUG_RODATA, enable it in and implement mark_rodata_ro().
+ * mark_rodata_ro() should strive to adjust the .rodata and .text ELF sections
+ * with read-only memory protection to prevent modifications of these sections
+ * after bootup. It can also try to use memory protection to prevent execution
+ * on the .rodata ELF section.
+ *
+ * In order to help architectures set both .text and .rodata as read-only with
+ * memory protections in one shot Linux has typically followed the convention
+ * to have the .rodata ELF section follow the .text ELF section on the vmlinux
+ * linker script.
+ *
+ * Linux calls mark_rodata_ro() after freeing .init code and prior to calling
+ * the first init userspace process.
+ */
 void mark_rodata_ro(void);
 #endif
 
@@ -140,25 +158,70 @@ extern bool initcall_debug;
 #endif
   
 #ifndef MODULE
+/**
+ * DOC: Initcall levels
+ *
+ * When Linux boots the kernel do_initcalls() iterates over each Linux
+ * initialization level ID and calls all routines embedded on each level ID.
+ * Prior to v2.5.2.3 Linux had only one init level onto which all init
+ * functions folded onto using __initcall(). After v2.5.2.4 Linux split up
+ * initcalls into 7 separate initcall subsection levels, each level describing
+ * different functionality part of the kernel (commit `9d6ba121b7e17085`_
+ * (v2.5.2.3 -> v2.5.2.4)). In order to remain backward compatible __initcall()
+ * calls were left mapped to device_initcall().
+ *
+ * Each init level consists of a dedicated ELF section, init functions are
+ * associated to an init level by linking it into the respective level's
+ * ELF section.
+ *
+ * Lower order init levels run prior to higher order init levels. Ordering
+ * inside each initcall level is determined by respective link order.
+ *
+ * .. _9d6ba121b7e17085: https://git.kernel.org/cgit/linux/kernel/git/history/history.git/commit/?idù6ba121b7e17085c95139233686b27a4d4c650e
+ */
 
 #ifndef __ASSEMBLY__
 
-/*
- * initcalls are now grouped by functionality into separate
- * subsections. Ordering inside the subsections is determined
- * by link order. 
- * For backwards compatibility, initcall() puts the call in 
- * the device init subsection.
+/**
+ * __define_initcall - wrapper for definiting init levels
  *
- * The `id' arg to __define_initcall() is needed so that multiple initcalls
- * can point at the same handler without causing duplicate-symbol build errors.
+ * @fn: init routine
+ * @id: init level
  *
- * Initcalls are run by placing pointers in initcall sections that the
- * kernel iterates at runtime. The linker can do dead code / data elimination
- * and remove that completely, so the initcall sections have to be marked
- * as KEEP() in the linker script.
+ * Defines a kernel initialization level. A respective linker script entry
+ * is required to ensure the init level is accounted for and to ensure symbols
+ * exist for iterating over all functions in the init level. A init level
+ * represents a series of functionality in the kernel.
+ *
+ * Ordering within an initialization level is determined by link order, so
+ * for instance if a Makefile had::
+ *
+ *	obj-y += foo.o
+ *	obj-y += bar.o
+ *
+ * And foo.c::
+ *
+ *	subsys_initcall(foo_init);
+ *
+ * And bar.c had::
+ *
+ *	subsys_initcall(bar_init);
+ *
+ * foo_init() would be called prior to bar_init().
+ *
+ * Note that @id in __define_initcall() also enables multiple initcalls
+ * to be created using the same handler for different init levels without
+ * causing duplicate-symbol build errors.
+ *
+ * Initcalls are run by placing start symbols to initcall levels inside ELF
+ * sections, the kernel in turn uses these symbols to iterate over each init
+ * level at runtime with do_initcall_level(). The end of each init level is
+ * marked by the subsequent's symbol's start address until we reach the symbol
+ * ``__initcall_end``. The linker can do dead code / data elimination and each
+ * init level start symbol could be removed completely in this process, to
+ * avoid this each init level start symbols must be marked as 'KEEP()' in the
+ * linker script to avoid any linker optimization heuristic on initcalls.
  */
-
 #define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
 	__attribute__((__section__(".initcall" #id ".init"))) = fn;
diff --git a/include/linux/sections.h b/include/linux/sections.h
new file mode 100644
index 000000000000..6771c727bcd1
--- /dev/null
+++ b/include/linux/sections.h
@@ -0,0 +1,87 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_CORE(section, core, name, level)			\
+	#section ".." #core "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
-- 
2.10.1

--
To unsubscribe from this list: send the line "unsubscribe linux-ia64" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 02/14] xtensa: skip adding literal when SORT() is used
  2016-12-22  2:37     ` Luis R. Rodriguez
  (?)
@ 2016-12-22  2:37       ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:37 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

When SORT(foo.*) is used the current sed replacements add
SORT(foo.literal foo.*), this breaks linking. Avoid adding
literals for SORT globs, if needed, these need to be added
manually.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/xtensa/kernel/Makefile | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index 264fb89c444e..ccedd016a8e0 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -30,10 +30,10 @@ AFLAGS_mxhead.o += -mtext-section-literals
 #
 # Replicate rules in scripts/Makefile.build
 
-sed-y = -e ':a; s/\*(\([^)]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
-	-e ':b; s/\*(\([^)]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
-	-e ':c; s/\*(\([^)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
-	-e ':d; s/\*(\([^)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
+sed-y = -e ':a; s/\*(\([^)SORT]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
+	-e ':b; s/\*(\([^)SORT]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
+	-e ':c; s/\*(\([^SORT)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
+	-e ':d; s/\*(\([^SORT)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
 	-e 's/\.{text}/.text/g'
 
 quiet_cmd__cpp_lds_S = LDS     $@
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 02/14] xtensa: skip adding literal when SORT() is used
@ 2016-12-22  2:37       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:37 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

When SORT(foo.*) is used the current sed replacements add
SORT(foo.literal foo.*), this breaks linking. Avoid adding
literals for SORT globs, if needed, these need to be added
manually.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/xtensa/kernel/Makefile | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index 264fb89c444e..ccedd016a8e0 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -30,10 +30,10 @@ AFLAGS_mxhead.o += -mtext-section-literals
 #
 # Replicate rules in scripts/Makefile.build
 
-sed-y = -e ':a; s/\*(\([^)]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
-	-e ':b; s/\*(\([^)]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
-	-e ':c; s/\*(\([^)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
-	-e ':d; s/\*(\([^)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
+sed-y = -e ':a; s/\*(\([^)SORT]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
+	-e ':b; s/\*(\([^)SORT]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
+	-e ':c; s/\*(\([^SORT)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
+	-e ':d; s/\*(\([^SORT)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
 	-e 's/\.{text}/.text/g'
 
 quiet_cmd__cpp_lds_S = LDS     $@
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 02/14] xtensa: skip adding literal when SORT() is used
@ 2016-12-22  2:37       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:37 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

When SORT(foo.*) is used the current sed replacements add
SORT(foo.literal foo.*), this breaks linking. Avoid adding
literals for SORT globs, if needed, these need to be added
manually.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/xtensa/kernel/Makefile | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index 264fb89c444e..ccedd016a8e0 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -30,10 +30,10 @@ AFLAGS_mxhead.o += -mtext-section-literals
 #
 # Replicate rules in scripts/Makefile.build
 
-sed-y = -e ':a; s/\*(\([^)]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
-	-e ':b; s/\*(\([^)]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
-	-e ':c; s/\*(\([^)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
-	-e ':d; s/\*(\([^)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
+sed-y = -e ':a; s/\*(\([^)SORT]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
+	-e ':b; s/\*(\([^)SORT]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
+	-e ':c; s/\*(\([^SORT)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
+	-e ':d; s/\*(\([^SORT)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
 	-e 's/\.{text}/.text/g'
 
 quiet_cmd__cpp_lds_S = LDS     $@
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 03/14] ranges.h: add helpers to build and identify Linux section ranges
  2016-12-22  2:37     ` Luis R. Rodriguez
  (?)
@ 2016-12-22  2:37       ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:37 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Section ranges are on one of the types of custom sections
types used in Linux. This provides a series of helpers for
defining them and using them. Most importantly this also
enables us to avoid modifying the linker script when we
add a new section range.

It turns out a lot of custom sections are actually section ranges,
and these are typically spelled out in their architecture specific
asm/sections.h file -- we enable architectures to override what asm
is used for section ranges but start by default trusting the
asm-generic version all around.

Although typically you will not want to have section ranges ordered
we must use SORT() on vmlinux.lds.S for section ranges to enable us
to extend a section range without modifying the linker script. To
accomplish this we use a special order string for the first element
of a section range -- the empty string "" (refer to __SECTION_RANGE_BEGIN()),
then "~" for the last element (refer to __SECTION_RANGE_BEGIN()). If
you use the "any" order for elements in between and use SORT() you end
up keeping any added element in betweeen and a reference to the
beginning and end of the section range without requiring custom linker
script modifications. Specific order annotations are also supported
to help construct synthetic functions, a demo for which will be provided
later.

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

o Extend commit log to justify SORT() and explain why and how we use
  specific special strings for the beginning, end elements of a section
  range and the "any" order for elements in between.

o Drop SECTION_RNG_ALL() -- we no longer need this on linker scripts

o To make this easier to read, as per Nicholas Piggin, add our own
  SECTION_RANGE_START(), SECTION_RANGE_END(). After reviewing the
  changes affected by this it seemed clearer and better then to also
  use our own specific SECTION_RANGE_SIZE(), and SECTION_RANGE_EMPTY(),
  and SECTION_RANGE_ALIGNMENT() as well.

o We were using LINUX_SECTION_START() and LINUX_SECTION_END() in some places
  but in some other places VMLINUX_SYMBOL(name), VMLINUX_SYMBOL(name##__end).
  Since we are adding SECTION_RANGE_START() and SECTION_RANGE_END() just
  use those consistently.

o Move the linker table *(SORT(.data.rng.*)) to be present before
  the recently added *(.data.[0-9a-zA-Z_]*) to ensure we keep sort order
  on the section range.

o Adds the "Linux section ordering" documentation, as its much more
  relevant after this patch, in particular when treating the "any"
  order level.

o Fix powerpc .text use: -- it does not use TEXT_TEXT so we must
  add our *(SORT(.text.rng.*)) to its linker script manually.

v4:

o tons of documentation love
o fix arch/x86/tools/relocs.c typo - which caused compilation issues
  on old toolchains
o port to new shiny sphinx documentation
o sprinkle a few more needed VMLINUX_SYMBOL() - fixes
  compilation on blackfin
o name changes as suggested 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
- rebrand DECLARE_SECTION_RNG() as DEFINE_SECTION_RANGE() - this is
  the asm version of the respective C version, this will have a
  userspace C demo added later.
o move __LINUX_RANGE() and __LINUX_RANGE_ORDER() - fixes builds
  on sparc
o adds section ranges to linker script
o rename SECTION_RANGE_ALL()
o use default alignment, fixes builds on powerpc and arm for both
  __LINUX_RANGE() and __LINUX_RANGE_ORDER()
o expand documentation to document modules support
o add maintainers
o use generic-y

v3: new in this series, uses copyleft-next

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst        |   1 +
 Documentation/sections/ranges.rst       |  74 +++++++++++++
 Documentation/sections/section-core.rst |   5 +
 MAINTAINERS                             |  10 ++
 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/Kbuild             |   1 +
 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/powerpc/kernel/vmlinux.lds.S       |   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            |  93 ++++++++++++++++
 include/asm-generic/section-core.h      |  41 +++++++
 include/asm-generic/vmlinux.lds.h       |  12 ++-
 include/linux/ranges.h                  | 183 ++++++++++++++++++++++++++++++++
 41 files changed, 451 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/linux/ranges.h

diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
index f37511ef05e7..4a1df389fa91 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -15,3 +15,4 @@ common a set of Linux helpers for ELF sections are also documented.
 
    background
    section-core
+   ranges
diff --git a/Documentation/sections/ranges.rst b/Documentation/sections/ranges.rst
new file mode 100644
index 000000000000..d9d3af4e52cb
--- /dev/null
+++ b/Documentation/sections/ranges.rst
@@ -0,0 +1,74 @@
+==========
+Linux section ranges
+==========
+
+This documents Linux' use of section ranges, how you can use
+them and how they work.
+
+About section ranges
+==========
+
+Introduction
+------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Introduction
+
+Section range module support
+----------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range module support
+
+Section range helpers
+==========+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range helpers
+
+SECTION_RANGE_START
+-------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_START
+
+SECTION_RANGE_END
+-----------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_END
+
+SECTION_RANGE_SIZE
+------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_SIZE
+
+SECTION_RANGE_EMPTY
+-------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_EMPTY
+
+SECTION_RANGE_ADDR_WITHIN
+-------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_ADDR_WITHIN
+
+SECTION_RANGE_ALIGNMENT
+-------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_ALIGNMENT
+
+DECLARE_SECTION_RANGE
+---------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DECLARE_SECTION_RANGE
+
+DEFINE_SECTION_RANGE
+--------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DEFINE_SECTION_RANGE
+
+__LINUX_RANGE
+-------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE
+
+__LINUX_RANGE_ORDER
+-------------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE_ORDER
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
index ac5815a0d9b3..1f613a6c7b78 100644
--- a/Documentation/sections/section-core.rst
+++ b/Documentation/sections/section-core.rst
@@ -114,6 +114,11 @@ Linux .ref\* sections
 .. kernel-doc:: include/asm-generic/section-core.h
    :doc: .ref.rodata
 
+Linux section ordering
+===========
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux section ordering
+
 Generic Linux kernel section helpers
 ==================
 
diff --git a/MAINTAINERS b/MAINTAINERS
index 308826f5094b..93bebccad674 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5422,6 +5422,16 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTION RANGES
+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
+S:	Supported
+F:	include/asm-generic/ranges.h
+F:	include/linux/ranges.h
+F:	Documentation/sections/ranges.rst
+
 GENERIC SECTIONS
 M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
 M:	Josh Poimboeuf <jpoimboe@redhat.com>
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index 5422827f1585..e44c896b91c4 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 7b2cb3dea5fc..a374b7f83888 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -52,3 +52,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 9b69a22a9ae1..0d47f98ccbc0 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -42,3 +42,4 @@ generic-y += unaligned.h
 generated-y += mach-types.h
 generated-y += unistd-nr.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 00ace5e826f1..e9939cbd9067 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index f2c3b656a0e7..edc176348d7c 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -23,3 +23,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index bf20541bcf21..3428415b1996 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 38127ce747be..cede2a950fbf 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 385cd88a9d9e..fb8bb4112773 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 46d7c599d9b8..5191fec655d7 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 1ec04ec1c82b..7929a992566c 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -76,3 +76,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index 37d7bfae7619..af17ee334788 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 672c6d5da18c..d8f226b35a0a 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 6111e1523750..1c6504d29312 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1277b45bf4f9..006e2863ad37 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index b1011375cd7a..4a8471434a3e 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -56,3 +56,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index c6c2cf6edc98..63c083a1f8da 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index a67d3177f3ca..288e21b64170 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index f8145bc85835..656af7b69940 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index c9c7cb82b00f..c55880659d67 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 86175e701869..7d6a704b808c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -72,3 +72,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 18a9d4c5ead7..f11d1249738f 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 4322d9746cdb..60d8349241a7 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 7394b770ae1f..fcfc9d102348 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -107,6 +107,7 @@ SECTIONS
 #endif
 		/* careful! __ftr_alt_* sections need to be close to .text */
 		*(.text .fixup __ftr_alt_* .ref.text)
+		*(SORT(.text.rng.*))
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 63a1c2924b91..c1b85a361e5d 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index f089a264cd38..f0cdb2cbca4d 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -15,3 +15,4 @@ generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 7b0356dca562..c9bb7932a3d1 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 438f86573dc5..28280887ac79 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index fb6b831c1fba..33f7069763ae 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 580bd5ff828f..b952dcb3e216 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -27,3 +27,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 8578702d4998..93abbfdab543 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += ranges.h
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index af975f21eeee..f672f2fc181d 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index 73eb7fd4aec4..f96fa2ddf7c9 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -68,6 +68,8 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
 	"__end_rodata|"
 	"__initramfs_start|"
 	"(jiffies|jiffies_64)|"
+	".rodata..rng.*|"
+	".init.text..rng.*|"
 #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 7879c31e66a7..2b7fe48c0225 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -33,3 +33,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/include/asm-generic/ranges.h b/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..75c196864f45
--- /dev/null
+++ b/include/asm-generic/ranges.h
@@ -0,0 +1,93 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  any, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       any, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   any, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(#section "..rng.name.any")))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using
+ * 	binutils SORT(), the number is sorted as a string, as such be
+ * 	sure to fill with zeroes any empty digits. For instance if you are
+ * 	using 3 levels of digits for order levels, use 001 for the first entry,
+ * 	0002 for the second, 999 for the last entry. You can use however many
+ * 	digits you need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(#section "..rng.name." #level)))
+
+#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/section-core.h b/include/asm-generic/section-core.h
index bb16befc4251..65fb076765f8 100644
--- a/include/asm-generic/section-core.h
+++ b/include/asm-generic/section-core.h
@@ -183,6 +183,47 @@
  * or data structures part of the init sections.
  */
 
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections alpha numerically. Linux has historically used 'SORT()' in
+ * ``include/asm-generic/vmlinux.lds.h``, its a well established practice. If
+ * 'SORT()' is used on a section one can provide ordering using a postfix on
+ * each section entry added. For instance if a linker script uses::
+ *
+ *    SORT(.foo.*)
+ *
+ * one can then add entries with explicit ordering using numeric postfixes for
+ * each entry, we refer to these as 'order levels'. Since 'SORT()' sorts alpha
+ * numerically a specific series set of digits must be agreed a-priori which
+ * would give also an idea of the max expected number of entries added to a
+ * section. For instance, if you expect a maximum of 999 entries you can use
+ * 3 digits for a section order level. If you wanted an entry to be ordered
+ * first you could use the postfix '000', if you wanted an entry to follow this
+ * you could use '001', and so on. We could for instance have::
+ *
+ *    .foo.000
+ *    .foo.001
+ *    .foo.002
+ *
+ * Often times one may want the option to specify no order is required for
+ * certain elements added to a section which does use 'SORT()' on the linker
+ * script. You can use any arbitrary string value to to specify no order is
+ * used, so long as its used consistantly. For instance, one possibility is to
+ * use the 'any' postfix.  All entries on the section would then have no
+ * specific ordering::
+ *
+ *    .foo.any
+ *    .foo.any
+ *    .foo.any
+ *
+ * To help establish a convention we reserve the special name 'any' for this
+ * purpose. Developers can use and expect the 'any' postfix string on sections
+ * as a helper to annotate section ordering at link time is not relevant
+ * for entries on a section.
+ */
+
 /* Can be used on foo.S for instance */
 #ifndef __set_section_core_type
 # define __set_section_core_type(___section, ___core, ___name,		\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 483f60c451f9..71bfd3b3c719 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -56,6 +56,7 @@
 
 #include <linux/export.h>
 #include <asm/section-core.h>
+#include <asm/ranges.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
@@ -205,6 +206,7 @@
  */
 #define DATA_DATA							\
 	*(.data .data.[0-9a-zA-Z_]*)					\
+	*(SORT(.data..rng.*))						\
 	*(.ref.data)							\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -273,7 +275,9 @@
 	. = ALIGN((align));						\
 	.rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {		\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
-		*(.rodata) *(.rodata.*)					\
+		*(.rodata)						\
+		*(SORT(.rodata..rng.*))					\
+		*(.rodata.*)						\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		KEEP(*(__vermagic))	/* Kernel version magic */	\
 		. = ALIGN(8);						\
@@ -446,7 +450,9 @@
  * conflicting section names, and must pull in .text.[0-9a-zA-Z_]* */
 #define TEXT_TEXT							\
 		ALIGN_FUNCTION();					\
-		*(.text.hot .text .text.fixup .text.unlikely)		\
+		*(.text.hot .text)					\
+		*(SORT(.text..rng.*))					\
+		*(.text.fixup .text.unlikely)				\
 		*(.ref.text)						\
 	MEM_KEEP(init.text)						\
 	MEM_KEEP(exit.text)						\
@@ -549,6 +555,7 @@
 #define INIT_DATA							\
 	KEEP(*(SORT(___kentry+*)))					\
 	*(.init.data)							\
+	*(SORT(.init.data..rng.*))					\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -572,6 +579,7 @@
 
 #define INIT_TEXT							\
 	*(.init.text)							\
+	*(SORT(.init.text..rng.*))					\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/ranges.h b/include/linux/ranges.h
new file mode 100644
index 000000000000..1e64674f6d7d
--- /dev/null
+++ b/include/linux/ranges.h
@@ -0,0 +1,183 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * SECTION_RANGE_START - get address of start of section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the start address of the section range.
+ * This should give you the address of the first entry.
+ *
+ */
+#define SECTION_RANGE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * SECTION_RANGE_END - get address of end of the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define SECTION_RANGE_END(name)		LINUX_SECTION_END(name)
+
+/**
+ * SECTION_RANGE_SIZE - get number of entries in the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the number of entries in the section range.
+ * Example usage:
+ *
+ *   unsigned int num_ents = LINKTABLE_SIZE(some_fns);
+ */
+#define SECTION_RANGE_SIZE(name)					\
+	((SECTION_RANGE_END(name)) - (SECTION_RANGE_START(name)))
+
+/**
+ * SECTION_RANGE_EMPTY - check if section range has no entries
+ *
+ * @name: name of the section range
+ *
+ * Returns true if the section range is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(some_fns);
+ */
+#define SECTION_RANGE_EMPTY(name)	(SECTION_RANGE_SIZE(name) = 0)
+
+/**
+ * SECTION_RANGE_ADDR_WITHIN - returns true if address is in the section range
+ *
+ * @name: name of the section range
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_RANGE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) SECTION_RANGE_START(name) &&		\
+          addr < (unsigned long) SECTION_RANGE_END(name))
+
+/**
+ * SECTION_RANGE_ALIGNMENT - get the alignment of the section range
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the section range.
+ */
+#define SECTION_RANGE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.")))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.~")))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) SECTION_RANGE_START(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) SECTION_RANGE_END(name)[0] = {}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 03/14] ranges.h: add helpers to build and identify Linux section ranges
@ 2016-12-22  2:37       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:37 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Section ranges are on one of the types of custom sections
types used in Linux. This provides a series of helpers for
defining them and using them. Most importantly this also
enables us to avoid modifying the linker script when we
add a new section range.

It turns out a lot of custom sections are actually section ranges,
and these are typically spelled out in their architecture specific
asm/sections.h file -- we enable architectures to override what asm
is used for section ranges but start by default trusting the
asm-generic version all around.

Although typically you will not want to have section ranges ordered
we must use SORT() on vmlinux.lds.S for section ranges to enable us
to extend a section range without modifying the linker script. To
accomplish this we use a special order string for the first element
of a section range -- the empty string "" (refer to __SECTION_RANGE_BEGIN()),
then "~" for the last element (refer to __SECTION_RANGE_BEGIN()). If
you use the "any" order for elements in between and use SORT() you end
up keeping any added element in betweeen and a reference to the
beginning and end of the section range without requiring custom linker
script modifications. Specific order annotations are also supported
to help construct synthetic functions, a demo for which will be provided
later.

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

o Extend commit log to justify SORT() and explain why and how we use
  specific special strings for the beginning, end elements of a section
  range and the "any" order for elements in between.

o Drop SECTION_RNG_ALL() -- we no longer need this on linker scripts

o To make this easier to read, as per Nicholas Piggin, add our own
  SECTION_RANGE_START(), SECTION_RANGE_END(). After reviewing the
  changes affected by this it seemed clearer and better then to also
  use our own specific SECTION_RANGE_SIZE(), and SECTION_RANGE_EMPTY(),
  and SECTION_RANGE_ALIGNMENT() as well.

o We were using LINUX_SECTION_START() and LINUX_SECTION_END() in some places
  but in some other places VMLINUX_SYMBOL(name), VMLINUX_SYMBOL(name##__end).
  Since we are adding SECTION_RANGE_START() and SECTION_RANGE_END() just
  use those consistently.

o Move the linker table *(SORT(.data.rng.*)) to be present before
  the recently added *(.data.[0-9a-zA-Z_]*) to ensure we keep sort order
  on the section range.

o Adds the "Linux section ordering" documentation, as its much more
  relevant after this patch, in particular when treating the "any"
  order level.

o Fix powerpc .text use: -- it does not use TEXT_TEXT so we must
  add our *(SORT(.text.rng.*)) to its linker script manually.

v4:

o tons of documentation love
o fix arch/x86/tools/relocs.c typo - which caused compilation issues
  on old toolchains
o port to new shiny sphinx documentation
o sprinkle a few more needed VMLINUX_SYMBOL() - fixes
  compilation on blackfin
o name changes as suggested 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
- rebrand DECLARE_SECTION_RNG() as DEFINE_SECTION_RANGE() - this is
  the asm version of the respective C version, this will have a
  userspace C demo added later.
o move __LINUX_RANGE() and __LINUX_RANGE_ORDER() - fixes builds
  on sparc
o adds section ranges to linker script
o rename SECTION_RANGE_ALL()
o use default alignment, fixes builds on powerpc and arm for both
  __LINUX_RANGE() and __LINUX_RANGE_ORDER()
o expand documentation to document modules support
o add maintainers
o use generic-y

v3: new in this series, uses copyleft-next

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst        |   1 +
 Documentation/sections/ranges.rst       |  74 +++++++++++++
 Documentation/sections/section-core.rst |   5 +
 MAINTAINERS                             |  10 ++
 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/Kbuild             |   1 +
 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/powerpc/kernel/vmlinux.lds.S       |   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            |  93 ++++++++++++++++
 include/asm-generic/section-core.h      |  41 +++++++
 include/asm-generic/vmlinux.lds.h       |  12 ++-
 include/linux/ranges.h                  | 183 ++++++++++++++++++++++++++++++++
 41 files changed, 451 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/linux/ranges.h

diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
index f37511ef05e7..4a1df389fa91 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -15,3 +15,4 @@ common a set of Linux helpers for ELF sections are also documented.
 
    background
    section-core
+   ranges
diff --git a/Documentation/sections/ranges.rst b/Documentation/sections/ranges.rst
new file mode 100644
index 000000000000..d9d3af4e52cb
--- /dev/null
+++ b/Documentation/sections/ranges.rst
@@ -0,0 +1,74 @@
+====================
+Linux section ranges
+====================
+
+This documents Linux' use of section ranges, how you can use
+them and how they work.
+
+About section ranges
+====================
+
+Introduction
+------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Introduction
+
+Section range module support
+----------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range module support
+
+Section range helpers
+=====================
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range helpers
+
+SECTION_RANGE_START
+-------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_START
+
+SECTION_RANGE_END
+-----------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_END
+
+SECTION_RANGE_SIZE
+------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_SIZE
+
+SECTION_RANGE_EMPTY
+-------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_EMPTY
+
+SECTION_RANGE_ADDR_WITHIN
+-------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_ADDR_WITHIN
+
+SECTION_RANGE_ALIGNMENT
+-------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_ALIGNMENT
+
+DECLARE_SECTION_RANGE
+---------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DECLARE_SECTION_RANGE
+
+DEFINE_SECTION_RANGE
+--------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DEFINE_SECTION_RANGE
+
+__LINUX_RANGE
+-------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE
+
+__LINUX_RANGE_ORDER
+-------------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE_ORDER
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
index ac5815a0d9b3..1f613a6c7b78 100644
--- a/Documentation/sections/section-core.rst
+++ b/Documentation/sections/section-core.rst
@@ -114,6 +114,11 @@ Linux .ref\* sections
 .. kernel-doc:: include/asm-generic/section-core.h
    :doc: .ref.rodata
 
+Linux section ordering
+======================
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux section ordering
+
 Generic Linux kernel section helpers
 ====================================
 
diff --git a/MAINTAINERS b/MAINTAINERS
index 308826f5094b..93bebccad674 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5422,6 +5422,16 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTION RANGES
+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
+S:	Supported
+F:	include/asm-generic/ranges.h
+F:	include/linux/ranges.h
+F:	Documentation/sections/ranges.rst
+
 GENERIC SECTIONS
 M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
 M:	Josh Poimboeuf <jpoimboe@redhat.com>
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index 5422827f1585..e44c896b91c4 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 7b2cb3dea5fc..a374b7f83888 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -52,3 +52,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 9b69a22a9ae1..0d47f98ccbc0 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -42,3 +42,4 @@ generic-y += unaligned.h
 generated-y += mach-types.h
 generated-y += unistd-nr.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 00ace5e826f1..e9939cbd9067 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index f2c3b656a0e7..edc176348d7c 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -23,3 +23,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index bf20541bcf21..3428415b1996 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 38127ce747be..cede2a950fbf 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 385cd88a9d9e..fb8bb4112773 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 46d7c599d9b8..5191fec655d7 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 1ec04ec1c82b..7929a992566c 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -76,3 +76,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index 37d7bfae7619..af17ee334788 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 672c6d5da18c..d8f226b35a0a 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 6111e1523750..1c6504d29312 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1277b45bf4f9..006e2863ad37 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index b1011375cd7a..4a8471434a3e 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -56,3 +56,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index c6c2cf6edc98..63c083a1f8da 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index a67d3177f3ca..288e21b64170 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index f8145bc85835..656af7b69940 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index c9c7cb82b00f..c55880659d67 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 86175e701869..7d6a704b808c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -72,3 +72,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 18a9d4c5ead7..f11d1249738f 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 4322d9746cdb..60d8349241a7 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 7394b770ae1f..fcfc9d102348 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -107,6 +107,7 @@ SECTIONS
 #endif
 		/* careful! __ftr_alt_* sections need to be close to .text */
 		*(.text .fixup __ftr_alt_* .ref.text)
+		*(SORT(.text.rng.*))
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 63a1c2924b91..c1b85a361e5d 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index f089a264cd38..f0cdb2cbca4d 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -15,3 +15,4 @@ generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 7b0356dca562..c9bb7932a3d1 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 438f86573dc5..28280887ac79 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index fb6b831c1fba..33f7069763ae 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 580bd5ff828f..b952dcb3e216 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -27,3 +27,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 8578702d4998..93abbfdab543 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += ranges.h
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index af975f21eeee..f672f2fc181d 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index 73eb7fd4aec4..f96fa2ddf7c9 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -68,6 +68,8 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
 	"__end_rodata|"
 	"__initramfs_start|"
 	"(jiffies|jiffies_64)|"
+	".rodata..rng.*|"
+	".init.text..rng.*|"
 #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 7879c31e66a7..2b7fe48c0225 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -33,3 +33,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/include/asm-generic/ranges.h b/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..75c196864f45
--- /dev/null
+++ b/include/asm-generic/ranges.h
@@ -0,0 +1,93 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  any, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       any, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   any, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(#section "..rng.name.any")))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using
+ * 	binutils SORT(), the number is sorted as a string, as such be
+ * 	sure to fill with zeroes any empty digits. For instance if you are
+ * 	using 3 levels of digits for order levels, use 001 for the first entry,
+ * 	0002 for the second, 999 for the last entry. You can use however many
+ * 	digits you need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(#section "..rng.name." #level)))
+
+#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/section-core.h b/include/asm-generic/section-core.h
index bb16befc4251..65fb076765f8 100644
--- a/include/asm-generic/section-core.h
+++ b/include/asm-generic/section-core.h
@@ -183,6 +183,47 @@
  * or data structures part of the init sections.
  */
 
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections alpha numerically. Linux has historically used 'SORT()' in
+ * ``include/asm-generic/vmlinux.lds.h``, its a well established practice. If
+ * 'SORT()' is used on a section one can provide ordering using a postfix on
+ * each section entry added. For instance if a linker script uses::
+ *
+ *    SORT(.foo.*)
+ *
+ * one can then add entries with explicit ordering using numeric postfixes for
+ * each entry, we refer to these as 'order levels'. Since 'SORT()' sorts alpha
+ * numerically a specific series set of digits must be agreed a-priori which
+ * would give also an idea of the max expected number of entries added to a
+ * section. For instance, if you expect a maximum of 999 entries you can use
+ * 3 digits for a section order level. If you wanted an entry to be ordered
+ * first you could use the postfix '000', if you wanted an entry to follow this
+ * you could use '001', and so on. We could for instance have::
+ *
+ *    .foo.000
+ *    .foo.001
+ *    .foo.002
+ *
+ * Often times one may want the option to specify no order is required for
+ * certain elements added to a section which does use 'SORT()' on the linker
+ * script. You can use any arbitrary string value to to specify no order is
+ * used, so long as its used consistantly. For instance, one possibility is to
+ * use the 'any' postfix.  All entries on the section would then have no
+ * specific ordering::
+ *
+ *    .foo.any
+ *    .foo.any
+ *    .foo.any
+ *
+ * To help establish a convention we reserve the special name 'any' for this
+ * purpose. Developers can use and expect the 'any' postfix string on sections
+ * as a helper to annotate section ordering at link time is not relevant
+ * for entries on a section.
+ */
+
 /* Can be used on foo.S for instance */
 #ifndef __set_section_core_type
 # define __set_section_core_type(___section, ___core, ___name,		\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 483f60c451f9..71bfd3b3c719 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -56,6 +56,7 @@
 
 #include <linux/export.h>
 #include <asm/section-core.h>
+#include <asm/ranges.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
@@ -205,6 +206,7 @@
  */
 #define DATA_DATA							\
 	*(.data .data.[0-9a-zA-Z_]*)					\
+	*(SORT(.data..rng.*))						\
 	*(.ref.data)							\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -273,7 +275,9 @@
 	. = ALIGN((align));						\
 	.rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {		\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
-		*(.rodata) *(.rodata.*)					\
+		*(.rodata)						\
+		*(SORT(.rodata..rng.*))					\
+		*(.rodata.*)						\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		KEEP(*(__vermagic))	/* Kernel version magic */	\
 		. = ALIGN(8);						\
@@ -446,7 +450,9 @@
  * conflicting section names, and must pull in .text.[0-9a-zA-Z_]* */
 #define TEXT_TEXT							\
 		ALIGN_FUNCTION();					\
-		*(.text.hot .text .text.fixup .text.unlikely)		\
+		*(.text.hot .text)					\
+		*(SORT(.text..rng.*))					\
+		*(.text.fixup .text.unlikely)				\
 		*(.ref.text)						\
 	MEM_KEEP(init.text)						\
 	MEM_KEEP(exit.text)						\
@@ -549,6 +555,7 @@
 #define INIT_DATA							\
 	KEEP(*(SORT(___kentry+*)))					\
 	*(.init.data)							\
+	*(SORT(.init.data..rng.*))					\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -572,6 +579,7 @@
 
 #define INIT_TEXT							\
 	*(.init.text)							\
+	*(SORT(.init.text..rng.*))					\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/ranges.h b/include/linux/ranges.h
new file mode 100644
index 000000000000..1e64674f6d7d
--- /dev/null
+++ b/include/linux/ranges.h
@@ -0,0 +1,183 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * SECTION_RANGE_START - get address of start of section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the start address of the section range.
+ * This should give you the address of the first entry.
+ *
+ */
+#define SECTION_RANGE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * SECTION_RANGE_END - get address of end of the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define SECTION_RANGE_END(name)		LINUX_SECTION_END(name)
+
+/**
+ * SECTION_RANGE_SIZE - get number of entries in the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the number of entries in the section range.
+ * Example usage:
+ *
+ *   unsigned int num_ents = LINKTABLE_SIZE(some_fns);
+ */
+#define SECTION_RANGE_SIZE(name)					\
+	((SECTION_RANGE_END(name)) - (SECTION_RANGE_START(name)))
+
+/**
+ * SECTION_RANGE_EMPTY - check if section range has no entries
+ *
+ * @name: name of the section range
+ *
+ * Returns true if the section range is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(some_fns);
+ */
+#define SECTION_RANGE_EMPTY(name)	(SECTION_RANGE_SIZE(name) == 0)
+
+/**
+ * SECTION_RANGE_ADDR_WITHIN - returns true if address is in the section range
+ *
+ * @name: name of the section range
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_RANGE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) SECTION_RANGE_START(name) &&		\
+          addr < (unsigned long) SECTION_RANGE_END(name))
+
+/**
+ * SECTION_RANGE_ALIGNMENT - get the alignment of the section range
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the section range.
+ */
+#define SECTION_RANGE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.")))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.~")))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) SECTION_RANGE_START(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) SECTION_RANGE_END(name)[0] = {}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 03/14] ranges.h: add helpers to build and identify Linux section ranges
@ 2016-12-22  2:37       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:37 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

Section ranges are on one of the types of custom sections
types used in Linux. This provides a series of helpers for
defining them and using them. Most importantly this also
enables us to avoid modifying the linker script when we
add a new section range.

It turns out a lot of custom sections are actually section ranges,
and these are typically spelled out in their architecture specific
asm/sections.h file -- we enable architectures to override what asm
is used for section ranges but start by default trusting the
asm-generic version all around.

Although typically you will not want to have section ranges ordered
we must use SORT() on vmlinux.lds.S for section ranges to enable us
to extend a section range without modifying the linker script. To
accomplish this we use a special order string for the first element
of a section range -- the empty string "" (refer to __SECTION_RANGE_BEGIN()),
then "~" for the last element (refer to __SECTION_RANGE_BEGIN()). If
you use the "any" order for elements in between and use SORT() you end
up keeping any added element in betweeen and a reference to the
beginning and end of the section range without requiring custom linker
script modifications. Specific order annotations are also supported
to help construct synthetic functions, a demo for which will be provided
later.

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

o Extend commit log to justify SORT() and explain why and how we use
  specific special strings for the beginning, end elements of a section
  range and the "any" order for elements in between.

o Drop SECTION_RNG_ALL() -- we no longer need this on linker scripts

o To make this easier to read, as per Nicholas Piggin, add our own
  SECTION_RANGE_START(), SECTION_RANGE_END(). After reviewing the
  changes affected by this it seemed clearer and better then to also
  use our own specific SECTION_RANGE_SIZE(), and SECTION_RANGE_EMPTY(),
  and SECTION_RANGE_ALIGNMENT() as well.

o We were using LINUX_SECTION_START() and LINUX_SECTION_END() in some places
  but in some other places VMLINUX_SYMBOL(name), VMLINUX_SYMBOL(name##__end).
  Since we are adding SECTION_RANGE_START() and SECTION_RANGE_END() just
  use those consistently.

o Move the linker table *(SORT(.data.rng.*)) to be present before
  the recently added *(.data.[0-9a-zA-Z_]*) to ensure we keep sort order
  on the section range.

o Adds the "Linux section ordering" documentation, as its much more
  relevant after this patch, in particular when treating the "any"
  order level.

o Fix powerpc .text use: -- it does not use TEXT_TEXT so we must
  add our *(SORT(.text.rng.*)) to its linker script manually.

v4:

o tons of documentation love
o fix arch/x86/tools/relocs.c typo - which caused compilation issues
  on old toolchains
o port to new shiny sphinx documentation
o sprinkle a few more needed VMLINUX_SYMBOL() - fixes
  compilation on blackfin
o name changes as suggested 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
- rebrand DECLARE_SECTION_RNG() as DEFINE_SECTION_RANGE() - this is
  the asm version of the respective C version, this will have a
  userspace C demo added later.
o move __LINUX_RANGE() and __LINUX_RANGE_ORDER() - fixes builds
  on sparc
o adds section ranges to linker script
o rename SECTION_RANGE_ALL()
o use default alignment, fixes builds on powerpc and arm for both
  __LINUX_RANGE() and __LINUX_RANGE_ORDER()
o expand documentation to document modules support
o add maintainers
o use generic-y

v3: new in this series, uses copyleft-next

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst        |   1 +
 Documentation/sections/ranges.rst       |  74 +++++++++++++
 Documentation/sections/section-core.rst |   5 +
 MAINTAINERS                             |  10 ++
 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/Kbuild             |   1 +
 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/powerpc/kernel/vmlinux.lds.S       |   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            |  93 ++++++++++++++++
 include/asm-generic/section-core.h      |  41 +++++++
 include/asm-generic/vmlinux.lds.h       |  12 ++-
 include/linux/ranges.h                  | 183 ++++++++++++++++++++++++++++++++
 41 files changed, 451 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/linux/ranges.h

diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
index f37511ef05e7..4a1df389fa91 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -15,3 +15,4 @@ common a set of Linux helpers for ELF sections are also documented.
 
    background
    section-core
+   ranges
diff --git a/Documentation/sections/ranges.rst b/Documentation/sections/ranges.rst
new file mode 100644
index 000000000000..d9d3af4e52cb
--- /dev/null
+++ b/Documentation/sections/ranges.rst
@@ -0,0 +1,74 @@
+====================
+Linux section ranges
+====================
+
+This documents Linux' use of section ranges, how you can use
+them and how they work.
+
+About section ranges
+====================
+
+Introduction
+------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Introduction
+
+Section range module support
+----------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range module support
+
+Section range helpers
+=====================
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range helpers
+
+SECTION_RANGE_START
+-------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_START
+
+SECTION_RANGE_END
+-----------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_END
+
+SECTION_RANGE_SIZE
+------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_SIZE
+
+SECTION_RANGE_EMPTY
+-------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_EMPTY
+
+SECTION_RANGE_ADDR_WITHIN
+-------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_ADDR_WITHIN
+
+SECTION_RANGE_ALIGNMENT
+-------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_ALIGNMENT
+
+DECLARE_SECTION_RANGE
+---------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DECLARE_SECTION_RANGE
+
+DEFINE_SECTION_RANGE
+--------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DEFINE_SECTION_RANGE
+
+__LINUX_RANGE
+-------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE
+
+__LINUX_RANGE_ORDER
+-------------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE_ORDER
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
index ac5815a0d9b3..1f613a6c7b78 100644
--- a/Documentation/sections/section-core.rst
+++ b/Documentation/sections/section-core.rst
@@ -114,6 +114,11 @@ Linux .ref\* sections
 .. kernel-doc:: include/asm-generic/section-core.h
    :doc: .ref.rodata
 
+Linux section ordering
+======================
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux section ordering
+
 Generic Linux kernel section helpers
 ====================================
 
diff --git a/MAINTAINERS b/MAINTAINERS
index 308826f5094b..93bebccad674 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5422,6 +5422,16 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTION RANGES
+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
+S:	Supported
+F:	include/asm-generic/ranges.h
+F:	include/linux/ranges.h
+F:	Documentation/sections/ranges.rst
+
 GENERIC SECTIONS
 M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
 M:	Josh Poimboeuf <jpoimboe@redhat.com>
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index 5422827f1585..e44c896b91c4 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 7b2cb3dea5fc..a374b7f83888 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -52,3 +52,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 9b69a22a9ae1..0d47f98ccbc0 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -42,3 +42,4 @@ generic-y += unaligned.h
 generated-y += mach-types.h
 generated-y += unistd-nr.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 00ace5e826f1..e9939cbd9067 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index f2c3b656a0e7..edc176348d7c 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -23,3 +23,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index bf20541bcf21..3428415b1996 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 38127ce747be..cede2a950fbf 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 385cd88a9d9e..fb8bb4112773 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 46d7c599d9b8..5191fec655d7 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 1ec04ec1c82b..7929a992566c 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -76,3 +76,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index 37d7bfae7619..af17ee334788 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 672c6d5da18c..d8f226b35a0a 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 6111e1523750..1c6504d29312 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1277b45bf4f9..006e2863ad37 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index b1011375cd7a..4a8471434a3e 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -56,3 +56,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index c6c2cf6edc98..63c083a1f8da 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index a67d3177f3ca..288e21b64170 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index f8145bc85835..656af7b69940 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index c9c7cb82b00f..c55880659d67 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 86175e701869..7d6a704b808c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -72,3 +72,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 18a9d4c5ead7..f11d1249738f 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 4322d9746cdb..60d8349241a7 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 7394b770ae1f..fcfc9d102348 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -107,6 +107,7 @@ SECTIONS
 #endif
 		/* careful! __ftr_alt_* sections need to be close to .text */
 		*(.text .fixup __ftr_alt_* .ref.text)
+		*(SORT(.text.rng.*))
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 63a1c2924b91..c1b85a361e5d 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index f089a264cd38..f0cdb2cbca4d 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -15,3 +15,4 @@ generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 7b0356dca562..c9bb7932a3d1 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 438f86573dc5..28280887ac79 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index fb6b831c1fba..33f7069763ae 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 580bd5ff828f..b952dcb3e216 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -27,3 +27,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 8578702d4998..93abbfdab543 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += ranges.h
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index af975f21eeee..f672f2fc181d 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index 73eb7fd4aec4..f96fa2ddf7c9 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -68,6 +68,8 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
 	"__end_rodata|"
 	"__initramfs_start|"
 	"(jiffies|jiffies_64)|"
+	".rodata..rng.*|"
+	".init.text..rng.*|"
 #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 7879c31e66a7..2b7fe48c0225 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -33,3 +33,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/include/asm-generic/ranges.h b/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..75c196864f45
--- /dev/null
+++ b/include/asm-generic/ranges.h
@@ -0,0 +1,93 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  any, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       any, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   any, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(#section "..rng.name.any")))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using
+ * 	binutils SORT(), the number is sorted as a string, as such be
+ * 	sure to fill with zeroes any empty digits. For instance if you are
+ * 	using 3 levels of digits for order levels, use 001 for the first entry,
+ * 	0002 for the second, 999 for the last entry. You can use however many
+ * 	digits you need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(#section "..rng.name." #level)))
+
+#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/section-core.h b/include/asm-generic/section-core.h
index bb16befc4251..65fb076765f8 100644
--- a/include/asm-generic/section-core.h
+++ b/include/asm-generic/section-core.h
@@ -183,6 +183,47 @@
  * or data structures part of the init sections.
  */
 
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections alpha numerically. Linux has historically used 'SORT()' in
+ * ``include/asm-generic/vmlinux.lds.h``, its a well established practice. If
+ * 'SORT()' is used on a section one can provide ordering using a postfix on
+ * each section entry added. For instance if a linker script uses::
+ *
+ *    SORT(.foo.*)
+ *
+ * one can then add entries with explicit ordering using numeric postfixes for
+ * each entry, we refer to these as 'order levels'. Since 'SORT()' sorts alpha
+ * numerically a specific series set of digits must be agreed a-priori which
+ * would give also an idea of the max expected number of entries added to a
+ * section. For instance, if you expect a maximum of 999 entries you can use
+ * 3 digits for a section order level. If you wanted an entry to be ordered
+ * first you could use the postfix '000', if you wanted an entry to follow this
+ * you could use '001', and so on. We could for instance have::
+ *
+ *    .foo.000
+ *    .foo.001
+ *    .foo.002
+ *
+ * Often times one may want the option to specify no order is required for
+ * certain elements added to a section which does use 'SORT()' on the linker
+ * script. You can use any arbitrary string value to to specify no order is
+ * used, so long as its used consistantly. For instance, one possibility is to
+ * use the 'any' postfix.  All entries on the section would then have no
+ * specific ordering::
+ *
+ *    .foo.any
+ *    .foo.any
+ *    .foo.any
+ *
+ * To help establish a convention we reserve the special name 'any' for this
+ * purpose. Developers can use and expect the 'any' postfix string on sections
+ * as a helper to annotate section ordering at link time is not relevant
+ * for entries on a section.
+ */
+
 /* Can be used on foo.S for instance */
 #ifndef __set_section_core_type
 # define __set_section_core_type(___section, ___core, ___name,		\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 483f60c451f9..71bfd3b3c719 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -56,6 +56,7 @@
 
 #include <linux/export.h>
 #include <asm/section-core.h>
+#include <asm/ranges.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
@@ -205,6 +206,7 @@
  */
 #define DATA_DATA							\
 	*(.data .data.[0-9a-zA-Z_]*)					\
+	*(SORT(.data..rng.*))						\
 	*(.ref.data)							\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -273,7 +275,9 @@
 	. = ALIGN((align));						\
 	.rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {		\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
-		*(.rodata) *(.rodata.*)					\
+		*(.rodata)						\
+		*(SORT(.rodata..rng.*))					\
+		*(.rodata.*)						\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		KEEP(*(__vermagic))	/* Kernel version magic */	\
 		. = ALIGN(8);						\
@@ -446,7 +450,9 @@
  * conflicting section names, and must pull in .text.[0-9a-zA-Z_]* */
 #define TEXT_TEXT							\
 		ALIGN_FUNCTION();					\
-		*(.text.hot .text .text.fixup .text.unlikely)		\
+		*(.text.hot .text)					\
+		*(SORT(.text..rng.*))					\
+		*(.text.fixup .text.unlikely)				\
 		*(.ref.text)						\
 	MEM_KEEP(init.text)						\
 	MEM_KEEP(exit.text)						\
@@ -549,6 +555,7 @@
 #define INIT_DATA							\
 	KEEP(*(SORT(___kentry+*)))					\
 	*(.init.data)							\
+	*(SORT(.init.data..rng.*))					\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -572,6 +579,7 @@
 
 #define INIT_TEXT							\
 	*(.init.text)							\
+	*(SORT(.init.text..rng.*))					\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/ranges.h b/include/linux/ranges.h
new file mode 100644
index 000000000000..1e64674f6d7d
--- /dev/null
+++ b/include/linux/ranges.h
@@ -0,0 +1,183 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * SECTION_RANGE_START - get address of start of section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the start address of the section range.
+ * This should give you the address of the first entry.
+ *
+ */
+#define SECTION_RANGE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * SECTION_RANGE_END - get address of end of the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define SECTION_RANGE_END(name)		LINUX_SECTION_END(name)
+
+/**
+ * SECTION_RANGE_SIZE - get number of entries in the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the number of entries in the section range.
+ * Example usage:
+ *
+ *   unsigned int num_ents = LINKTABLE_SIZE(some_fns);
+ */
+#define SECTION_RANGE_SIZE(name)					\
+	((SECTION_RANGE_END(name)) - (SECTION_RANGE_START(name)))
+
+/**
+ * SECTION_RANGE_EMPTY - check if section range has no entries
+ *
+ * @name: name of the section range
+ *
+ * Returns true if the section range is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(some_fns);
+ */
+#define SECTION_RANGE_EMPTY(name)	(SECTION_RANGE_SIZE(name) == 0)
+
+/**
+ * SECTION_RANGE_ADDR_WITHIN - returns true if address is in the section range
+ *
+ * @name: name of the section range
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_RANGE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) SECTION_RANGE_START(name) &&		\
+          addr < (unsigned long) SECTION_RANGE_END(name))
+
+/**
+ * SECTION_RANGE_ALIGNMENT - get the alignment of the section range
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the section range.
+ */
+#define SECTION_RANGE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.")))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.~")))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) SECTION_RANGE_START(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) SECTION_RANGE_END(name)[0] = {}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 04/14] tables.h: add linker table support
  2016-12-22  2:37     ` Luis R. Rodriguez
  (?)
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

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.

v5:
o Use ..tbl.* instead of .tbl.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clashes with compiler generated
  sections.
o Replace section macros with section names
o Dropped SECTION_RNG_ALL()
o Fix documentation typos
o To make this easier to read, as per Nicholas Piggin, add our own
  LINKTABLE_START(), LINKTABLE_END(). After reviewing the changes
  affected by this it seemed clearer and better then to also
  use our own specific LINKTABLE_SIZE(), LINKTABLE_EMPTY() and
  LINKTABLE_ALIGNMENT() as well.
o Clarifies SECTION_TBL_RO needs to be kept since some toolchains
  are buggy, and so we also add SECTION_TBL_RO_STR.
o We were using LINUX_SECTION_START() and LINUX_SECTION_END() in some places
  but in some other places VMLINUX_SYMBOL(name), VMLINUX_SYMBOL(name##__end).
  Since we are adding LINKTABLE_START() and LINKTABLE_END() just use those
  consistently.
o Fix DEFINE_LINKTABLE_INIT() by making it use DECLARE_LINKTABLE_RO()
  which forces const.
o Fix powerpc .text use: it does not use TEXT_TEXT so we must
  add our *(SORT(.text.tbl.*)) to its linker script manually.

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@ipxe.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst         |   1 +
 Documentation/sections/linker-tables.rst | 212 +++++++++++
 MAINTAINERS                              |  10 +
 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/powerpc/kernel/vmlinux.lds.S        |   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/tables.h             |  48 +++
 include/asm-generic/vmlinux.lds.h        |   6 +
 include/linux/tables.h                   | 612 +++++++++++++++++++++++++++++++
 39 files changed, 948 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 4a1df389fa91..7c7c1adf955c 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -16,3 +16,4 @@ common a set of Linux helpers for ELF sections are also documented.
    background
    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..71704159e90e
--- /dev/null
+++ b/Documentation/sections/linker-tables.rst
@@ -0,0 +1,212 @@
+=========+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_START
+---------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_START
+
+LINKTABLE_END
+-------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_END
+
+LINKTABLE_SIZE
+--------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_SIZE
+
+LINKTABLE_EMPTY
+---------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_EMPTY
+
+LINKTABLE_ADDR_WITHIN
+---------------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_ADDR_WITHIN
+
+LINKTABLE_ALIGNMENT
+-------------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_ALIGNMENT
+
+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 93bebccad674..c57ba50e2348 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5405,6 +5405,16 @@ 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
+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
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 a374b7f83888..ccfa69ce2608 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -53,3 +53,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 0d47f98ccbc0..b70d4b78d577 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -43,3 +43,4 @@ generated-y += mach-types.h
 generated-y += unistd-nr.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 e9939cbd9067..0c1e781ab10b 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -47,3 +47,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 3428415b1996..9115b215fc7e 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -49,3 +49,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..90a0d3df35c8
--- /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@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 weak 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 */
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 006e2863ad37..c28bcdecc764 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -36,3 +36,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 4a8471434a3e..c836f7e2a5e7 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -57,3 +57,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 288e21b64170..579f494914f5 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 f11d1249738f..aaae8a9f6099 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -30,3 +30,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 60d8349241a7..7c06627a0a0d 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -10,3 +10,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/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index fcfc9d102348..8cd940c72895 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -108,6 +108,7 @@ SECTIONS
 		/* careful! __ftr_alt_* sections need to be close to .text */
 		*(.text .fixup __ftr_alt_* .ref.text)
 		*(SORT(.text.rng.*))
+		*(SORT(.text..tbl.*))
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index c1b85a361e5d..96dd69931427 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 28280887ac79..23a2216f4146 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -23,3 +23,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 33f7069763ae..a599f6f4ee0a 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -42,3 +42,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 b952dcb3e216..d2867aa09e23 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -28,3 +28,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 93abbfdab543..6671a1f08ead 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -62,3 +62,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 f672f2fc181d..4cb511f1067c 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -14,3 +14,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 f96fa2ddf7c9..484a24c309fb 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 2b7fe48c0225..7b41f32a2ba0 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -34,3 +34,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/tables.h b/include/asm-generic/tables.h
new file mode 100644
index 000000000000..16ef40d145fb
--- /dev/null
+++ b/include/asm-generic/tables.h
@@ -0,0 +1,48 @@
+#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..tbl.name.level
+
+/* Some toolchains are buggy, let them override */
+#ifndef SECTION_TBL_RO
+# define SECTION_TBL_RO	.rodata
+#endif
+
+#define SECTION_TBL_RO_STR __stringify(SECTION_TBL_RO)
+
+#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, 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, 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 71bfd3b3c719..ce1e9a310ada 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)
@@ -207,6 +208,7 @@
 #define DATA_DATA							\
 	*(.data .data.[0-9a-zA-Z_]*)					\
 	*(SORT(.data..rng.*))						\
+	*(SORT(.data..tbl.*))						\
 	*(.ref.data)							\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -277,6 +279,7 @@
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
 		*(.rodata)						\
 		*(SORT(.rodata..rng.*))					\
+		*(SORT(.rodata..tbl.*))					\
 		*(.rodata.*)						\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		KEEP(*(__vermagic))	/* Kernel version magic */	\
@@ -452,6 +455,7 @@
 		ALIGN_FUNCTION();					\
 		*(.text.hot .text)					\
 		*(SORT(.text..rng.*))					\
+		*(SORT(.text..tbl.*))					\
 		*(.text.fixup .text.unlikely)				\
 		*(.ref.text)						\
 	MEM_KEEP(init.text)						\
@@ -556,6 +560,7 @@
 	KEEP(*(SORT(___kentry+*)))					\
 	*(.init.data)							\
 	*(SORT(.init.data..rng.*))					\
+	*(SORT(.init.data..tbl.*))					\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -580,6 +585,7 @@
 #define INIT_TEXT							\
 	*(.init.text)							\
 	*(SORT(.init.text..rng.*))					\
+	*(SORT(.init.text..tbl.*))					\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
new file mode 100644
index 000000000000..cc8fb1dcee47
--- /dev/null
+++ b/include/linux/tables.h
@@ -0,0 +1,612 @@
+#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(.foo..tbl.*))
+ *
+ * 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_START - get address of start of linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the start address of the linker table.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINKTABLE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * LINKTABLE_END - get address of end of the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define LINKTABLE_END(name)	LINUX_SECTION_END(name)
+
+/**
+ * LINKTABLE_SIZE - get number of entries in the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the number of entries in the linker table.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINKTABLE_SIZE(frobnicator_fns);
+ */
+#define LINKTABLE_SIZE(name)					\
+	((LINKTABLE_END(name)) - (LINKTABLE_START(name)))
+
+/**
+ * LINKTABLE_EMPTY - check if linker table has no entries
+ *
+ * @name: name of linker table
+ *
+ * Returns true if the linker table is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(frobnicator_fns);
+ */
+#define LINKTABLE_EMPTY(name)	(LINKTABLE_SIZE(name) = 0)
+
+/**
+ * LINKTABLE_ADDR_WITHIN - returns true if address is in the linker table
+ *
+ * @name: name of the linker table
+ * @addr: address to query for
+ *
+ * Returns true if the address is part of the linker table.
+ */
+#define LINKTABLE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) LINKTABLE_START(name) &&		\
+          addr < (unsigned long) LINKTABLE_END(name))
+
+/**
+ * LINKTABLE_ALIGNMENT - get the alignment of the linker table
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the linker table.
+ */
+#define LINKTABLE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * 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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_TEXT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE_RO(name, ~) LINKTABLE_END(name)[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_RO(type, name);				\
+	LINKTABLE_INIT_WEAK(name,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT_DATA(name, ~) LINKTABLE_END(name)[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 = LINKTABLE_START(tbl);				\
+	     pointer < LINKTABLE_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 < LINKTABLE_SIZE(tbl); i++)			\
+		(LINKTABLE_START(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 < LINKTABLE_SIZE(tbl); i++)		\
+		err = (LINKTABLE_START(tbl)[i]).func (args);		\
+		err;							\
+})
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_LINKER_TABLES_H */
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 04/14] tables.h: add linker table support
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

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.

v5:
o Use ..tbl.* instead of .tbl.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clashes with compiler generated
  sections.
o Replace section macros with section names
o Dropped SECTION_RNG_ALL()
o Fix documentation typos
o To make this easier to read, as per Nicholas Piggin, add our own
  LINKTABLE_START(), LINKTABLE_END(). After reviewing the changes
  affected by this it seemed clearer and better then to also
  use our own specific LINKTABLE_SIZE(), LINKTABLE_EMPTY() and
  LINKTABLE_ALIGNMENT() as well.
o Clarifies SECTION_TBL_RO needs to be kept since some toolchains
  are buggy, and so we also add SECTION_TBL_RO_STR.
o We were using LINUX_SECTION_START() and LINUX_SECTION_END() in some places
  but in some other places VMLINUX_SYMBOL(name), VMLINUX_SYMBOL(name##__end).
  Since we are adding LINKTABLE_START() and LINKTABLE_END() just use those
  consistently.
o Fix DEFINE_LINKTABLE_INIT() by making it use DECLARE_LINKTABLE_RO()
  which forces const.
o Fix powerpc .text use: it does not use TEXT_TEXT so we must
  add our *(SORT(.text.tbl.*)) to its linker script manually.

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@ipxe.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst         |   1 +
 Documentation/sections/linker-tables.rst | 212 +++++++++++
 MAINTAINERS                              |  10 +
 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/powerpc/kernel/vmlinux.lds.S        |   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/tables.h             |  48 +++
 include/asm-generic/vmlinux.lds.h        |   6 +
 include/linux/tables.h                   | 612 +++++++++++++++++++++++++++++++
 39 files changed, 948 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 4a1df389fa91..7c7c1adf955c 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -16,3 +16,4 @@ common a set of Linux helpers for ELF sections are also documented.
    background
    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..71704159e90e
--- /dev/null
+++ b/Documentation/sections/linker-tables.rst
@@ -0,0 +1,212 @@
+===================
+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_START
+---------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_START
+
+LINKTABLE_END
+-------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_END
+
+LINKTABLE_SIZE
+--------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_SIZE
+
+LINKTABLE_EMPTY
+---------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_EMPTY
+
+LINKTABLE_ADDR_WITHIN
+---------------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_ADDR_WITHIN
+
+LINKTABLE_ALIGNMENT
+-------------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_ALIGNMENT
+
+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 93bebccad674..c57ba50e2348 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5405,6 +5405,16 @@ 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
+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
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 a374b7f83888..ccfa69ce2608 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -53,3 +53,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 0d47f98ccbc0..b70d4b78d577 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -43,3 +43,4 @@ generated-y += mach-types.h
 generated-y += unistd-nr.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 e9939cbd9067..0c1e781ab10b 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -47,3 +47,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 3428415b1996..9115b215fc7e 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -49,3 +49,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..90a0d3df35c8
--- /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@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 weak 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 */
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 006e2863ad37..c28bcdecc764 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -36,3 +36,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 4a8471434a3e..c836f7e2a5e7 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -57,3 +57,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 288e21b64170..579f494914f5 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 f11d1249738f..aaae8a9f6099 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -30,3 +30,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 60d8349241a7..7c06627a0a0d 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -10,3 +10,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/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index fcfc9d102348..8cd940c72895 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -108,6 +108,7 @@ SECTIONS
 		/* careful! __ftr_alt_* sections need to be close to .text */
 		*(.text .fixup __ftr_alt_* .ref.text)
 		*(SORT(.text.rng.*))
+		*(SORT(.text..tbl.*))
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index c1b85a361e5d..96dd69931427 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 28280887ac79..23a2216f4146 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -23,3 +23,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 33f7069763ae..a599f6f4ee0a 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -42,3 +42,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 b952dcb3e216..d2867aa09e23 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -28,3 +28,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 93abbfdab543..6671a1f08ead 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -62,3 +62,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 f672f2fc181d..4cb511f1067c 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -14,3 +14,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 f96fa2ddf7c9..484a24c309fb 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 2b7fe48c0225..7b41f32a2ba0 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -34,3 +34,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/tables.h b/include/asm-generic/tables.h
new file mode 100644
index 000000000000..16ef40d145fb
--- /dev/null
+++ b/include/asm-generic/tables.h
@@ -0,0 +1,48 @@
+#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..tbl.name.level
+
+/* Some toolchains are buggy, let them override */
+#ifndef SECTION_TBL_RO
+# define SECTION_TBL_RO	.rodata
+#endif
+
+#define SECTION_TBL_RO_STR __stringify(SECTION_TBL_RO)
+
+#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, 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, 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 71bfd3b3c719..ce1e9a310ada 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)
@@ -207,6 +208,7 @@
 #define DATA_DATA							\
 	*(.data .data.[0-9a-zA-Z_]*)					\
 	*(SORT(.data..rng.*))						\
+	*(SORT(.data..tbl.*))						\
 	*(.ref.data)							\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -277,6 +279,7 @@
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
 		*(.rodata)						\
 		*(SORT(.rodata..rng.*))					\
+		*(SORT(.rodata..tbl.*))					\
 		*(.rodata.*)						\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		KEEP(*(__vermagic))	/* Kernel version magic */	\
@@ -452,6 +455,7 @@
 		ALIGN_FUNCTION();					\
 		*(.text.hot .text)					\
 		*(SORT(.text..rng.*))					\
+		*(SORT(.text..tbl.*))					\
 		*(.text.fixup .text.unlikely)				\
 		*(.ref.text)						\
 	MEM_KEEP(init.text)						\
@@ -556,6 +560,7 @@
 	KEEP(*(SORT(___kentry+*)))					\
 	*(.init.data)							\
 	*(SORT(.init.data..rng.*))					\
+	*(SORT(.init.data..tbl.*))					\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -580,6 +585,7 @@
 #define INIT_TEXT							\
 	*(.init.text)							\
 	*(SORT(.init.text..rng.*))					\
+	*(SORT(.init.text..tbl.*))					\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
new file mode 100644
index 000000000000..cc8fb1dcee47
--- /dev/null
+++ b/include/linux/tables.h
@@ -0,0 +1,612 @@
+#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(.foo..tbl.*))
+ *
+ * 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_START - get address of start of linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the start address of the linker table.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINKTABLE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * LINKTABLE_END - get address of end of the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define LINKTABLE_END(name)	LINUX_SECTION_END(name)
+
+/**
+ * LINKTABLE_SIZE - get number of entries in the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the number of entries in the linker table.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINKTABLE_SIZE(frobnicator_fns);
+ */
+#define LINKTABLE_SIZE(name)					\
+	((LINKTABLE_END(name)) - (LINKTABLE_START(name)))
+
+/**
+ * LINKTABLE_EMPTY - check if linker table has no entries
+ *
+ * @name: name of linker table
+ *
+ * Returns true if the linker table is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(frobnicator_fns);
+ */
+#define LINKTABLE_EMPTY(name)	(LINKTABLE_SIZE(name) == 0)
+
+/**
+ * LINKTABLE_ADDR_WITHIN - returns true if address is in the linker table
+ *
+ * @name: name of the linker table
+ * @addr: address to query for
+ *
+ * Returns true if the address is part of the linker table.
+ */
+#define LINKTABLE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) LINKTABLE_START(name) &&		\
+          addr < (unsigned long) LINKTABLE_END(name))
+
+/**
+ * LINKTABLE_ALIGNMENT - get the alignment of the linker table
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the linker table.
+ */
+#define LINKTABLE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * 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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_TEXT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE_RO(name, ~) LINKTABLE_END(name)[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_RO(type, name);				\
+	LINKTABLE_INIT_WEAK(name,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT_DATA(name, ~) LINKTABLE_END(name)[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 = LINKTABLE_START(tbl);				\
+	     pointer < LINKTABLE_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 < LINKTABLE_SIZE(tbl); i++)			\
+		(LINKTABLE_START(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 < LINKTABLE_SIZE(tbl); i++)		\
+		err = (LINKTABLE_START(tbl)[i]).func (args);		\
+		err;							\
+})
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_LINKER_TABLES_H */
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 04/14] tables.h: add linker table support
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

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.

v5:
o Use ..tbl.* instead of .tbl.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clashes with compiler generated
  sections.
o Replace section macros with section names
o Dropped SECTION_RNG_ALL()
o Fix documentation typos
o To make this easier to read, as per Nicholas Piggin, add our own
  LINKTABLE_START(), LINKTABLE_END(). After reviewing the changes
  affected by this it seemed clearer and better then to also
  use our own specific LINKTABLE_SIZE(), LINKTABLE_EMPTY() and
  LINKTABLE_ALIGNMENT() as well.
o Clarifies SECTION_TBL_RO needs to be kept since some toolchains
  are buggy, and so we also add SECTION_TBL_RO_STR.
o We were using LINUX_SECTION_START() and LINUX_SECTION_END() in some places
  but in some other places VMLINUX_SYMBOL(name), VMLINUX_SYMBOL(name##__end).
  Since we are adding LINKTABLE_START() and LINKTABLE_END() just use those
  consistently.
o Fix DEFINE_LINKTABLE_INIT() by making it use DECLARE_LINKTABLE_RO()
  which forces const.
o Fix powerpc .text use: it does not use TEXT_TEXT so we must
  add our *(SORT(.text.tbl.*)) to its linker script manually.

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@ipxe.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst         |   1 +
 Documentation/sections/linker-tables.rst | 212 +++++++++++
 MAINTAINERS                              |  10 +
 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/powerpc/kernel/vmlinux.lds.S        |   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/tables.h             |  48 +++
 include/asm-generic/vmlinux.lds.h        |   6 +
 include/linux/tables.h                   | 612 +++++++++++++++++++++++++++++++
 39 files changed, 948 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 4a1df389fa91..7c7c1adf955c 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -16,3 +16,4 @@ common a set of Linux helpers for ELF sections are also documented.
    background
    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..71704159e90e
--- /dev/null
+++ b/Documentation/sections/linker-tables.rst
@@ -0,0 +1,212 @@
+===================
+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_START
+---------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_START
+
+LINKTABLE_END
+-------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_END
+
+LINKTABLE_SIZE
+--------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_SIZE
+
+LINKTABLE_EMPTY
+---------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_EMPTY
+
+LINKTABLE_ADDR_WITHIN
+---------------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_ADDR_WITHIN
+
+LINKTABLE_ALIGNMENT
+-------------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_ALIGNMENT
+
+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 93bebccad674..c57ba50e2348 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5405,6 +5405,16 @@ 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
+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
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 a374b7f83888..ccfa69ce2608 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -53,3 +53,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 0d47f98ccbc0..b70d4b78d577 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -43,3 +43,4 @@ generated-y += mach-types.h
 generated-y += unistd-nr.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 e9939cbd9067..0c1e781ab10b 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -47,3 +47,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 3428415b1996..9115b215fc7e 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -49,3 +49,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..90a0d3df35c8
--- /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@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 weak 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 */
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 006e2863ad37..c28bcdecc764 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -36,3 +36,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 4a8471434a3e..c836f7e2a5e7 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -57,3 +57,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 288e21b64170..579f494914f5 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 f11d1249738f..aaae8a9f6099 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -30,3 +30,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 60d8349241a7..7c06627a0a0d 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -10,3 +10,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/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index fcfc9d102348..8cd940c72895 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -108,6 +108,7 @@ SECTIONS
 		/* careful! __ftr_alt_* sections need to be close to .text */
 		*(.text .fixup __ftr_alt_* .ref.text)
 		*(SORT(.text.rng.*))
+		*(SORT(.text..tbl.*))
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index c1b85a361e5d..96dd69931427 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 28280887ac79..23a2216f4146 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -23,3 +23,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 33f7069763ae..a599f6f4ee0a 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -42,3 +42,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 b952dcb3e216..d2867aa09e23 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -28,3 +28,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 93abbfdab543..6671a1f08ead 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -62,3 +62,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 f672f2fc181d..4cb511f1067c 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -14,3 +14,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 f96fa2ddf7c9..484a24c309fb 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 2b7fe48c0225..7b41f32a2ba0 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -34,3 +34,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/tables.h b/include/asm-generic/tables.h
new file mode 100644
index 000000000000..16ef40d145fb
--- /dev/null
+++ b/include/asm-generic/tables.h
@@ -0,0 +1,48 @@
+#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..tbl.name.level
+
+/* Some toolchains are buggy, let them override */
+#ifndef SECTION_TBL_RO
+# define SECTION_TBL_RO	.rodata
+#endif
+
+#define SECTION_TBL_RO_STR __stringify(SECTION_TBL_RO)
+
+#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, 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, 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 71bfd3b3c719..ce1e9a310ada 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)
@@ -207,6 +208,7 @@
 #define DATA_DATA							\
 	*(.data .data.[0-9a-zA-Z_]*)					\
 	*(SORT(.data..rng.*))						\
+	*(SORT(.data..tbl.*))						\
 	*(.ref.data)							\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -277,6 +279,7 @@
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
 		*(.rodata)						\
 		*(SORT(.rodata..rng.*))					\
+		*(SORT(.rodata..tbl.*))					\
 		*(.rodata.*)						\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		KEEP(*(__vermagic))	/* Kernel version magic */	\
@@ -452,6 +455,7 @@
 		ALIGN_FUNCTION();					\
 		*(.text.hot .text)					\
 		*(SORT(.text..rng.*))					\
+		*(SORT(.text..tbl.*))					\
 		*(.text.fixup .text.unlikely)				\
 		*(.ref.text)						\
 	MEM_KEEP(init.text)						\
@@ -556,6 +560,7 @@
 	KEEP(*(SORT(___kentry+*)))					\
 	*(.init.data)							\
 	*(SORT(.init.data..rng.*))					\
+	*(SORT(.init.data..tbl.*))					\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -580,6 +585,7 @@
 #define INIT_TEXT							\
 	*(.init.text)							\
 	*(SORT(.init.text..rng.*))					\
+	*(SORT(.init.text..tbl.*))					\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
new file mode 100644
index 000000000000..cc8fb1dcee47
--- /dev/null
+++ b/include/linux/tables.h
@@ -0,0 +1,612 @@
+#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(.foo..tbl.*))
+ *
+ * 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_START - get address of start of linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the start address of the linker table.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINKTABLE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * LINKTABLE_END - get address of end of the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define LINKTABLE_END(name)	LINUX_SECTION_END(name)
+
+/**
+ * LINKTABLE_SIZE - get number of entries in the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the number of entries in the linker table.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINKTABLE_SIZE(frobnicator_fns);
+ */
+#define LINKTABLE_SIZE(name)					\
+	((LINKTABLE_END(name)) - (LINKTABLE_START(name)))
+
+/**
+ * LINKTABLE_EMPTY - check if linker table has no entries
+ *
+ * @name: name of linker table
+ *
+ * Returns true if the linker table is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(frobnicator_fns);
+ */
+#define LINKTABLE_EMPTY(name)	(LINKTABLE_SIZE(name) == 0)
+
+/**
+ * LINKTABLE_ADDR_WITHIN - returns true if address is in the linker table
+ *
+ * @name: name of the linker table
+ * @addr: address to query for
+ *
+ * Returns true if the address is part of the linker table.
+ */
+#define LINKTABLE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) LINKTABLE_START(name) &&		\
+          addr < (unsigned long) LINKTABLE_END(name))
+
+/**
+ * LINKTABLE_ALIGNMENT - get the alignment of the linker table
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the linker table.
+ */
+#define LINKTABLE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * 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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_TEXT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE_RO(name, ~) LINKTABLE_END(name)[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_RO(type, name);				\
+	LINKTABLE_INIT_WEAK(name,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT_DATA(name, ~) LINKTABLE_END(name)[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 = LINKTABLE_START(tbl);				\
+	     pointer < LINKTABLE_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 < LINKTABLE_SIZE(tbl); i++)			\
+		(LINKTABLE_START(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 < LINKTABLE_SIZE(tbl); i++)		\
+		err = (LINKTABLE_START(tbl)[i]).func (args);		\
+		err;							\
+})
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_LINKER_TABLES_H */
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 05/14] kbuild: enable option to force compile force-obj-y and force-lib-y
  2016-12-22  2:37     ` Luis R. Rodriguez
  (?)
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Linux provides a rich array of features, enabling each feature
however increases the size of the kernel and there are many
features which users often want disabled. The traditional
solution to this problem is for each feature to have its own
Kconfig symbol, followed by a series of #ifdef statements
in C code and header files, allowing the feature to be compiled
only when desirable. As the variability of Linux increases build
tests can and are often done with random kernel configurations,
allyesconfig, and allmodconfig to help find code issues. This
however doesn't catch all errors and as a consequence code that
is typically not enabled often can suffer from bit-rot over time.

An alternative approach for subsystems, which refer to as the 'build-all
link-selectively philosophy' is to keep the Kconfig symbols, replace
the #ifdef approach by having each feature implemented it its own C file,
and force compilation for all features to avoid the code bit-rot problem.
With this strategy only features that are enabled via Kconfig get
linked into the kernel, so the forced compilation has no size impact
on the kernel. The practice of having each feature implemented in its own
C file is already prevalent in many subsystems, however #ifdefs are still
typically required during feature initialization. For instance in:

  #ifdef CONFIG_FOO
  foo_init();
  #endif

We cannot remove the #ifdef and leave foo_init() as we'd either
need to always enable the feature or add a respective #ifdef in a
foo.h which makes foo_init() do nothing when CONFIG_FOO is disabled.

Linker tables enable lifting the requirement to use of #ifdefs during
initialization. With linker tables initialization sequences can instead
be aggregated into a custom ELF section at link time, during run time
the table can be iterated over and each init sequence enabled can be called.
A feature's init routine is only added to a table when its respective
Kconfig symbols has been enabled and therefore linked in. Linker tables
enable subsystems to completely do away with #ifdefs if one is comfortable
in accepting all subsystem's feature's structural size implications.

Subsystems which want to follow the 'build-all link-selectively
philosophy' still need a way to easily express and annotate that they
wish for all code to always be compiled to help avoid code bit rot,
as such two new targets force-obj-y and force-lib-y are provided to
help with this. Its not fair to require everyone to force compilation
of all features of a subsystem though, so as a compromise, the new
targets only force compilation when CONFIG_BUILD_AVOID_BITROT is
enabled.

Only built-in features are supported at the moment. Module support
is expected to be added after a generic solution to add linker
tables to modules more easily is developed.

v4: this patch was added to this series, it was split off from the
    linker tables addition due to the confusion over the code bit
    rot alternatives that are possible with linker tables.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/kbuild/makefiles.txt       | 36 ++++++++++++++++
 Documentation/sections/linker-tables.rst | 15 +++++++
 include/linux/tables.h                   | 71 ++++++++++++++++++++++++++++++++
 init/Kconfig                             | 22 ++++++++++
 scripts/Makefile.build                   |  7 ++--
 scripts/Makefile.clean                   |  2 +
 scripts/Makefile.lib                     | 11 +++++
 7 files changed, 161 insertions(+), 3 deletions(-)

diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 9b9c4797fc55..1af275cd4879 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -1090,6 +1090,42 @@ When kbuild executes, the following steps are followed (roughly):
 	In this example, extra-y is used to list object files that
 	shall be built, but shall not be linked as part of built-in.o.
 
+    force-obj-y force-lib-y
+
+	When CONFIG_BUILD_AVOID_BITROT is enabled using these targets for your
+	kconfig symbols forces compilation of the associated objects if the
+	kconfig's symbol's dependencies are met, the objects however are only
+	linked into to the kernel if and only if the kconfig symbol was
+	enabled. If CONFIG_BUILD_AVOID_BITROT is disabled the force-obj-y and
+	force-lib-y targets are functionally equilvalent to obj-y and lib-y
+	respectively.
+
+	Using force-obj-y and force-lib-y are part of a code architecture and
+	build philosophy further enabled by linker tables, for more details
+	refer to the documention in include/linux/tables.h, refer to the
+	sections:
+
+		o The code bit-rot problem
+		o The build-all selective-link philosophy
+		o Avoiding the code bit-rot problem with linker tables
+		o Linker table module support
+
+	Modules support is expected to be enhanced in the future, so for now
+	only built-in features are supported.
+
+	Example use:
+
+		force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	An alternative to using force-obj-y, is to use extra-y followed by the
+	respective obj-y:
+
+		extra-y += foo.o
+		obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	Using force-obj-y and force-lib-y can be used to help annotate the
+	targets follow the 'build-all selective-link philosophy' further
+	enabled by linker tables.
 
 --- 6.7 Commands useful for building a boot image
 
diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index 71704159e90e..a80f4dd94659 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -30,6 +30,21 @@ How linker tables simplify initialization code
 .. kernel-doc:: include/linux/tables.h
    :doc: How linker tables simplify initialization code
 
+The code bit-rot problem
+------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The code bit-rot problem
+
+The build-all selective-link philosophy
+---------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The build-all selective-link philosophy
+
+Avoiding the code bit-rot problem with linker tables
+----------------------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: Avoiding the code bit-rot problem with linker tables
+
 Using linker tables in Linux
 ==============
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
index cc8fb1dcee47..fdadf794b63e 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -169,6 +169,77 @@
  */
 
 /**
+ * DOC: The code bit-rot problem
+ *
+ * Linux provides a rich array of features, enabling each feature
+ * however increases the size of the kernel and there are many
+ * features which users often want disabled. The traditional
+ * solution to this problem is for each feature to have its own
+ * Kconfig symbol, followed by a series of #ifdef statements
+ * in C code and header files, allowing the feature to be compiled
+ * only when desirable. As the variability of Linux increases build
+ * tests can and are often done with random kernel configurations,
+ * allyesconfig, and allmodconfig to help find code issues. This
+ * however doesn't catch all errors and as a consequence code that
+ * is typically not enabled often can suffer from bit-rot over time.
+ */
+
+/**
+ * DOC: The build-all selective-link philosophy
+ *
+ * A code architecture philosophy to help avoid code bit-rot consists
+ * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
+ * by instead having each feature implemented it its own C file, and force
+ * compilation for all features. Only features that are enabled get linked in,
+ * the forced compilation therefore has no size impact on the final result of
+ * the kernel. The practice of having each feature implemented in its own C
+ * file is already prevalent in many subsystems, however #ifdefs are still
+ * typically required during feature initialization. For instance in::
+ *
+ *	#ifdef CONFIG_FOO
+ *	foo_init();
+ *	#endif
+ *
+ * We cannot remove the #ifdef and leave foo_init() as we'd either
+ * need to always enable the feature or add a respective #ifdef in a
+ * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem with linker tables
+ *
+ * Linker tables can be used to further help avoid the code bit-rot problem
+ * when embracing the 'build-all selective-link philosophy' by lifting the
+ * requirement to use of #ifdefs during initialization. With linker tables
+ * initialization sequences can be aggregated into a custom ELF section at
+ * link time, during run time the table can be iterated over and each init
+ * sequence enabled can be called. A feature's init routine is only added to a
+ * table when its respective Kconfig symbols has been enabled and therefore
+ * linked in. Linker tables enable subsystems to completely do away with
+ * #ifdefs if one is comfortable in accepting all subsystem's feature's
+ * structural size implications.
+ *
+ * To further help with this the Linux build system supports two special
+ * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
+ * follow the 'build-all selective-link philosophy' can use these targets for a
+ * feature's kconfig symbol. Using these targets will always require
+ * compilation of the kconfig's objects if the kconfig symbol's dependencies
+ * are met but only link the objects into the kernel, and therefore enable the
+ * feature, if and only if the kconfig symbol has been enabled.
+ *
+ * Not all users or build systems may want to opt-in to compile all objects
+ * following the 'build-all selective-link philosophy', as such the targets
+ * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
+ * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
+ * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
+ * ``obj-y`` and ``lib-y`` respectively.
+ *
+ * Example use::
+ *
+ * 	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+ */
+
+/**
  * DOC: Linker table module support
  *
  * Modules can use linker tables, however the linker table definition
diff --git a/init/Kconfig b/init/Kconfig
index 223b734abccd..2faf4eee4c70 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -63,6 +63,28 @@ config CROSS_COMPILE
 	  need to set this unless you want the configured kernel build
 	  directory to select the cross-compiler automatically.
 
+config BUILD_AVOID_BITROT
+	bool "Enable force building of force-obj-y and force-lib-y"
+	default n
+	help
+	  When enabled objects under the force-obj-y and force-lib-y targets
+	  using a Kconfig symbol will be forced to compile if the Kconfig
+	  symbol's dependencies are met but only linked into the kernel if
+	  the Kconfig symbol is enabled. If a Kconfig symbol on a force-obj-y
+	  or force-lib-y target is disabled, it will be compiled but not linked
+	  into the kernel.
+
+	  The force-obj-y and force-lib-y targets can be used by subsystems
+	  which wish to want to follow the 'build-all selective-link philosophy'
+	  documented under include/linux/tables.h.
+
+	  Say Y if you have a decent build machine and would like to help test
+	  building code for more subsystems. Say N if you do you not have a
+	  good build machine or only want to compile what you've enabled for
+	  your kernel.
+
+	  Enabling this option never increases the size of your kernel.
+
 config COMPILE_TEST
 	bool "Compile also drivers which will not load"
 	depends on !UML
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index eadcd4d359d9..c34af839d47c 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -92,7 +92,8 @@ modorder-target := $(obj)/modules.order
 
 # We keep a list of all modules in $(MODVERDIR)
 
-__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
+__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y) \
+				$(force-obj-y)) \
 	 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
 	 $(subdir-ym) $(always)
 	@:
@@ -392,8 +393,8 @@ endif
 $(obj)/%.o: $(src)/%.S $(objtool_obj) FORCE
 	$(call if_changed_rule,as_o_S)
 
-targets += $(real-objs-y) $(real-objs-m) $(lib-y)
-targets += $(extra-y) $(MAKECMDGOALS) $(always)
+targets += $(real-objs-y) $(real-objs-m) $(lib-y) $(force-lib-y)
+targets += $(extra-y) $(force-obj-y) $(MAKECMDGOALS) $(always)
 
 # Linker scripts preprocessor (.lds.S -> .lds)
 # ---------------------------------------------------------------------------
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-) \
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 0a07f9014944..d1cb0cfdf1bf 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -12,6 +12,15 @@ export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y)
 # Figure out what we need to build from the various variables
 # ===================================== 
+ifeq ($(CONFIG_BUILD_AVOID_BITROT),y)
+extra-y += $(force-obj-) $(force-lib-)
+endif
+
+obj-m += $(force-obj-m)
+obj-y += $(force-obj-y)
+lib-m += $(force-lib-m)
+lib-y += $(force-lib-y)
+
 # When an object is listed to be built compiled-in and modular,
 # only build the compiled-in version
 
@@ -72,6 +81,8 @@ real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)
 # Add subdir path
 
 extra-y		:= $(addprefix $(obj)/,$(extra-y))
+force-obj-y		:= $(addprefix $(obj)/,$(force-obj-y))
+force-obj-m		:= $(addprefix $(obj)/,$(force-obj-m))
 always		:= $(addprefix $(obj)/,$(always))
 targets		:= $(addprefix $(obj)/,$(targets))
 modorder	:= $(addprefix $(obj)/,$(modorder))
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 05/14] kbuild: enable option to force compile force-obj-y and force-lib-y
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Linux provides a rich array of features, enabling each feature
however increases the size of the kernel and there are many
features which users often want disabled. The traditional
solution to this problem is for each feature to have its own
Kconfig symbol, followed by a series of #ifdef statements
in C code and header files, allowing the feature to be compiled
only when desirable. As the variability of Linux increases build
tests can and are often done with random kernel configurations,
allyesconfig, and allmodconfig to help find code issues. This
however doesn't catch all errors and as a consequence code that
is typically not enabled often can suffer from bit-rot over time.

An alternative approach for subsystems, which refer to as the 'build-all
link-selectively philosophy' is to keep the Kconfig symbols, replace
the #ifdef approach by having each feature implemented it its own C file,
and force compilation for all features to avoid the code bit-rot problem.
With this strategy only features that are enabled via Kconfig get
linked into the kernel, so the forced compilation has no size impact
on the kernel. The practice of having each feature implemented in its own
C file is already prevalent in many subsystems, however #ifdefs are still
typically required during feature initialization. For instance in:

  #ifdef CONFIG_FOO
  foo_init();
  #endif

We cannot remove the #ifdef and leave foo_init() as we'd either
need to always enable the feature or add a respective #ifdef in a
foo.h which makes foo_init() do nothing when CONFIG_FOO is disabled.

Linker tables enable lifting the requirement to use of #ifdefs during
initialization. With linker tables initialization sequences can instead
be aggregated into a custom ELF section at link time, during run time
the table can be iterated over and each init sequence enabled can be called.
A feature's init routine is only added to a table when its respective
Kconfig symbols has been enabled and therefore linked in. Linker tables
enable subsystems to completely do away with #ifdefs if one is comfortable
in accepting all subsystem's feature's structural size implications.

Subsystems which want to follow the 'build-all link-selectively
philosophy' still need a way to easily express and annotate that they
wish for all code to always be compiled to help avoid code bit rot,
as such two new targets force-obj-y and force-lib-y are provided to
help with this. Its not fair to require everyone to force compilation
of all features of a subsystem though, so as a compromise, the new
targets only force compilation when CONFIG_BUILD_AVOID_BITROT is
enabled.

Only built-in features are supported at the moment. Module support
is expected to be added after a generic solution to add linker
tables to modules more easily is developed.

v4: this patch was added to this series, it was split off from the
    linker tables addition due to the confusion over the code bit
    rot alternatives that are possible with linker tables.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/kbuild/makefiles.txt       | 36 ++++++++++++++++
 Documentation/sections/linker-tables.rst | 15 +++++++
 include/linux/tables.h                   | 71 ++++++++++++++++++++++++++++++++
 init/Kconfig                             | 22 ++++++++++
 scripts/Makefile.build                   |  7 ++--
 scripts/Makefile.clean                   |  2 +
 scripts/Makefile.lib                     | 11 +++++
 7 files changed, 161 insertions(+), 3 deletions(-)

diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 9b9c4797fc55..1af275cd4879 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -1090,6 +1090,42 @@ When kbuild executes, the following steps are followed (roughly):
 	In this example, extra-y is used to list object files that
 	shall be built, but shall not be linked as part of built-in.o.
 
+    force-obj-y force-lib-y
+
+	When CONFIG_BUILD_AVOID_BITROT is enabled using these targets for your
+	kconfig symbols forces compilation of the associated objects if the
+	kconfig's symbol's dependencies are met, the objects however are only
+	linked into to the kernel if and only if the kconfig symbol was
+	enabled. If CONFIG_BUILD_AVOID_BITROT is disabled the force-obj-y and
+	force-lib-y targets are functionally equilvalent to obj-y and lib-y
+	respectively.
+
+	Using force-obj-y and force-lib-y are part of a code architecture and
+	build philosophy further enabled by linker tables, for more details
+	refer to the documention in include/linux/tables.h, refer to the
+	sections:
+
+		o The code bit-rot problem
+		o The build-all selective-link philosophy
+		o Avoiding the code bit-rot problem with linker tables
+		o Linker table module support
+
+	Modules support is expected to be enhanced in the future, so for now
+	only built-in features are supported.
+
+	Example use:
+
+		force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	An alternative to using force-obj-y, is to use extra-y followed by the
+	respective obj-y:
+
+		extra-y += foo.o
+		obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	Using force-obj-y and force-lib-y can be used to help annotate the
+	targets follow the 'build-all selective-link philosophy' further
+	enabled by linker tables.
 
 --- 6.7 Commands useful for building a boot image
 
diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index 71704159e90e..a80f4dd94659 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -30,6 +30,21 @@ How linker tables simplify initialization code
 .. kernel-doc:: include/linux/tables.h
    :doc: How linker tables simplify initialization code
 
+The code bit-rot problem
+------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The code bit-rot problem
+
+The build-all selective-link philosophy
+---------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The build-all selective-link philosophy
+
+Avoiding the code bit-rot problem with linker tables
+----------------------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: Avoiding the code bit-rot problem with linker tables
+
 Using linker tables in Linux
 ============================
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
index cc8fb1dcee47..fdadf794b63e 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -169,6 +169,77 @@
  */
 
 /**
+ * DOC: The code bit-rot problem
+ *
+ * Linux provides a rich array of features, enabling each feature
+ * however increases the size of the kernel and there are many
+ * features which users often want disabled. The traditional
+ * solution to this problem is for each feature to have its own
+ * Kconfig symbol, followed by a series of #ifdef statements
+ * in C code and header files, allowing the feature to be compiled
+ * only when desirable. As the variability of Linux increases build
+ * tests can and are often done with random kernel configurations,
+ * allyesconfig, and allmodconfig to help find code issues. This
+ * however doesn't catch all errors and as a consequence code that
+ * is typically not enabled often can suffer from bit-rot over time.
+ */
+
+/**
+ * DOC: The build-all selective-link philosophy
+ *
+ * A code architecture philosophy to help avoid code bit-rot consists
+ * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
+ * by instead having each feature implemented it its own C file, and force
+ * compilation for all features. Only features that are enabled get linked in,
+ * the forced compilation therefore has no size impact on the final result of
+ * the kernel. The practice of having each feature implemented in its own C
+ * file is already prevalent in many subsystems, however #ifdefs are still
+ * typically required during feature initialization. For instance in::
+ *
+ *	#ifdef CONFIG_FOO
+ *	foo_init();
+ *	#endif
+ *
+ * We cannot remove the #ifdef and leave foo_init() as we'd either
+ * need to always enable the feature or add a respective #ifdef in a
+ * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem with linker tables
+ *
+ * Linker tables can be used to further help avoid the code bit-rot problem
+ * when embracing the 'build-all selective-link philosophy' by lifting the
+ * requirement to use of #ifdefs during initialization. With linker tables
+ * initialization sequences can be aggregated into a custom ELF section at
+ * link time, during run time the table can be iterated over and each init
+ * sequence enabled can be called. A feature's init routine is only added to a
+ * table when its respective Kconfig symbols has been enabled and therefore
+ * linked in. Linker tables enable subsystems to completely do away with
+ * #ifdefs if one is comfortable in accepting all subsystem's feature's
+ * structural size implications.
+ *
+ * To further help with this the Linux build system supports two special
+ * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
+ * follow the 'build-all selective-link philosophy' can use these targets for a
+ * feature's kconfig symbol. Using these targets will always require
+ * compilation of the kconfig's objects if the kconfig symbol's dependencies
+ * are met but only link the objects into the kernel, and therefore enable the
+ * feature, if and only if the kconfig symbol has been enabled.
+ *
+ * Not all users or build systems may want to opt-in to compile all objects
+ * following the 'build-all selective-link philosophy', as such the targets
+ * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
+ * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
+ * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
+ * ``obj-y`` and ``lib-y`` respectively.
+ *
+ * Example use::
+ *
+ * 	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+ */
+
+/**
  * DOC: Linker table module support
  *
  * Modules can use linker tables, however the linker table definition
diff --git a/init/Kconfig b/init/Kconfig
index 223b734abccd..2faf4eee4c70 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -63,6 +63,28 @@ config CROSS_COMPILE
 	  need to set this unless you want the configured kernel build
 	  directory to select the cross-compiler automatically.
 
+config BUILD_AVOID_BITROT
+	bool "Enable force building of force-obj-y and force-lib-y"
+	default n
+	help
+	  When enabled objects under the force-obj-y and force-lib-y targets
+	  using a Kconfig symbol will be forced to compile if the Kconfig
+	  symbol's dependencies are met but only linked into the kernel if
+	  the Kconfig symbol is enabled. If a Kconfig symbol on a force-obj-y
+	  or force-lib-y target is disabled, it will be compiled but not linked
+	  into the kernel.
+
+	  The force-obj-y and force-lib-y targets can be used by subsystems
+	  which wish to want to follow the 'build-all selective-link philosophy'
+	  documented under include/linux/tables.h.
+
+	  Say Y if you have a decent build machine and would like to help test
+	  building code for more subsystems. Say N if you do you not have a
+	  good build machine or only want to compile what you've enabled for
+	  your kernel.
+
+	  Enabling this option never increases the size of your kernel.
+
 config COMPILE_TEST
 	bool "Compile also drivers which will not load"
 	depends on !UML
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index eadcd4d359d9..c34af839d47c 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -92,7 +92,8 @@ modorder-target := $(obj)/modules.order
 
 # We keep a list of all modules in $(MODVERDIR)
 
-__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
+__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y) \
+				$(force-obj-y)) \
 	 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
 	 $(subdir-ym) $(always)
 	@:
@@ -392,8 +393,8 @@ endif
 $(obj)/%.o: $(src)/%.S $(objtool_obj) FORCE
 	$(call if_changed_rule,as_o_S)
 
-targets += $(real-objs-y) $(real-objs-m) $(lib-y)
-targets += $(extra-y) $(MAKECMDGOALS) $(always)
+targets += $(real-objs-y) $(real-objs-m) $(lib-y) $(force-lib-y)
+targets += $(extra-y) $(force-obj-y) $(MAKECMDGOALS) $(always)
 
 # Linker scripts preprocessor (.lds.S -> .lds)
 # ---------------------------------------------------------------------------
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-) \
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 0a07f9014944..d1cb0cfdf1bf 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -12,6 +12,15 @@ export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y)
 # Figure out what we need to build from the various variables
 # ===========================================================================
 
+ifeq ($(CONFIG_BUILD_AVOID_BITROT),y)
+extra-y += $(force-obj-) $(force-lib-)
+endif
+
+obj-m += $(force-obj-m)
+obj-y += $(force-obj-y)
+lib-m += $(force-lib-m)
+lib-y += $(force-lib-y)
+
 # When an object is listed to be built compiled-in and modular,
 # only build the compiled-in version
 
@@ -72,6 +81,8 @@ real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)
 # Add subdir path
 
 extra-y		:= $(addprefix $(obj)/,$(extra-y))
+force-obj-y		:= $(addprefix $(obj)/,$(force-obj-y))
+force-obj-m		:= $(addprefix $(obj)/,$(force-obj-m))
 always		:= $(addprefix $(obj)/,$(always))
 targets		:= $(addprefix $(obj)/,$(targets))
 modorder	:= $(addprefix $(obj)/,$(modorder))
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 05/14] kbuild: enable option to force compile force-obj-y and force-lib-y
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

Linux provides a rich array of features, enabling each feature
however increases the size of the kernel and there are many
features which users often want disabled. The traditional
solution to this problem is for each feature to have its own
Kconfig symbol, followed by a series of #ifdef statements
in C code and header files, allowing the feature to be compiled
only when desirable. As the variability of Linux increases build
tests can and are often done with random kernel configurations,
allyesconfig, and allmodconfig to help find code issues. This
however doesn't catch all errors and as a consequence code that
is typically not enabled often can suffer from bit-rot over time.

An alternative approach for subsystems, which refer to as the 'build-all
link-selectively philosophy' is to keep the Kconfig symbols, replace
the #ifdef approach by having each feature implemented it its own C file,
and force compilation for all features to avoid the code bit-rot problem.
With this strategy only features that are enabled via Kconfig get
linked into the kernel, so the forced compilation has no size impact
on the kernel. The practice of having each feature implemented in its own
C file is already prevalent in many subsystems, however #ifdefs are still
typically required during feature initialization. For instance in:

  #ifdef CONFIG_FOO
  foo_init();
  #endif

We cannot remove the #ifdef and leave foo_init() as we'd either
need to always enable the feature or add a respective #ifdef in a
foo.h which makes foo_init() do nothing when CONFIG_FOO is disabled.

Linker tables enable lifting the requirement to use of #ifdefs during
initialization. With linker tables initialization sequences can instead
be aggregated into a custom ELF section at link time, during run time
the table can be iterated over and each init sequence enabled can be called.
A feature's init routine is only added to a table when its respective
Kconfig symbols has been enabled and therefore linked in. Linker tables
enable subsystems to completely do away with #ifdefs if one is comfortable
in accepting all subsystem's feature's structural size implications.

Subsystems which want to follow the 'build-all link-selectively
philosophy' still need a way to easily express and annotate that they
wish for all code to always be compiled to help avoid code bit rot,
as such two new targets force-obj-y and force-lib-y are provided to
help with this. Its not fair to require everyone to force compilation
of all features of a subsystem though, so as a compromise, the new
targets only force compilation when CONFIG_BUILD_AVOID_BITROT is
enabled.

Only built-in features are supported at the moment. Module support
is expected to be added after a generic solution to add linker
tables to modules more easily is developed.

v4: this patch was added to this series, it was split off from the
    linker tables addition due to the confusion over the code bit
    rot alternatives that are possible with linker tables.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/kbuild/makefiles.txt       | 36 ++++++++++++++++
 Documentation/sections/linker-tables.rst | 15 +++++++
 include/linux/tables.h                   | 71 ++++++++++++++++++++++++++++++++
 init/Kconfig                             | 22 ++++++++++
 scripts/Makefile.build                   |  7 ++--
 scripts/Makefile.clean                   |  2 +
 scripts/Makefile.lib                     | 11 +++++
 7 files changed, 161 insertions(+), 3 deletions(-)

diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 9b9c4797fc55..1af275cd4879 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -1090,6 +1090,42 @@ When kbuild executes, the following steps are followed (roughly):
 	In this example, extra-y is used to list object files that
 	shall be built, but shall not be linked as part of built-in.o.
 
+    force-obj-y force-lib-y
+
+	When CONFIG_BUILD_AVOID_BITROT is enabled using these targets for your
+	kconfig symbols forces compilation of the associated objects if the
+	kconfig's symbol's dependencies are met, the objects however are only
+	linked into to the kernel if and only if the kconfig symbol was
+	enabled. If CONFIG_BUILD_AVOID_BITROT is disabled the force-obj-y and
+	force-lib-y targets are functionally equilvalent to obj-y and lib-y
+	respectively.
+
+	Using force-obj-y and force-lib-y are part of a code architecture and
+	build philosophy further enabled by linker tables, for more details
+	refer to the documention in include/linux/tables.h, refer to the
+	sections:
+
+		o The code bit-rot problem
+		o The build-all selective-link philosophy
+		o Avoiding the code bit-rot problem with linker tables
+		o Linker table module support
+
+	Modules support is expected to be enhanced in the future, so for now
+	only built-in features are supported.
+
+	Example use:
+
+		force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	An alternative to using force-obj-y, is to use extra-y followed by the
+	respective obj-y:
+
+		extra-y += foo.o
+		obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	Using force-obj-y and force-lib-y can be used to help annotate the
+	targets follow the 'build-all selective-link philosophy' further
+	enabled by linker tables.
 
 --- 6.7 Commands useful for building a boot image
 
diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index 71704159e90e..a80f4dd94659 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -30,6 +30,21 @@ How linker tables simplify initialization code
 .. kernel-doc:: include/linux/tables.h
    :doc: How linker tables simplify initialization code
 
+The code bit-rot problem
+------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The code bit-rot problem
+
+The build-all selective-link philosophy
+---------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The build-all selective-link philosophy
+
+Avoiding the code bit-rot problem with linker tables
+----------------------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: Avoiding the code bit-rot problem with linker tables
+
 Using linker tables in Linux
 ============================
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
index cc8fb1dcee47..fdadf794b63e 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -169,6 +169,77 @@
  */
 
 /**
+ * DOC: The code bit-rot problem
+ *
+ * Linux provides a rich array of features, enabling each feature
+ * however increases the size of the kernel and there are many
+ * features which users often want disabled. The traditional
+ * solution to this problem is for each feature to have its own
+ * Kconfig symbol, followed by a series of #ifdef statements
+ * in C code and header files, allowing the feature to be compiled
+ * only when desirable. As the variability of Linux increases build
+ * tests can and are often done with random kernel configurations,
+ * allyesconfig, and allmodconfig to help find code issues. This
+ * however doesn't catch all errors and as a consequence code that
+ * is typically not enabled often can suffer from bit-rot over time.
+ */
+
+/**
+ * DOC: The build-all selective-link philosophy
+ *
+ * A code architecture philosophy to help avoid code bit-rot consists
+ * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
+ * by instead having each feature implemented it its own C file, and force
+ * compilation for all features. Only features that are enabled get linked in,
+ * the forced compilation therefore has no size impact on the final result of
+ * the kernel. The practice of having each feature implemented in its own C
+ * file is already prevalent in many subsystems, however #ifdefs are still
+ * typically required during feature initialization. For instance in::
+ *
+ *	#ifdef CONFIG_FOO
+ *	foo_init();
+ *	#endif
+ *
+ * We cannot remove the #ifdef and leave foo_init() as we'd either
+ * need to always enable the feature or add a respective #ifdef in a
+ * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem with linker tables
+ *
+ * Linker tables can be used to further help avoid the code bit-rot problem
+ * when embracing the 'build-all selective-link philosophy' by lifting the
+ * requirement to use of #ifdefs during initialization. With linker tables
+ * initialization sequences can be aggregated into a custom ELF section at
+ * link time, during run time the table can be iterated over and each init
+ * sequence enabled can be called. A feature's init routine is only added to a
+ * table when its respective Kconfig symbols has been enabled and therefore
+ * linked in. Linker tables enable subsystems to completely do away with
+ * #ifdefs if one is comfortable in accepting all subsystem's feature's
+ * structural size implications.
+ *
+ * To further help with this the Linux build system supports two special
+ * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
+ * follow the 'build-all selective-link philosophy' can use these targets for a
+ * feature's kconfig symbol. Using these targets will always require
+ * compilation of the kconfig's objects if the kconfig symbol's dependencies
+ * are met but only link the objects into the kernel, and therefore enable the
+ * feature, if and only if the kconfig symbol has been enabled.
+ *
+ * Not all users or build systems may want to opt-in to compile all objects
+ * following the 'build-all selective-link philosophy', as such the targets
+ * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
+ * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
+ * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
+ * ``obj-y`` and ``lib-y`` respectively.
+ *
+ * Example use::
+ *
+ * 	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+ */
+
+/**
  * DOC: Linker table module support
  *
  * Modules can use linker tables, however the linker table definition
diff --git a/init/Kconfig b/init/Kconfig
index 223b734abccd..2faf4eee4c70 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -63,6 +63,28 @@ config CROSS_COMPILE
 	  need to set this unless you want the configured kernel build
 	  directory to select the cross-compiler automatically.
 
+config BUILD_AVOID_BITROT
+	bool "Enable force building of force-obj-y and force-lib-y"
+	default n
+	help
+	  When enabled objects under the force-obj-y and force-lib-y targets
+	  using a Kconfig symbol will be forced to compile if the Kconfig
+	  symbol's dependencies are met but only linked into the kernel if
+	  the Kconfig symbol is enabled. If a Kconfig symbol on a force-obj-y
+	  or force-lib-y target is disabled, it will be compiled but not linked
+	  into the kernel.
+
+	  The force-obj-y and force-lib-y targets can be used by subsystems
+	  which wish to want to follow the 'build-all selective-link philosophy'
+	  documented under include/linux/tables.h.
+
+	  Say Y if you have a decent build machine and would like to help test
+	  building code for more subsystems. Say N if you do you not have a
+	  good build machine or only want to compile what you've enabled for
+	  your kernel.
+
+	  Enabling this option never increases the size of your kernel.
+
 config COMPILE_TEST
 	bool "Compile also drivers which will not load"
 	depends on !UML
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index eadcd4d359d9..c34af839d47c 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -92,7 +92,8 @@ modorder-target := $(obj)/modules.order
 
 # We keep a list of all modules in $(MODVERDIR)
 
-__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
+__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y) \
+				$(force-obj-y)) \
 	 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
 	 $(subdir-ym) $(always)
 	@:
@@ -392,8 +393,8 @@ endif
 $(obj)/%.o: $(src)/%.S $(objtool_obj) FORCE
 	$(call if_changed_rule,as_o_S)
 
-targets += $(real-objs-y) $(real-objs-m) $(lib-y)
-targets += $(extra-y) $(MAKECMDGOALS) $(always)
+targets += $(real-objs-y) $(real-objs-m) $(lib-y) $(force-lib-y)
+targets += $(extra-y) $(force-obj-y) $(MAKECMDGOALS) $(always)
 
 # Linker scripts preprocessor (.lds.S -> .lds)
 # ---------------------------------------------------------------------------
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-) \
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 0a07f9014944..d1cb0cfdf1bf 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -12,6 +12,15 @@ export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y)
 # Figure out what we need to build from the various variables
 # ===========================================================================
 
+ifeq ($(CONFIG_BUILD_AVOID_BITROT),y)
+extra-y += $(force-obj-) $(force-lib-)
+endif
+
+obj-m += $(force-obj-m)
+obj-y += $(force-obj-y)
+lib-m += $(force-lib-m)
+lib-y += $(force-lib-y)
+
 # When an object is listed to be built compiled-in and modular,
 # only build the compiled-in version
 
@@ -72,6 +81,8 @@ real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)
 # Add subdir path
 
 extra-y		:= $(addprefix $(obj)/,$(extra-y))
+force-obj-y		:= $(addprefix $(obj)/,$(force-obj-y))
+force-obj-m		:= $(addprefix $(obj)/,$(force-obj-m))
 always		:= $(addprefix $(obj)/,$(always))
 targets		:= $(addprefix $(obj)/,$(targets))
 modorder	:= $(addprefix $(obj)/,$(modorder))
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 06/14] firmware/Makefile: force recompilation if makefile changes
  2016-12-22  2:37     ` Luis R. Rodriguez
  (?)
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

If you modify the target asm we currently do not force the
recompilation of the firmware files. The target asm is in
the firmware/Makefile, peg this file as a dependency to
require re-compilation of firmware targets when the asm
changes.

v3: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 firmware/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/firmware/Makefile b/firmware/Makefile
index e297e1b52636..fa3e81c2a97b 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -176,7 +176,8 @@ quiet_cmd_fwbin = MK_FW   $@
 wordsize_deps := $(wildcard include/config/64bit.h include/config/32bit.h \
 		include/config/ppc32.h include/config/ppc64.h \
 		include/config/superh32.h include/config/superh64.h \
-		include/config/x86_32.h include/config/x86_64.h)
+		include/config/x86_32.h include/config/x86_64.h \
+		firmware/Makefile)
 
 $(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)): %: $(wordsize_deps)
 	$(call cmd,fwbin,$(patsubst %.gen.S,%,$@))
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 06/14] firmware/Makefile: force recompilation if makefile changes
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

If you modify the target asm we currently do not force the
recompilation of the firmware files. The target asm is in
the firmware/Makefile, peg this file as a dependency to
require re-compilation of firmware targets when the asm
changes.

v3: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 firmware/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/firmware/Makefile b/firmware/Makefile
index e297e1b52636..fa3e81c2a97b 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -176,7 +176,8 @@ quiet_cmd_fwbin = MK_FW   $@
 wordsize_deps := $(wildcard include/config/64bit.h include/config/32bit.h \
 		include/config/ppc32.h include/config/ppc64.h \
 		include/config/superh32.h include/config/superh64.h \
-		include/config/x86_32.h include/config/x86_64.h)
+		include/config/x86_32.h include/config/x86_64.h \
+		firmware/Makefile)
 
 $(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)): %: $(wordsize_deps)
 	$(call cmd,fwbin,$(patsubst %.gen.S,%,$@))
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 06/14] firmware/Makefile: force recompilation if makefile changes
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

If you modify the target asm we currently do not force the
recompilation of the firmware files. The target asm is in
the firmware/Makefile, peg this file as a dependency to
require re-compilation of firmware targets when the asm
changes.

v3: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 firmware/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/firmware/Makefile b/firmware/Makefile
index e297e1b52636..fa3e81c2a97b 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -176,7 +176,8 @@ quiet_cmd_fwbin = MK_FW   $@
 wordsize_deps := $(wildcard include/config/64bit.h include/config/32bit.h \
 		include/config/ppc32.h include/config/ppc64.h \
 		include/config/superh32.h include/config/superh64.h \
-		include/config/x86_32.h include/config/x86_64.h)
+		include/config/x86_32.h include/config/x86_64.h \
+		firmware/Makefile)
 
 $(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)): %: $(wordsize_deps)
 	$(call cmd,fwbin,$(patsubst %.gen.S,%,$@))
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 07/14] firmware: port built-in section to linker table
  2016-12-22  2:37     ` Luis R. Rodriguez
  (?)
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This ports built-in firmware to use linker tables,
this replaces the custom section solution with a
generic solution.

This also demos the use of the .rodata linker table.

Tested with 0 built-in firmware, 1 and 2 built-in
firmwares successfully.

v5:

o since we dropped SECTION_ORDER_ANY, use 'any' order level explicitly

v4:

o work around c6x toolchain bug by using SECTION_TBL_RO

o fix compilation on blackfin

v3:
o explicitly include tables.h as we no longer include
  tables.h from sections.h

o use new section_tbl_asmtype() helper on firmware/Makefile
  to enable having to unfold things on our own.

v2: introduced this file in this version of the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/x86/kernel/cpu/microcode/core.c |  8 ++++----
 drivers/base/firmware_class.c        | 12 ++++++------
 firmware/Makefile                    |  3 ++-
 include/asm-generic/vmlinux.lds.h    |  7 -------
 4 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index c4bb2f7169f6..09133ef2c31b 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -31,6 +31,7 @@
 #include <linux/cpu.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/tables.h>
 
 #include <asm/microcode_intel.h>
 #include <asm/cpu_device_id.h>
@@ -110,15 +111,14 @@ static bool __init check_loader_disabled_bsp(void)
 	return *res;
 }
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DECLARE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 bool get_builtin_firmware(struct cpio_data *cd, const char *name)
 {
 #ifdef CONFIG_FW_LOADER
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw) {
 		if (!strcmp(name, b_fw->name)) {
 			cd->size = b_fw->size;
 			cd->data = b_fw->data;
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 4497d263209f..94f2cf24d85d 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -31,6 +31,7 @@
 #include <linux/reboot.h>
 #include <linux/security.h>
 #include <linux/swait.h>
+#include <linux/tables.h>
 
 #include <generated/utsrelease.h>
 
@@ -44,15 +45,14 @@ MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_FW_LOADER
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DEFINE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 				    void *buf, size_t size)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw) {
 		if (strcmp(name, b_fw->name) = 0) {
 			fw->size = b_fw->size;
 			fw->data = b_fw->data;
@@ -68,9 +68,9 @@ static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 
 static bool fw_is_builtin_firmware(const struct firmware *fw)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++)
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw)
 		if (fw->data = b_fw->data)
 			return true;
 
diff --git a/firmware/Makefile b/firmware/Makefile
index fa3e81c2a97b..9c8cae144ede 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -155,6 +155,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  ASM_ALIGN=$(if $(CONFIG_64BIT),3,2);			     \
 		  PROGBITS=$(if $(CONFIG_ARM),%,@)progbits;		     \
 		  echo "/* Generated by firmware/Makefile */"		> $@;\
+		  echo "\#include <asm/tables.h>"			>>$@;\
 		  echo "    .section .rodata"				>>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_bin:"				>>$@;\
@@ -164,7 +165,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_name:"				>>$@;\
 		  echo "    .string \"$$FWNAME\""			>>$@;\
-		  echo "    .section .builtin_fw,\"a\",$${PROGBITS}"	>>$@;\
+		  echo "    set_section_tbl_type(SECTION_TBL_RO, builtin_fw, any, a,$${PROGBITS})" >>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_name"		>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_bin"		>>$@;\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index ce1e9a310ada..8a5325d75932 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -324,13 +324,6 @@
 		VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .;	\
 	}								\
 									\
-	/* Built-in firmware blobs */					\
-	.builtin_fw        : AT(ADDR(.builtin_fw) - LOAD_OFFSET) {	\
-		VMLINUX_SYMBOL(__start_builtin_fw) = .;			\
-		KEEP(*(.builtin_fw))					\
-		VMLINUX_SYMBOL(__end_builtin_fw) = .;			\
-	}								\
-									\
 	TRACEDATA							\
 									\
 	/* Kernel symbol table: Normal symbols */			\
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 07/14] firmware: port built-in section to linker table
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This ports built-in firmware to use linker tables,
this replaces the custom section solution with a
generic solution.

This also demos the use of the .rodata linker table.

Tested with 0 built-in firmware, 1 and 2 built-in
firmwares successfully.

v5:

o since we dropped SECTION_ORDER_ANY, use 'any' order level explicitly

v4:

o work around c6x toolchain bug by using SECTION_TBL_RO

o fix compilation on blackfin

v3:
o explicitly include tables.h as we no longer include
  tables.h from sections.h

o use new section_tbl_asmtype() helper on firmware/Makefile
  to enable having to unfold things on our own.

v2: introduced this file in this version of the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/x86/kernel/cpu/microcode/core.c |  8 ++++----
 drivers/base/firmware_class.c        | 12 ++++++------
 firmware/Makefile                    |  3 ++-
 include/asm-generic/vmlinux.lds.h    |  7 -------
 4 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index c4bb2f7169f6..09133ef2c31b 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -31,6 +31,7 @@
 #include <linux/cpu.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/tables.h>
 
 #include <asm/microcode_intel.h>
 #include <asm/cpu_device_id.h>
@@ -110,15 +111,14 @@ static bool __init check_loader_disabled_bsp(void)
 	return *res;
 }
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DECLARE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 bool get_builtin_firmware(struct cpio_data *cd, const char *name)
 {
 #ifdef CONFIG_FW_LOADER
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw) {
 		if (!strcmp(name, b_fw->name)) {
 			cd->size = b_fw->size;
 			cd->data = b_fw->data;
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 4497d263209f..94f2cf24d85d 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -31,6 +31,7 @@
 #include <linux/reboot.h>
 #include <linux/security.h>
 #include <linux/swait.h>
+#include <linux/tables.h>
 
 #include <generated/utsrelease.h>
 
@@ -44,15 +45,14 @@ MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_FW_LOADER
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DEFINE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 				    void *buf, size_t size)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw) {
 		if (strcmp(name, b_fw->name) == 0) {
 			fw->size = b_fw->size;
 			fw->data = b_fw->data;
@@ -68,9 +68,9 @@ static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 
 static bool fw_is_builtin_firmware(const struct firmware *fw)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++)
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw)
 		if (fw->data == b_fw->data)
 			return true;
 
diff --git a/firmware/Makefile b/firmware/Makefile
index fa3e81c2a97b..9c8cae144ede 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -155,6 +155,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  ASM_ALIGN=$(if $(CONFIG_64BIT),3,2);			     \
 		  PROGBITS=$(if $(CONFIG_ARM),%,@)progbits;		     \
 		  echo "/* Generated by firmware/Makefile */"		> $@;\
+		  echo "\#include <asm/tables.h>"			>>$@;\
 		  echo "    .section .rodata"				>>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_bin:"				>>$@;\
@@ -164,7 +165,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_name:"				>>$@;\
 		  echo "    .string \"$$FWNAME\""			>>$@;\
-		  echo "    .section .builtin_fw,\"a\",$${PROGBITS}"	>>$@;\
+		  echo "    set_section_tbl_type(SECTION_TBL_RO, builtin_fw, any, a,$${PROGBITS})" >>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_name"		>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_bin"		>>$@;\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index ce1e9a310ada..8a5325d75932 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -324,13 +324,6 @@
 		VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .;	\
 	}								\
 									\
-	/* Built-in firmware blobs */					\
-	.builtin_fw        : AT(ADDR(.builtin_fw) - LOAD_OFFSET) {	\
-		VMLINUX_SYMBOL(__start_builtin_fw) = .;			\
-		KEEP(*(.builtin_fw))					\
-		VMLINUX_SYMBOL(__end_builtin_fw) = .;			\
-	}								\
-									\
 	TRACEDATA							\
 									\
 	/* Kernel symbol table: Normal symbols */			\
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 07/14] firmware: port built-in section to linker table
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez, Barry Song, Mike Frysinger, Michael Matz,
	Fengguang Wu

This ports built-in firmware to use linker tables,
this replaces the custom section solution with a
generic solution.

This also demos the use of the .rodata linker table.

Tested with 0 built-in firmware, 1 and 2 built-in
firmwares successfully.

v5:

o since we dropped SECTION_ORDER_ANY, use 'any' order level explicitly

v4:

o work around c6x toolchain bug by using SECTION_TBL_RO

o fix compilation on blackfin

v3:
o explicitly include tables.h as we no longer include
  tables.h from sections.h

o use new section_tbl_asmtype() helper on firmware/Makefile
  to enable having to unfold things on our own.

v2: introduced this file in this version of the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/x86/kernel/cpu/microcode/core.c |  8 ++++----
 drivers/base/firmware_class.c        | 12 ++++++------
 firmware/Makefile                    |  3 ++-
 include/asm-generic/vmlinux.lds.h    |  7 -------
 4 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index c4bb2f7169f6..09133ef2c31b 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -31,6 +31,7 @@
 #include <linux/cpu.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/tables.h>
 
 #include <asm/microcode_intel.h>
 #include <asm/cpu_device_id.h>
@@ -110,15 +111,14 @@ static bool __init check_loader_disabled_bsp(void)
 	return *res;
 }
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DECLARE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 bool get_builtin_firmware(struct cpio_data *cd, const char *name)
 {
 #ifdef CONFIG_FW_LOADER
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw) {
 		if (!strcmp(name, b_fw->name)) {
 			cd->size = b_fw->size;
 			cd->data = b_fw->data;
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 4497d263209f..94f2cf24d85d 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -31,6 +31,7 @@
 #include <linux/reboot.h>
 #include <linux/security.h>
 #include <linux/swait.h>
+#include <linux/tables.h>
 
 #include <generated/utsrelease.h>
 
@@ -44,15 +45,14 @@ MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_FW_LOADER
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DEFINE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 				    void *buf, size_t size)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw) {
 		if (strcmp(name, b_fw->name) == 0) {
 			fw->size = b_fw->size;
 			fw->data = b_fw->data;
@@ -68,9 +68,9 @@ static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 
 static bool fw_is_builtin_firmware(const struct firmware *fw)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++)
+	LINKTABLE_FOR_EACH(b_fw, builtin_fw)
 		if (fw->data == b_fw->data)
 			return true;
 
diff --git a/firmware/Makefile b/firmware/Makefile
index fa3e81c2a97b..9c8cae144ede 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -155,6 +155,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  ASM_ALIGN=$(if $(CONFIG_64BIT),3,2);			     \
 		  PROGBITS=$(if $(CONFIG_ARM),%,@)progbits;		     \
 		  echo "/* Generated by firmware/Makefile */"		> $@;\
+		  echo "\#include <asm/tables.h>"			>>$@;\
 		  echo "    .section .rodata"				>>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_bin:"				>>$@;\
@@ -164,7 +165,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_name:"				>>$@;\
 		  echo "    .string \"$$FWNAME\""			>>$@;\
-		  echo "    .section .builtin_fw,\"a\",$${PROGBITS}"	>>$@;\
+		  echo "    set_section_tbl_type(SECTION_TBL_RO, builtin_fw, any, a,$${PROGBITS})" >>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_name"		>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_bin"		>>$@;\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index ce1e9a310ada..8a5325d75932 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -324,13 +324,6 @@
 		VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .;	\
 	}								\
 									\
-	/* Built-in firmware blobs */					\
-	.builtin_fw        : AT(ADDR(.builtin_fw) - LOAD_OFFSET) {	\
-		VMLINUX_SYMBOL(__start_builtin_fw) = .;			\
-		KEEP(*(.builtin_fw))					\
-		VMLINUX_SYMBOL(__end_builtin_fw) = .;			\
-	}								\
-									\
 	TRACEDATA							\
 									\
 	/* Kernel symbol table: Normal symbols */			\
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 08/14] jump_label: move guard #endif down where it belongs
  2016-12-22  2:37     ` Luis R. Rodriguez
  (?)
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

The ending header guard is misplaced. This has no
functional change, this is just an eye-sore.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/linux/jump_label.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index a0547c571800..b63d6b7b0db0 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -402,6 +402,6 @@ extern bool ____wrong_branch_error(void);
 #define static_branch_enable(x)		static_key_enable(&(x)->key)
 #define static_branch_disable(x)	static_key_disable(&(x)->key)
 
-#endif	/* _LINUX_JUMP_LABEL_H */
-
 #endif /* __ASSEMBLY__ */
+
+#endif	/* _LINUX_JUMP_LABEL_H */
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 08/14] jump_label: move guard #endif down where it belongs
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

The ending header guard is misplaced. This has no
functional change, this is just an eye-sore.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/linux/jump_label.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index a0547c571800..b63d6b7b0db0 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -402,6 +402,6 @@ extern bool ____wrong_branch_error(void);
 #define static_branch_enable(x)		static_key_enable(&(x)->key)
 #define static_branch_disable(x)	static_key_disable(&(x)->key)
 
-#endif	/* _LINUX_JUMP_LABEL_H */
-
 #endif /* __ASSEMBLY__ */
+
+#endif	/* _LINUX_JUMP_LABEL_H */
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 08/14] jump_label: move guard #endif down where it belongs
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

The ending header guard is misplaced. This has no
functional change, this is just an eye-sore.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/linux/jump_label.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index a0547c571800..b63d6b7b0db0 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -402,6 +402,6 @@ extern bool ____wrong_branch_error(void);
 #define static_branch_enable(x)		static_key_enable(&(x)->key)
 #define static_branch_disable(x)	static_key_disable(&(x)->key)
 
-#endif	/* _LINUX_JUMP_LABEL_H */
-
 #endif /* __ASSEMBLY__ */
+
+#endif	/* _LINUX_JUMP_LABEL_H */
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 09/14] jump_label: port __jump_table to linker tables
  2016-12-22  2:37     ` Luis R. Rodriguez
  (?)
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Move the __jump_table from the a custom section solution
to a generic solution, this avoiding extra vmlinux.lds.h
customizations.

This also demos the use of the .data linker table and of
the shared asm call push_section_tbl().

Built-in kernel functionality was tested with CONFIG_STATIC_KEYS_SELFTEST.
Moduler  kernel functionality was tested with CONFIG_TEST_STATIC_KEYS.
Both work as expected.

Since __jump_table sections are also supported per
module this also required expanding module-common.lds.S
to capture and fold all .data.tlb.__jump_table.* onto
the the section __jump_table -- in this case for modules
need to keep a reference in place, given the alternative
is to use DEFINE_LINKTABLE(struct jump_entry, __jump_table)
per module -- and later through macro hacks instantiate
the jump entries per module upon init. This is doable but
we'd loose out on the sorting of the table using the
linker, to sort we'd always still need to expand the
module common linker script. An alternative mechanism
is possible which would make these custom module sections
extensions dynamic without requiring manual changes, this
however is best done later through a separate evolution
once linker tables are in place.

A careful reviewer may note that some architectures use
"\n\t" to separate asm code, while others just use a new line.
Upon review last time it was deemed reasonable to for all
architectures to just use "\n", this is defined as ASM_CMD_SEP,
and if an architecture needs to override they can do so on their
architecture sections.h prior to including asm-generic/sections.h

v5:

o Use ..tbl instead of .tbl as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

o Use LINKTABLE_START() and LINKTABLE_END()

o fixed tile jump label port -- tile got jump label support as of commit
  65a792e84f25d1 ("tile/jump_label: add jump label support for TILE-Gx"),
  as such we just needed to adjust the asm to account for the new
  linker table API use. This commit was merged as of v4.5-rc1.

v4:

o Some architectures allow linker scripts to follow including header
  files, some others do not, so if you need a helper on a linker script
  you need to explicitly include it. So for instance although
  scripts/module-common.lds.S includes <asm/tables.h> and this file
  includes <asm/section-core.h>, you still need to explicitly
  include it on the linker script. This issue is present on ARM.

o as per Josh Poimboeuf open code the section table name instead
  of including the kernel section headers, the simplicity and
  independence from the kernel is preferred.

v3:

o More elaborate tests performed
o first modular support use case, module tested was
  CONFIG_TEST_STATIC_KEYS (lib/test_static_keys.ko), this
  required us to extend module-common.lds.S
o use generic push_section_tbl_any() for all architectures
o Makes use of ASM_CMD_SEP to enable architectures to override later
  if needed
o guard tables.h inclusion and table definition with __KERNEL__

v2: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arm/include/asm/jump_label.h     |  6 ++++--
 arch/arm64/include/asm/jump_label.h   |  6 ++++--
 arch/mips/include/asm/jump_label.h    |  6 ++++--
 arch/powerpc/include/asm/jump_label.h |  8 +++++---
 arch/s390/include/asm/jump_label.h    |  6 ++++--
 arch/sparc/include/asm/jump_label.h   |  6 ++++--
 arch/tile/include/asm/jump_label.h    |  5 +++--
 arch/x86/include/asm/jump_label.h     | 10 ++++++----
 include/asm-generic/vmlinux.lds.h     |  5 -----
 include/linux/jump_label.h            |  4 ++--
 kernel/jump_label.c                   | 17 ++++++++++-------
 scripts/module-common.lds             |  1 +
 tools/objtool/special.c               |  2 +-
 13 files changed, 48 insertions(+), 34 deletions(-)

diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h
index 34f7b6980d21..609e0592a942 100644
--- a/arch/arm/include/asm/jump_label.h
+++ b/arch/arm/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_ARM_JUMP_LABEL_H
 #define _ASM_ARM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(nop) "\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
@@ -26,7 +28,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(b) " %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
diff --git a/arch/arm64/include/asm/jump_label.h b/arch/arm64/include/asm/jump_label.h
index 1b5e0e843c3a..bb56ac4fafb5 100644
--- a/arch/arm64/include/asm/jump_label.h
+++ b/arch/arm64/include/asm/jump_label.h
@@ -19,6 +19,8 @@
 #ifndef __ASM_JUMP_LABEL_H
 #define __ASM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -29,7 +31,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm goto("1: nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
@@ -43,7 +45,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm goto("1: b %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
diff --git a/arch/mips/include/asm/jump_label.h b/arch/mips/include/asm/jump_label.h
index e77672539e8e..07289a1b1bcd 100644
--- a/arch/mips/include/asm/jump_label.h
+++ b/arch/mips/include/asm/jump_label.h
@@ -8,6 +8,8 @@
 #ifndef _ASM_MIPS_JUMP_LABEL_H
 #define _ASM_MIPS_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -30,7 +32,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\t" NOP_INSN "\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -44,7 +46,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\tj %l[l_yes]\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
index 9a287e0ac8b1..7a75623740d0 100644
--- a/arch/powerpc/include/asm/jump_label.h
+++ b/arch/powerpc/include/asm/jump_label.h
@@ -10,6 +10,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
 
@@ -23,7 +25,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 "nop # arch_static_branch\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -37,7 +39,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes] # arch_static_branch_jump\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -62,7 +64,7 @@ struct jump_entry {
 #else
 #define ARCH_STATIC_BRANCH(LABEL, KEY)		\
 1098:	nop;					\
-	.pushsection __jump_table, "aw";	\
+	push_section_tbl_any(.data, __jump_table, aw); \
 	FTR_ENTRY_LONG 1098b, LABEL, KEY;	\
 	.popsection
 #endif
diff --git a/arch/s390/include/asm/jump_label.h b/arch/s390/include/asm/jump_label.h
index 9be198f5ee79..58e53af49e7e 100644
--- a/arch/s390/include/asm/jump_label.h
+++ b/arch/s390/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_S390_JUMP_LABEL_H
 #define _ASM_S390_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -16,7 +18,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 0,"__stringify(JUMP_LABEL_NOP_OFFSET)"\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
@@ -30,7 +32,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 15, %l[label]\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
diff --git a/arch/sparc/include/asm/jump_label.h b/arch/sparc/include/asm/jump_label.h
index 62d0354d1727..35d3e5d31821 100644
--- a/arch/sparc/include/asm/jump_label.h
+++ b/arch/sparc/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_SPARC_JUMP_LABEL_H
 #define _ASM_SPARC_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 	asm_volatile_goto("1:\n\t"
 		 "nop\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
@@ -28,7 +30,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes]\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
diff --git a/arch/tile/include/asm/jump_label.h b/arch/tile/include/asm/jump_label.h
index cde7573f397b..9bd989daad4a 100644
--- a/arch/tile/include/asm/jump_label.h
+++ b/arch/tile/include/asm/jump_label.h
@@ -16,6 +16,7 @@
 #define _ASM_TILE_JUMP_LABEL_H
 
 #include <arch/opcode.h>
+#include <asm/tables.h>
 
 #define JUMP_LABEL_NOP_SIZE	TILE_BUNDLE_SIZE_IN_BYTES
 
@@ -24,7 +25,7 @@ static __always_inline bool arch_static_branch(struct static_key *key,
 {
 	asm_volatile_goto("1:\n\t"
 		"nop" "\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".quad 1b, %l[l_yes], %0 + %1 \n\t"
 		".popsection\n\t"
 		: :  "i" (key), "i" (branch) : : l_yes);
@@ -38,7 +39,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key,
 {
 	asm_volatile_goto("1:\n\t"
 		"j %l[l_yes]" "\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".quad 1b, %l[l_yes], %0 + %1 \n\t"
 		".popsection\n\t"
 		: :  "i" (key), "i" (branch) : : l_yes);
diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h
index adc54c12cbd1..627df4752db0 100644
--- a/arch/x86/include/asm/jump_label.h
+++ b/arch/x86/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_JUMP_LABEL_H
 #define _ASM_X86_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef HAVE_JUMP_LABEL
 /*
  * For better or for worse, if jump labels (the gcc extension) are missing,
@@ -34,7 +36,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:"
 		".byte " __stringify(STATIC_KEY_INIT_NOP) "\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -50,7 +52,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:"
 		".byte 0xe9\n\t .long %l[l_yes] - 2f\n\t"
 		"2:\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -85,7 +87,7 @@ struct jump_entry {
 	.else
 	.byte		STATIC_KEY_INIT_NOP
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(.data, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key
 	.popsection
@@ -101,7 +103,7 @@ struct jump_entry {
 	.long		\target - .Lstatic_jump_after_\@
 .Lstatic_jump_after_\@:
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(.data, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key + 1
 	.popsection
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 8a5325d75932..887d844f0406 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -216,11 +216,6 @@
 	*(.data.unlikely)						\
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
-	/* implement dynamic printk debug */				\
-	. = ALIGN(8);                                                   \
-	VMLINUX_SYMBOL(__start___jump_table) = .;                       \
-	KEEP(*(__jump_table))                                           \
-	VMLINUX_SYMBOL(__stop___jump_table) = .;                        \
 	. = ALIGN(8);							\
 	VMLINUX_SYMBOL(__start___verbose) = .;                          \
 	KEEP(*(__verbose))                                              \
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index b63d6b7b0db0..e6277888b558 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -117,6 +117,7 @@ enum jump_label_type {
 struct module;
 
 #ifdef HAVE_JUMP_LABEL
+#include <linux/tables.h>
 
 #define JUMP_TYPE_FALSE	0UL
 #define JUMP_TYPE_TRUE	1UL
@@ -132,8 +133,7 @@ static __always_inline bool static_key_true(struct static_key *key)
 	return !arch_static_branch(key, true);
 }
 
-extern struct jump_entry __start___jump_table[];
-extern struct jump_entry __stop___jump_table[];
+DECLARE_LINKTABLE(struct jump_entry, __jump_table);
 
 extern void jump_label_init(void);
 extern void jump_label_lock(void);
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 93ad6c1fb9b6..d5c1067439ab 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -15,9 +15,12 @@
 #include <linux/static_key.h>
 #include <linux/jump_label_ratelimit.h>
 #include <linux/bug.h>
+#include <linux/tables.h>
 
 #ifdef HAVE_JUMP_LABEL
 
+DEFINE_LINKTABLE(struct jump_entry, __jump_table);
+
 /* mutex to protect coming/going of the the jump_label table */
 static DEFINE_MUTEX(jump_label_mutex);
 
@@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
 
 void __init jump_label_init(void)
 {
-	struct jump_entry *iter_start = __start___jump_table;
-	struct jump_entry *iter_stop = __stop___jump_table;
 	struct static_key *key = NULL;
 	struct jump_entry *iter;
 
@@ -292,9 +293,10 @@ void __init jump_label_init(void)
 		return;
 
 	jump_label_lock();
-	jump_label_sort_entries(iter_start, iter_stop);
+	jump_label_sort_entries(LINKTABLE_START(__jump_table),
+				LINKTABLE_END(__jump_table));
 
-	for (iter = iter_start; iter < iter_stop; iter++) {
+	LINKTABLE_FOR_EACH(iter, __jump_table) {
 		struct static_key *iterk;
 
 		/* rewrite NOPs */
@@ -539,8 +541,9 @@ early_initcall(jump_label_init_module);
  */
 int jump_label_text_reserved(void *start, void *end)
 {
-	int ret = __jump_label_text_reserved(__start___jump_table,
-			__stop___jump_table, start, end);
+	int ret = __jump_label_text_reserved(LINKTABLE_START(__jump_table),
+					     LINKTABLE_END(__jump_table),
+					     start, end);
 
 	if (ret)
 		return ret;
@@ -553,7 +556,7 @@ int jump_label_text_reserved(void *start, void *end)
 
 static void jump_label_update(struct static_key *key)
 {
-	struct jump_entry *stop = __stop___jump_table;
+	struct jump_entry *stop = LINKTABLE_END(__jump_table);
 	struct jump_entry *entry = static_key_entries(key);
 #ifdef CONFIG_MODULES
 	struct module *mod;
diff --git a/scripts/module-common.lds b/scripts/module-common.lds
index 73a2c7da0e55..db0e724556c5 100644
--- a/scripts/module-common.lds
+++ b/scripts/module-common.lds
@@ -16,6 +16,7 @@ SECTIONS {
 	__kcrctab_unused	0 : { *(SORT(___kcrctab_unused+*)) }
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
+	__jump_table		0 : { *(SORT(.data..tbl.__jump_table.*)) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
diff --git a/tools/objtool/special.c b/tools/objtool/special.c
index bff8abb3a4aa..79968e118294 100644
--- a/tools/objtool/special.c
+++ b/tools/objtool/special.c
@@ -63,7 +63,7 @@ struct special_entry entries[] = {
 		.feature = ALT_FEATURE_OFFSET,
 	},
 	{
-		.sec = "__jump_table",
+		.sec = ".data..tbl.__jump_table.any",
 		.jump_or_nop = true,
 		.size = JUMP_ENTRY_SIZE,
 		.orig = JUMP_ORIG_OFFSET,
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 09/14] jump_label: port __jump_table to linker tables
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Move the __jump_table from the a custom section solution
to a generic solution, this avoiding extra vmlinux.lds.h
customizations.

This also demos the use of the .data linker table and of
the shared asm call push_section_tbl().

Built-in kernel functionality was tested with CONFIG_STATIC_KEYS_SELFTEST.
Moduler  kernel functionality was tested with CONFIG_TEST_STATIC_KEYS.
Both work as expected.

Since __jump_table sections are also supported per
module this also required expanding module-common.lds.S
to capture and fold all .data.tlb.__jump_table.* onto
the the section __jump_table -- in this case for modules
need to keep a reference in place, given the alternative
is to use DEFINE_LINKTABLE(struct jump_entry, __jump_table)
per module -- and later through macro hacks instantiate
the jump entries per module upon init. This is doable but
we'd loose out on the sorting of the table using the
linker, to sort we'd always still need to expand the
module common linker script. An alternative mechanism
is possible which would make these custom module sections
extensions dynamic without requiring manual changes, this
however is best done later through a separate evolution
once linker tables are in place.

A careful reviewer may note that some architectures use
"\n\t" to separate asm code, while others just use a new line.
Upon review last time it was deemed reasonable to for all
architectures to just use "\n", this is defined as ASM_CMD_SEP,
and if an architecture needs to override they can do so on their
architecture sections.h prior to including asm-generic/sections.h

v5:

o Use ..tbl instead of .tbl as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

o Use LINKTABLE_START() and LINKTABLE_END()

o fixed tile jump label port -- tile got jump label support as of commit
  65a792e84f25d1 ("tile/jump_label: add jump label support for TILE-Gx"),
  as such we just needed to adjust the asm to account for the new
  linker table API use. This commit was merged as of v4.5-rc1.

v4:

o Some architectures allow linker scripts to follow including header
  files, some others do not, so if you need a helper on a linker script
  you need to explicitly include it. So for instance although
  scripts/module-common.lds.S includes <asm/tables.h> and this file
  includes <asm/section-core.h>, you still need to explicitly
  include it on the linker script. This issue is present on ARM.

o as per Josh Poimboeuf open code the section table name instead
  of including the kernel section headers, the simplicity and
  independence from the kernel is preferred.

v3:

o More elaborate tests performed
o first modular support use case, module tested was
  CONFIG_TEST_STATIC_KEYS (lib/test_static_keys.ko), this
  required us to extend module-common.lds.S
o use generic push_section_tbl_any() for all architectures
o Makes use of ASM_CMD_SEP to enable architectures to override later
  if needed
o guard tables.h inclusion and table definition with __KERNEL__

v2: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arm/include/asm/jump_label.h     |  6 ++++--
 arch/arm64/include/asm/jump_label.h   |  6 ++++--
 arch/mips/include/asm/jump_label.h    |  6 ++++--
 arch/powerpc/include/asm/jump_label.h |  8 +++++---
 arch/s390/include/asm/jump_label.h    |  6 ++++--
 arch/sparc/include/asm/jump_label.h   |  6 ++++--
 arch/tile/include/asm/jump_label.h    |  5 +++--
 arch/x86/include/asm/jump_label.h     | 10 ++++++----
 include/asm-generic/vmlinux.lds.h     |  5 -----
 include/linux/jump_label.h            |  4 ++--
 kernel/jump_label.c                   | 17 ++++++++++-------
 scripts/module-common.lds             |  1 +
 tools/objtool/special.c               |  2 +-
 13 files changed, 48 insertions(+), 34 deletions(-)

diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h
index 34f7b6980d21..609e0592a942 100644
--- a/arch/arm/include/asm/jump_label.h
+++ b/arch/arm/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_ARM_JUMP_LABEL_H
 #define _ASM_ARM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(nop) "\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
@@ -26,7 +28,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(b) " %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
diff --git a/arch/arm64/include/asm/jump_label.h b/arch/arm64/include/asm/jump_label.h
index 1b5e0e843c3a..bb56ac4fafb5 100644
--- a/arch/arm64/include/asm/jump_label.h
+++ b/arch/arm64/include/asm/jump_label.h
@@ -19,6 +19,8 @@
 #ifndef __ASM_JUMP_LABEL_H
 #define __ASM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -29,7 +31,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm goto("1: nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
@@ -43,7 +45,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm goto("1: b %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
diff --git a/arch/mips/include/asm/jump_label.h b/arch/mips/include/asm/jump_label.h
index e77672539e8e..07289a1b1bcd 100644
--- a/arch/mips/include/asm/jump_label.h
+++ b/arch/mips/include/asm/jump_label.h
@@ -8,6 +8,8 @@
 #ifndef _ASM_MIPS_JUMP_LABEL_H
 #define _ASM_MIPS_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -30,7 +32,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\t" NOP_INSN "\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -44,7 +46,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\tj %l[l_yes]\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
index 9a287e0ac8b1..7a75623740d0 100644
--- a/arch/powerpc/include/asm/jump_label.h
+++ b/arch/powerpc/include/asm/jump_label.h
@@ -10,6 +10,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
 
@@ -23,7 +25,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 "nop # arch_static_branch\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -37,7 +39,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes] # arch_static_branch_jump\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -62,7 +64,7 @@ struct jump_entry {
 #else
 #define ARCH_STATIC_BRANCH(LABEL, KEY)		\
 1098:	nop;					\
-	.pushsection __jump_table, "aw";	\
+	push_section_tbl_any(.data, __jump_table, aw); \
 	FTR_ENTRY_LONG 1098b, LABEL, KEY;	\
 	.popsection
 #endif
diff --git a/arch/s390/include/asm/jump_label.h b/arch/s390/include/asm/jump_label.h
index 9be198f5ee79..58e53af49e7e 100644
--- a/arch/s390/include/asm/jump_label.h
+++ b/arch/s390/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_S390_JUMP_LABEL_H
 #define _ASM_S390_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -16,7 +18,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 0,"__stringify(JUMP_LABEL_NOP_OFFSET)"\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
@@ -30,7 +32,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 15, %l[label]\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
diff --git a/arch/sparc/include/asm/jump_label.h b/arch/sparc/include/asm/jump_label.h
index 62d0354d1727..35d3e5d31821 100644
--- a/arch/sparc/include/asm/jump_label.h
+++ b/arch/sparc/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_SPARC_JUMP_LABEL_H
 #define _ASM_SPARC_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 	asm_volatile_goto("1:\n\t"
 		 "nop\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
@@ -28,7 +30,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes]\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
diff --git a/arch/tile/include/asm/jump_label.h b/arch/tile/include/asm/jump_label.h
index cde7573f397b..9bd989daad4a 100644
--- a/arch/tile/include/asm/jump_label.h
+++ b/arch/tile/include/asm/jump_label.h
@@ -16,6 +16,7 @@
 #define _ASM_TILE_JUMP_LABEL_H
 
 #include <arch/opcode.h>
+#include <asm/tables.h>
 
 #define JUMP_LABEL_NOP_SIZE	TILE_BUNDLE_SIZE_IN_BYTES
 
@@ -24,7 +25,7 @@ static __always_inline bool arch_static_branch(struct static_key *key,
 {
 	asm_volatile_goto("1:\n\t"
 		"nop" "\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".quad 1b, %l[l_yes], %0 + %1 \n\t"
 		".popsection\n\t"
 		: :  "i" (key), "i" (branch) : : l_yes);
@@ -38,7 +39,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key,
 {
 	asm_volatile_goto("1:\n\t"
 		"j %l[l_yes]" "\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".quad 1b, %l[l_yes], %0 + %1 \n\t"
 		".popsection\n\t"
 		: :  "i" (key), "i" (branch) : : l_yes);
diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h
index adc54c12cbd1..627df4752db0 100644
--- a/arch/x86/include/asm/jump_label.h
+++ b/arch/x86/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_JUMP_LABEL_H
 #define _ASM_X86_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef HAVE_JUMP_LABEL
 /*
  * For better or for worse, if jump labels (the gcc extension) are missing,
@@ -34,7 +36,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:"
 		".byte " __stringify(STATIC_KEY_INIT_NOP) "\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -50,7 +52,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:"
 		".byte 0xe9\n\t .long %l[l_yes] - 2f\n\t"
 		"2:\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -85,7 +87,7 @@ struct jump_entry {
 	.else
 	.byte		STATIC_KEY_INIT_NOP
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(.data, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key
 	.popsection
@@ -101,7 +103,7 @@ struct jump_entry {
 	.long		\target - .Lstatic_jump_after_\@
 .Lstatic_jump_after_\@:
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(.data, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key + 1
 	.popsection
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 8a5325d75932..887d844f0406 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -216,11 +216,6 @@
 	*(.data.unlikely)						\
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
-	/* implement dynamic printk debug */				\
-	. = ALIGN(8);                                                   \
-	VMLINUX_SYMBOL(__start___jump_table) = .;                       \
-	KEEP(*(__jump_table))                                           \
-	VMLINUX_SYMBOL(__stop___jump_table) = .;                        \
 	. = ALIGN(8);							\
 	VMLINUX_SYMBOL(__start___verbose) = .;                          \
 	KEEP(*(__verbose))                                              \
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index b63d6b7b0db0..e6277888b558 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -117,6 +117,7 @@ enum jump_label_type {
 struct module;
 
 #ifdef HAVE_JUMP_LABEL
+#include <linux/tables.h>
 
 #define JUMP_TYPE_FALSE	0UL
 #define JUMP_TYPE_TRUE	1UL
@@ -132,8 +133,7 @@ static __always_inline bool static_key_true(struct static_key *key)
 	return !arch_static_branch(key, true);
 }
 
-extern struct jump_entry __start___jump_table[];
-extern struct jump_entry __stop___jump_table[];
+DECLARE_LINKTABLE(struct jump_entry, __jump_table);
 
 extern void jump_label_init(void);
 extern void jump_label_lock(void);
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 93ad6c1fb9b6..d5c1067439ab 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -15,9 +15,12 @@
 #include <linux/static_key.h>
 #include <linux/jump_label_ratelimit.h>
 #include <linux/bug.h>
+#include <linux/tables.h>
 
 #ifdef HAVE_JUMP_LABEL
 
+DEFINE_LINKTABLE(struct jump_entry, __jump_table);
+
 /* mutex to protect coming/going of the the jump_label table */
 static DEFINE_MUTEX(jump_label_mutex);
 
@@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
 
 void __init jump_label_init(void)
 {
-	struct jump_entry *iter_start = __start___jump_table;
-	struct jump_entry *iter_stop = __stop___jump_table;
 	struct static_key *key = NULL;
 	struct jump_entry *iter;
 
@@ -292,9 +293,10 @@ void __init jump_label_init(void)
 		return;
 
 	jump_label_lock();
-	jump_label_sort_entries(iter_start, iter_stop);
+	jump_label_sort_entries(LINKTABLE_START(__jump_table),
+				LINKTABLE_END(__jump_table));
 
-	for (iter = iter_start; iter < iter_stop; iter++) {
+	LINKTABLE_FOR_EACH(iter, __jump_table) {
 		struct static_key *iterk;
 
 		/* rewrite NOPs */
@@ -539,8 +541,9 @@ early_initcall(jump_label_init_module);
  */
 int jump_label_text_reserved(void *start, void *end)
 {
-	int ret = __jump_label_text_reserved(__start___jump_table,
-			__stop___jump_table, start, end);
+	int ret = __jump_label_text_reserved(LINKTABLE_START(__jump_table),
+					     LINKTABLE_END(__jump_table),
+					     start, end);
 
 	if (ret)
 		return ret;
@@ -553,7 +556,7 @@ int jump_label_text_reserved(void *start, void *end)
 
 static void jump_label_update(struct static_key *key)
 {
-	struct jump_entry *stop = __stop___jump_table;
+	struct jump_entry *stop = LINKTABLE_END(__jump_table);
 	struct jump_entry *entry = static_key_entries(key);
 #ifdef CONFIG_MODULES
 	struct module *mod;
diff --git a/scripts/module-common.lds b/scripts/module-common.lds
index 73a2c7da0e55..db0e724556c5 100644
--- a/scripts/module-common.lds
+++ b/scripts/module-common.lds
@@ -16,6 +16,7 @@ SECTIONS {
 	__kcrctab_unused	0 : { *(SORT(___kcrctab_unused+*)) }
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
+	__jump_table		0 : { *(SORT(.data..tbl.__jump_table.*)) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
diff --git a/tools/objtool/special.c b/tools/objtool/special.c
index bff8abb3a4aa..79968e118294 100644
--- a/tools/objtool/special.c
+++ b/tools/objtool/special.c
@@ -63,7 +63,7 @@ struct special_entry entries[] = {
 		.feature = ALT_FEATURE_OFFSET,
 	},
 	{
-		.sec = "__jump_table",
+		.sec = ".data..tbl.__jump_table.any",
 		.jump_or_nop = true,
 		.size = JUMP_ENTRY_SIZE,
 		.orig = JUMP_ORIG_OFFSET,
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 09/14] jump_label: port __jump_table to linker tables
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

Move the __jump_table from the a custom section solution
to a generic solution, this avoiding extra vmlinux.lds.h
customizations.

This also demos the use of the .data linker table and of
the shared asm call push_section_tbl().

Built-in kernel functionality was tested with CONFIG_STATIC_KEYS_SELFTEST.
Moduler  kernel functionality was tested with CONFIG_TEST_STATIC_KEYS.
Both work as expected.

Since __jump_table sections are also supported per
module this also required expanding module-common.lds.S
to capture and fold all .data.tlb.__jump_table.* onto
the the section __jump_table -- in this case for modules
need to keep a reference in place, given the alternative
is to use DEFINE_LINKTABLE(struct jump_entry, __jump_table)
per module -- and later through macro hacks instantiate
the jump entries per module upon init. This is doable but
we'd loose out on the sorting of the table using the
linker, to sort we'd always still need to expand the
module common linker script. An alternative mechanism
is possible which would make these custom module sections
extensions dynamic without requiring manual changes, this
however is best done later through a separate evolution
once linker tables are in place.

A careful reviewer may note that some architectures use
"\n\t" to separate asm code, while others just use a new line.
Upon review last time it was deemed reasonable to for all
architectures to just use "\n", this is defined as ASM_CMD_SEP,
and if an architecture needs to override they can do so on their
architecture sections.h prior to including asm-generic/sections.h

v5:

o Use ..tbl instead of .tbl as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

o Use LINKTABLE_START() and LINKTABLE_END()

o fixed tile jump label port -- tile got jump label support as of commit
  65a792e84f25d1 ("tile/jump_label: add jump label support for TILE-Gx"),
  as such we just needed to adjust the asm to account for the new
  linker table API use. This commit was merged as of v4.5-rc1.

v4:

o Some architectures allow linker scripts to follow including header
  files, some others do not, so if you need a helper on a linker script
  you need to explicitly include it. So for instance although
  scripts/module-common.lds.S includes <asm/tables.h> and this file
  includes <asm/section-core.h>, you still need to explicitly
  include it on the linker script. This issue is present on ARM.

o as per Josh Poimboeuf open code the section table name instead
  of including the kernel section headers, the simplicity and
  independence from the kernel is preferred.

v3:

o More elaborate tests performed
o first modular support use case, module tested was
  CONFIG_TEST_STATIC_KEYS (lib/test_static_keys.ko), this
  required us to extend module-common.lds.S
o use generic push_section_tbl_any() for all architectures
o Makes use of ASM_CMD_SEP to enable architectures to override later
  if needed
o guard tables.h inclusion and table definition with __KERNEL__

v2: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arm/include/asm/jump_label.h     |  6 ++++--
 arch/arm64/include/asm/jump_label.h   |  6 ++++--
 arch/mips/include/asm/jump_label.h    |  6 ++++--
 arch/powerpc/include/asm/jump_label.h |  8 +++++---
 arch/s390/include/asm/jump_label.h    |  6 ++++--
 arch/sparc/include/asm/jump_label.h   |  6 ++++--
 arch/tile/include/asm/jump_label.h    |  5 +++--
 arch/x86/include/asm/jump_label.h     | 10 ++++++----
 include/asm-generic/vmlinux.lds.h     |  5 -----
 include/linux/jump_label.h            |  4 ++--
 kernel/jump_label.c                   | 17 ++++++++++-------
 scripts/module-common.lds             |  1 +
 tools/objtool/special.c               |  2 +-
 13 files changed, 48 insertions(+), 34 deletions(-)

diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h
index 34f7b6980d21..609e0592a942 100644
--- a/arch/arm/include/asm/jump_label.h
+++ b/arch/arm/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_ARM_JUMP_LABEL_H
 #define _ASM_ARM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(nop) "\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
@@ -26,7 +28,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(b) " %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
diff --git a/arch/arm64/include/asm/jump_label.h b/arch/arm64/include/asm/jump_label.h
index 1b5e0e843c3a..bb56ac4fafb5 100644
--- a/arch/arm64/include/asm/jump_label.h
+++ b/arch/arm64/include/asm/jump_label.h
@@ -19,6 +19,8 @@
 #ifndef __ASM_JUMP_LABEL_H
 #define __ASM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -29,7 +31,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm goto("1: nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
@@ -43,7 +45,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm goto("1: b %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
diff --git a/arch/mips/include/asm/jump_label.h b/arch/mips/include/asm/jump_label.h
index e77672539e8e..07289a1b1bcd 100644
--- a/arch/mips/include/asm/jump_label.h
+++ b/arch/mips/include/asm/jump_label.h
@@ -8,6 +8,8 @@
 #ifndef _ASM_MIPS_JUMP_LABEL_H
 #define _ASM_MIPS_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -30,7 +32,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\t" NOP_INSN "\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -44,7 +46,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\tj %l[l_yes]\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
index 9a287e0ac8b1..7a75623740d0 100644
--- a/arch/powerpc/include/asm/jump_label.h
+++ b/arch/powerpc/include/asm/jump_label.h
@@ -10,6 +10,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
 
@@ -23,7 +25,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 "nop # arch_static_branch\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -37,7 +39,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes] # arch_static_branch_jump\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -62,7 +64,7 @@ struct jump_entry {
 #else
 #define ARCH_STATIC_BRANCH(LABEL, KEY)		\
 1098:	nop;					\
-	.pushsection __jump_table, "aw";	\
+	push_section_tbl_any(.data, __jump_table, aw); \
 	FTR_ENTRY_LONG 1098b, LABEL, KEY;	\
 	.popsection
 #endif
diff --git a/arch/s390/include/asm/jump_label.h b/arch/s390/include/asm/jump_label.h
index 9be198f5ee79..58e53af49e7e 100644
--- a/arch/s390/include/asm/jump_label.h
+++ b/arch/s390/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_S390_JUMP_LABEL_H
 #define _ASM_S390_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -16,7 +18,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 0,"__stringify(JUMP_LABEL_NOP_OFFSET)"\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
@@ -30,7 +32,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 15, %l[label]\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
diff --git a/arch/sparc/include/asm/jump_label.h b/arch/sparc/include/asm/jump_label.h
index 62d0354d1727..35d3e5d31821 100644
--- a/arch/sparc/include/asm/jump_label.h
+++ b/arch/sparc/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_SPARC_JUMP_LABEL_H
 #define _ASM_SPARC_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 	asm_volatile_goto("1:\n\t"
 		 "nop\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
@@ -28,7 +30,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes]\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
diff --git a/arch/tile/include/asm/jump_label.h b/arch/tile/include/asm/jump_label.h
index cde7573f397b..9bd989daad4a 100644
--- a/arch/tile/include/asm/jump_label.h
+++ b/arch/tile/include/asm/jump_label.h
@@ -16,6 +16,7 @@
 #define _ASM_TILE_JUMP_LABEL_H
 
 #include <arch/opcode.h>
+#include <asm/tables.h>
 
 #define JUMP_LABEL_NOP_SIZE	TILE_BUNDLE_SIZE_IN_BYTES
 
@@ -24,7 +25,7 @@ static __always_inline bool arch_static_branch(struct static_key *key,
 {
 	asm_volatile_goto("1:\n\t"
 		"nop" "\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".quad 1b, %l[l_yes], %0 + %1 \n\t"
 		".popsection\n\t"
 		: :  "i" (key), "i" (branch) : : l_yes);
@@ -38,7 +39,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key,
 {
 	asm_volatile_goto("1:\n\t"
 		"j %l[l_yes]" "\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".quad 1b, %l[l_yes], %0 + %1 \n\t"
 		".popsection\n\t"
 		: :  "i" (key), "i" (branch) : : l_yes);
diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h
index adc54c12cbd1..627df4752db0 100644
--- a/arch/x86/include/asm/jump_label.h
+++ b/arch/x86/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_JUMP_LABEL_H
 #define _ASM_X86_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef HAVE_JUMP_LABEL
 /*
  * For better or for worse, if jump labels (the gcc extension) are missing,
@@ -34,7 +36,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:"
 		".byte " __stringify(STATIC_KEY_INIT_NOP) "\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -50,7 +52,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:"
 		".byte 0xe9\n\t .long %l[l_yes] - 2f\n\t"
 		"2:\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -85,7 +87,7 @@ struct jump_entry {
 	.else
 	.byte		STATIC_KEY_INIT_NOP
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(.data, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key
 	.popsection
@@ -101,7 +103,7 @@ struct jump_entry {
 	.long		\target - .Lstatic_jump_after_\@
 .Lstatic_jump_after_\@:
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(.data, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key + 1
 	.popsection
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 8a5325d75932..887d844f0406 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -216,11 +216,6 @@
 	*(.data.unlikely)						\
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
-	/* implement dynamic printk debug */				\
-	. = ALIGN(8);                                                   \
-	VMLINUX_SYMBOL(__start___jump_table) = .;                       \
-	KEEP(*(__jump_table))                                           \
-	VMLINUX_SYMBOL(__stop___jump_table) = .;                        \
 	. = ALIGN(8);							\
 	VMLINUX_SYMBOL(__start___verbose) = .;                          \
 	KEEP(*(__verbose))                                              \
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index b63d6b7b0db0..e6277888b558 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -117,6 +117,7 @@ enum jump_label_type {
 struct module;
 
 #ifdef HAVE_JUMP_LABEL
+#include <linux/tables.h>
 
 #define JUMP_TYPE_FALSE	0UL
 #define JUMP_TYPE_TRUE	1UL
@@ -132,8 +133,7 @@ static __always_inline bool static_key_true(struct static_key *key)
 	return !arch_static_branch(key, true);
 }
 
-extern struct jump_entry __start___jump_table[];
-extern struct jump_entry __stop___jump_table[];
+DECLARE_LINKTABLE(struct jump_entry, __jump_table);
 
 extern void jump_label_init(void);
 extern void jump_label_lock(void);
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 93ad6c1fb9b6..d5c1067439ab 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -15,9 +15,12 @@
 #include <linux/static_key.h>
 #include <linux/jump_label_ratelimit.h>
 #include <linux/bug.h>
+#include <linux/tables.h>
 
 #ifdef HAVE_JUMP_LABEL
 
+DEFINE_LINKTABLE(struct jump_entry, __jump_table);
+
 /* mutex to protect coming/going of the the jump_label table */
 static DEFINE_MUTEX(jump_label_mutex);
 
@@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
 
 void __init jump_label_init(void)
 {
-	struct jump_entry *iter_start = __start___jump_table;
-	struct jump_entry *iter_stop = __stop___jump_table;
 	struct static_key *key = NULL;
 	struct jump_entry *iter;
 
@@ -292,9 +293,10 @@ void __init jump_label_init(void)
 		return;
 
 	jump_label_lock();
-	jump_label_sort_entries(iter_start, iter_stop);
+	jump_label_sort_entries(LINKTABLE_START(__jump_table),
+				LINKTABLE_END(__jump_table));
 
-	for (iter = iter_start; iter < iter_stop; iter++) {
+	LINKTABLE_FOR_EACH(iter, __jump_table) {
 		struct static_key *iterk;
 
 		/* rewrite NOPs */
@@ -539,8 +541,9 @@ early_initcall(jump_label_init_module);
  */
 int jump_label_text_reserved(void *start, void *end)
 {
-	int ret = __jump_label_text_reserved(__start___jump_table,
-			__stop___jump_table, start, end);
+	int ret = __jump_label_text_reserved(LINKTABLE_START(__jump_table),
+					     LINKTABLE_END(__jump_table),
+					     start, end);
 
 	if (ret)
 		return ret;
@@ -553,7 +556,7 @@ int jump_label_text_reserved(void *start, void *end)
 
 static void jump_label_update(struct static_key *key)
 {
-	struct jump_entry *stop = __stop___jump_table;
+	struct jump_entry *stop = LINKTABLE_END(__jump_table);
 	struct jump_entry *entry = static_key_entries(key);
 #ifdef CONFIG_MODULES
 	struct module *mod;
diff --git a/scripts/module-common.lds b/scripts/module-common.lds
index 73a2c7da0e55..db0e724556c5 100644
--- a/scripts/module-common.lds
+++ b/scripts/module-common.lds
@@ -16,6 +16,7 @@ SECTIONS {
 	__kcrctab_unused	0 : { *(SORT(___kcrctab_unused+*)) }
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
+	__jump_table		0 : { *(SORT(.data..tbl.__jump_table.*)) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
diff --git a/tools/objtool/special.c b/tools/objtool/special.c
index bff8abb3a4aa..79968e118294 100644
--- a/tools/objtool/special.c
+++ b/tools/objtool/special.c
@@ -63,7 +63,7 @@ struct special_entry entries[] = {
 		.feature = ALT_FEATURE_OFFSET,
 	},
 	{
-		.sec = "__jump_table",
+		.sec = ".data..tbl.__jump_table.any",
 		.jump_or_nop = true,
 		.size = JUMP_ENTRY_SIZE,
 		.orig = JUMP_ORIG_OFFSET,
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 10/14] dynamic_debug: port to use linker tables
  2016-12-22  2:37     ` Luis R. Rodriguez
  (?)
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This removes the custom vmlinux.lds.h hacks and uses
the generalized solution for .data entries.

There is much more potential for further fine tuning here
in the future though. For instance, linker tables enable
an extra postfix for order level annotations, this could
easily be used as the KBUILD_MODNAME and with a bit of
linker table changes we may be able to get a direct O(1)
count of the entries for that KBUILD_MODNAME: it would
just be a count on the number of entries for the given
order level. This should help make dynamic_debug_init()
cleaner and also reduce the amount of time it takes at
boot time. Instead of iterating over each print until we
have all for a KBUILD_MODNAME, we'd instead directly
operate on each KBUILD_MODNAME directly. We can work on
this later to make this change easier to review.

Tested dynamic debug with dyndbg query and debugfs control
and it works as expected, for both built-in code and modules.

v5:

o Use ..tbl instead of .tbl as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names,
  use LINKTABLE_EMPTY(), LINKTABLE_START()

v4: fix compilation on blackfin
v3: added modular support
v2: introduced this patch into the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/asm-generic/vmlinux.lds.h |  4 ----
 include/linux/dynamic_debug.h     |  5 +++--
 lib/dynamic_debug.c               | 13 ++++++-------
 scripts/module-common.lds         |  1 +
 4 files changed, 10 insertions(+), 13 deletions(-)

diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 887d844f0406..37b99537d5a9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -216,10 +216,6 @@
 	*(.data.unlikely)						\
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
-	. = ALIGN(8);							\
-	VMLINUX_SYMBOL(__start___verbose) = .;                          \
-	KEEP(*(__verbose))                                              \
-	VMLINUX_SYMBOL(__stop___verbose) = .;				\
 	LIKELY_PROFILE()		       				\
 	BRANCH_PROFILE()						\
 	TRACE_PRINTKS()							\
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 546d68057e3b..a52618a77b09 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -4,6 +4,7 @@
 #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
 #include <linux/jump_label.h>
 #endif
+#include <linux/tables.h>
 
 /*
  * An instance of this structure is created in a special
@@ -50,6 +51,7 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
 				const char *modname);
 
 #if defined(CONFIG_DYNAMIC_DEBUG)
+DECLARE_LINKTABLE(struct _ddebug, __verbose);
 extern int ddebug_remove_module(const char *mod_name);
 extern __printf(2, 3)
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
@@ -71,8 +73,7 @@ void __dynamic_netdev_dbg(struct _ddebug *descriptor,
 			  const char *fmt, ...);
 
 #define DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, key, init)	\
-	static struct _ddebug  __aligned(8)			\
-	__attribute__((section("__verbose"))) name = {		\
+	static LINKTABLE(__verbose, SECTION_ORDER_ANY) name = {	\
 		.modname = KBUILD_MODNAME,			\
 		.function = __func__,				\
 		.filename = __FILE__,				\
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index da796e2dc4f5..23da6bcf2f95 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -37,8 +37,7 @@
 #include <linux/device.h>
 #include <linux/netdevice.h>
 
-extern struct _ddebug __start___verbose[];
-extern struct _ddebug __stop___verbose[];
+DEFINE_LINKTABLE(struct _ddebug, __verbose);
 
 struct ddebug_table {
 	struct list_head link;
@@ -978,14 +977,14 @@ static int __init dynamic_debug_init(void)
 	int n = 0, entries = 0, modct = 0;
 	int verbose_bytes = 0;
 
-	if (__start___verbose = __stop___verbose) {
-		pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
+	if (LINKTABLE_EMPTY(__verbose)) {
+		pr_warn("dynamic debug linker table empty on CONFIG_DYNAMIC_DEBUG build\n");
 		return 1;
 	}
-	iter = __start___verbose;
+	iter = LINKTABLE_START(__verbose);
 	modname = iter->modname;
 	iter_start = iter;
-	for (; iter < __stop___verbose; iter++) {
+	LINKTABLE_FOR_EACH(iter, __verbose) {
 		entries++;
 		verbose_bytes += strlen(iter->modname) + strlen(iter->function)
 			+ strlen(iter->filename) + strlen(iter->format);
@@ -1008,7 +1007,7 @@ static int __init dynamic_debug_init(void)
 	ddebug_init_success = 1;
 	vpr_info("%d modules, %d entries and %d bytes in ddebug tables, %d bytes in (readonly) verbose section\n",
 		 modct, entries, (int)(modct * sizeof(struct ddebug_table)),
-		 verbose_bytes + (int)(__stop___verbose - __start___verbose));
+		 verbose_bytes + (int)(LINKTABLE_SIZE(__verbose)));
 
 	/* apply ddebug_query boot param, dont unload tables on err */
 	if (ddebug_setup_string[0] != '\0') {
diff --git a/scripts/module-common.lds b/scripts/module-common.lds
index db0e724556c5..25755d458f09 100644
--- a/scripts/module-common.lds
+++ b/scripts/module-common.lds
@@ -17,6 +17,7 @@ SECTIONS {
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
 	__jump_table		0 : { *(SORT(.data..tbl.__jump_table.*)) }
+	__verbose		0 : { *(SORT(.data..tbl.__verbose.*)) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 10/14] dynamic_debug: port to use linker tables
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This removes the custom vmlinux.lds.h hacks and uses
the generalized solution for .data entries.

There is much more potential for further fine tuning here
in the future though. For instance, linker tables enable
an extra postfix for order level annotations, this could
easily be used as the KBUILD_MODNAME and with a bit of
linker table changes we may be able to get a direct O(1)
count of the entries for that KBUILD_MODNAME: it would
just be a count on the number of entries for the given
order level. This should help make dynamic_debug_init()
cleaner and also reduce the amount of time it takes at
boot time. Instead of iterating over each print until we
have all for a KBUILD_MODNAME, we'd instead directly
operate on each KBUILD_MODNAME directly. We can work on
this later to make this change easier to review.

Tested dynamic debug with dyndbg query and debugfs control
and it works as expected, for both built-in code and modules.

v5:

o Use ..tbl instead of .tbl as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names,
  use LINKTABLE_EMPTY(), LINKTABLE_START()

v4: fix compilation on blackfin
v3: added modular support
v2: introduced this patch into the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/asm-generic/vmlinux.lds.h |  4 ----
 include/linux/dynamic_debug.h     |  5 +++--
 lib/dynamic_debug.c               | 13 ++++++-------
 scripts/module-common.lds         |  1 +
 4 files changed, 10 insertions(+), 13 deletions(-)

diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 887d844f0406..37b99537d5a9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -216,10 +216,6 @@
 	*(.data.unlikely)						\
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
-	. = ALIGN(8);							\
-	VMLINUX_SYMBOL(__start___verbose) = .;                          \
-	KEEP(*(__verbose))                                              \
-	VMLINUX_SYMBOL(__stop___verbose) = .;				\
 	LIKELY_PROFILE()		       				\
 	BRANCH_PROFILE()						\
 	TRACE_PRINTKS()							\
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 546d68057e3b..a52618a77b09 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -4,6 +4,7 @@
 #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
 #include <linux/jump_label.h>
 #endif
+#include <linux/tables.h>
 
 /*
  * An instance of this structure is created in a special
@@ -50,6 +51,7 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
 				const char *modname);
 
 #if defined(CONFIG_DYNAMIC_DEBUG)
+DECLARE_LINKTABLE(struct _ddebug, __verbose);
 extern int ddebug_remove_module(const char *mod_name);
 extern __printf(2, 3)
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
@@ -71,8 +73,7 @@ void __dynamic_netdev_dbg(struct _ddebug *descriptor,
 			  const char *fmt, ...);
 
 #define DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, key, init)	\
-	static struct _ddebug  __aligned(8)			\
-	__attribute__((section("__verbose"))) name = {		\
+	static LINKTABLE(__verbose, SECTION_ORDER_ANY) name = {	\
 		.modname = KBUILD_MODNAME,			\
 		.function = __func__,				\
 		.filename = __FILE__,				\
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index da796e2dc4f5..23da6bcf2f95 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -37,8 +37,7 @@
 #include <linux/device.h>
 #include <linux/netdevice.h>
 
-extern struct _ddebug __start___verbose[];
-extern struct _ddebug __stop___verbose[];
+DEFINE_LINKTABLE(struct _ddebug, __verbose);
 
 struct ddebug_table {
 	struct list_head link;
@@ -978,14 +977,14 @@ static int __init dynamic_debug_init(void)
 	int n = 0, entries = 0, modct = 0;
 	int verbose_bytes = 0;
 
-	if (__start___verbose == __stop___verbose) {
-		pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
+	if (LINKTABLE_EMPTY(__verbose)) {
+		pr_warn("dynamic debug linker table empty on CONFIG_DYNAMIC_DEBUG build\n");
 		return 1;
 	}
-	iter = __start___verbose;
+	iter = LINKTABLE_START(__verbose);
 	modname = iter->modname;
 	iter_start = iter;
-	for (; iter < __stop___verbose; iter++) {
+	LINKTABLE_FOR_EACH(iter, __verbose) {
 		entries++;
 		verbose_bytes += strlen(iter->modname) + strlen(iter->function)
 			+ strlen(iter->filename) + strlen(iter->format);
@@ -1008,7 +1007,7 @@ static int __init dynamic_debug_init(void)
 	ddebug_init_success = 1;
 	vpr_info("%d modules, %d entries and %d bytes in ddebug tables, %d bytes in (readonly) verbose section\n",
 		 modct, entries, (int)(modct * sizeof(struct ddebug_table)),
-		 verbose_bytes + (int)(__stop___verbose - __start___verbose));
+		 verbose_bytes + (int)(LINKTABLE_SIZE(__verbose)));
 
 	/* apply ddebug_query boot param, dont unload tables on err */
 	if (ddebug_setup_string[0] != '\0') {
diff --git a/scripts/module-common.lds b/scripts/module-common.lds
index db0e724556c5..25755d458f09 100644
--- a/scripts/module-common.lds
+++ b/scripts/module-common.lds
@@ -17,6 +17,7 @@ SECTIONS {
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
 	__jump_table		0 : { *(SORT(.data..tbl.__jump_table.*)) }
+	__verbose		0 : { *(SORT(.data..tbl.__verbose.*)) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 10/14] dynamic_debug: port to use linker tables
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez, Barry Song, Mike Frysinger, Michael Matz,
	Fengguang Wu

This removes the custom vmlinux.lds.h hacks and uses
the generalized solution for .data entries.

There is much more potential for further fine tuning here
in the future though. For instance, linker tables enable
an extra postfix for order level annotations, this could
easily be used as the KBUILD_MODNAME and with a bit of
linker table changes we may be able to get a direct O(1)
count of the entries for that KBUILD_MODNAME: it would
just be a count on the number of entries for the given
order level. This should help make dynamic_debug_init()
cleaner and also reduce the amount of time it takes at
boot time. Instead of iterating over each print until we
have all for a KBUILD_MODNAME, we'd instead directly
operate on each KBUILD_MODNAME directly. We can work on
this later to make this change easier to review.

Tested dynamic debug with dyndbg query and debugfs control
and it works as expected, for both built-in code and modules.

v5:

o Use ..tbl instead of .tbl as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names,
  use LINKTABLE_EMPTY(), LINKTABLE_START()

v4: fix compilation on blackfin
v3: added modular support
v2: introduced this patch into the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/asm-generic/vmlinux.lds.h |  4 ----
 include/linux/dynamic_debug.h     |  5 +++--
 lib/dynamic_debug.c               | 13 ++++++-------
 scripts/module-common.lds         |  1 +
 4 files changed, 10 insertions(+), 13 deletions(-)

diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 887d844f0406..37b99537d5a9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -216,10 +216,6 @@
 	*(.data.unlikely)						\
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
-	. = ALIGN(8);							\
-	VMLINUX_SYMBOL(__start___verbose) = .;                          \
-	KEEP(*(__verbose))                                              \
-	VMLINUX_SYMBOL(__stop___verbose) = .;				\
 	LIKELY_PROFILE()		       				\
 	BRANCH_PROFILE()						\
 	TRACE_PRINTKS()							\
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 546d68057e3b..a52618a77b09 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -4,6 +4,7 @@
 #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
 #include <linux/jump_label.h>
 #endif
+#include <linux/tables.h>
 
 /*
  * An instance of this structure is created in a special
@@ -50,6 +51,7 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
 				const char *modname);
 
 #if defined(CONFIG_DYNAMIC_DEBUG)
+DECLARE_LINKTABLE(struct _ddebug, __verbose);
 extern int ddebug_remove_module(const char *mod_name);
 extern __printf(2, 3)
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
@@ -71,8 +73,7 @@ void __dynamic_netdev_dbg(struct _ddebug *descriptor,
 			  const char *fmt, ...);
 
 #define DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, key, init)	\
-	static struct _ddebug  __aligned(8)			\
-	__attribute__((section("__verbose"))) name = {		\
+	static LINKTABLE(__verbose, SECTION_ORDER_ANY) name = {	\
 		.modname = KBUILD_MODNAME,			\
 		.function = __func__,				\
 		.filename = __FILE__,				\
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index da796e2dc4f5..23da6bcf2f95 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -37,8 +37,7 @@
 #include <linux/device.h>
 #include <linux/netdevice.h>
 
-extern struct _ddebug __start___verbose[];
-extern struct _ddebug __stop___verbose[];
+DEFINE_LINKTABLE(struct _ddebug, __verbose);
 
 struct ddebug_table {
 	struct list_head link;
@@ -978,14 +977,14 @@ static int __init dynamic_debug_init(void)
 	int n = 0, entries = 0, modct = 0;
 	int verbose_bytes = 0;
 
-	if (__start___verbose == __stop___verbose) {
-		pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
+	if (LINKTABLE_EMPTY(__verbose)) {
+		pr_warn("dynamic debug linker table empty on CONFIG_DYNAMIC_DEBUG build\n");
 		return 1;
 	}
-	iter = __start___verbose;
+	iter = LINKTABLE_START(__verbose);
 	modname = iter->modname;
 	iter_start = iter;
-	for (; iter < __stop___verbose; iter++) {
+	LINKTABLE_FOR_EACH(iter, __verbose) {
 		entries++;
 		verbose_bytes += strlen(iter->modname) + strlen(iter->function)
 			+ strlen(iter->filename) + strlen(iter->format);
@@ -1008,7 +1007,7 @@ static int __init dynamic_debug_init(void)
 	ddebug_init_success = 1;
 	vpr_info("%d modules, %d entries and %d bytes in ddebug tables, %d bytes in (readonly) verbose section\n",
 		 modct, entries, (int)(modct * sizeof(struct ddebug_table)),
-		 verbose_bytes + (int)(__stop___verbose - __start___verbose));
+		 verbose_bytes + (int)(LINKTABLE_SIZE(__verbose)));
 
 	/* apply ddebug_query boot param, dont unload tables on err */
 	if (ddebug_setup_string[0] != '\0') {
diff --git a/scripts/module-common.lds b/scripts/module-common.lds
index db0e724556c5..25755d458f09 100644
--- a/scripts/module-common.lds
+++ b/scripts/module-common.lds
@@ -17,6 +17,7 @@ SECTIONS {
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
 	__jump_table		0 : { *(SORT(.data..tbl.__jump_table.*)) }
+	__verbose		0 : { *(SORT(.data..tbl.__verbose.*)) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 11/14] kprobes: move kprobe declarations to asm-generic/kprobes.h
  2016-12-22  2:37     ` Luis R. Rodriguez
  (?)
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Often all is needed is these small helpers, instead of compiler.h
or a full kprobes.h. This is important for asm helpers, in fact even
some asm/kprobes.h make use of these helpers... instead just keep a
generic asm file with helpers useful for asm code with the least amount
of clutter as possible.

Likewise we need now to also address what to do about this file for both
when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
for when architectures have CONFIG_HAVE_KPROBES but have disabled
CONFIG_KPROBES.

Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
this means most architecture code cannot include asm/kprobes.h safely.
Correct this and add guards for architectures missing them. Additionally
provide architectures that not have kprobes support with the default
asm-generic solution. This lets us force asm/kprobes.h on the header
include/linux/kprobes.h always, but most importantly we can now safely
include just asm/kprobes.h on architecture code without bringing
the full kitchen sink of header files.

Two architectures already provided a guard against CONFIG_KPROBES on
its kprobes.h: sh, arch. The rest of the architectures needed gaurds
added. We avoid including any not-needed headers on asm/kprobes.h
unless kprobes have been enabled.

In a subsequent atomic change we can try now to remove compiler.h from
include/linux/kprobes.h.

During this sweep I've also identified a few architectures defining
a common macro needed for both kprobes and ftrace, that of the
definition of the breakput instruction up. Some refer to this as
BREAKPOINT_INSTRUCTION. This must be kept outside of the #ifdef
CONFIG_KPROBES guard.

v5:

o fix BREAKPOINT_INSTRUCTION dependency with kernel architecture
  ftrace implementations:  Although its correct to #ifdef CONFIG_KPROBES
  on the architecture arch/$(ARCH)/include/asm/kprobes.h when
  architectures support ftrace they will rely on the
  BREAKPOINT_INSTRUCTION definition, this needs to be kept out from
  CONFIG_KPROBES as ftrace can be enabled without kprobes. This
  fixes compilation on x86 where kprobes is disabled but ftrace is
  left enabled.

o include <asm/kprobes.h> on arch/arm64/kernel/probes/decode-insn.h

v4: introduced this patch into the series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/alpha/include/asm/Kbuild          |  1 +
 arch/arc/include/asm/kprobes.h         |  6 ++++--
 arch/arm/include/asm/kprobes.h         |  4 ++++
 arch/arm/probes/decode.h               |  1 +
 arch/arm64/include/asm/kprobes.h       |  4 ++++
 arch/arm64/kernel/insn.c               |  1 +
 arch/arm64/kernel/probes/decode-insn.h |  2 ++
 arch/avr32/include/asm/kprobes.h       |  7 ++++++-
 arch/blackfin/include/asm/Kbuild       |  1 +
 arch/c6x/include/asm/Kbuild            |  1 +
 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/kprobes.h        | 12 +++++++++---
 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/kprobes.h        |  6 +++++-
 arch/mn10300/include/asm/kprobes.h     |  7 ++++++-
 arch/nios2/include/asm/Kbuild          |  1 +
 arch/openrisc/include/asm/Kbuild       |  1 +
 arch/parisc/include/asm/Kbuild         |  1 +
 arch/powerpc/include/asm/kprobes.h     |  3 +++
 arch/s390/include/asm/kprobes.h        |  7 ++++++-
 arch/score/include/asm/Kbuild          |  1 +
 arch/sh/include/asm/kprobes.h          |  5 ++++-
 arch/sparc/include/asm/kprobes.h       | 10 ++++++++--
 arch/tile/include/asm/kprobes.h        |  6 +++++-
 arch/um/include/asm/Kbuild             |  1 +
 arch/unicore32/include/asm/Kbuild      |  1 +
 arch/x86/include/asm/kprobes.h         |  9 ++++++++-
 arch/xtensa/include/asm/Kbuild         |  1 +
 include/asm-generic/kprobes.h          | 25 +++++++++++++++++++++++++
 include/linux/compiler.h               |  8 --------
 include/linux/kprobes.h                | 19 +++----------------
 37 files changed, 122 insertions(+), 38 deletions(-)
 create mode 100644 include/asm-generic/kprobes.h

diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index f3bdc31d3c97..54d388fd026f 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += trace_clock.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/arc/include/asm/kprobes.h b/arch/arc/include/asm/kprobes.h
index 944dbedb38b5..00bdbe167615 100644
--- a/arch/arc/include/asm/kprobes.h
+++ b/arch/arc/include/asm/kprobes.h
@@ -9,6 +9,8 @@
 #ifndef _ARC_KPROBES_H
 #define _ARC_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
 #ifdef CONFIG_KPROBES
 
 typedef u16 kprobe_opcode_t;
@@ -55,6 +57,6 @@ void trap_is_kprobe(unsigned long address, struct pt_regs *regs);
 static void trap_is_kprobe(unsigned long address, struct pt_regs *regs)
 {
 }
-#endif
+#endif /* CONFIG_KPROBES */
 
-#endif
+#endif /* _ARC_KPROBES_H */
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index 3ea9be559726..59655459da59 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/notifier.h>
@@ -83,4 +86,5 @@ struct arch_optimized_insn {
 	 */
 };
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm/probes/decode.h b/arch/arm/probes/decode.h
index f9b08ba7fe73..548d622a3159 100644
--- a/arch/arm/probes/decode.h
+++ b/arch/arm/probes/decode.h
@@ -22,6 +22,7 @@
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <asm/probes.h>
+#include <asm/kprobes.h>
 
 void __init arm_probes_decode_init(void);
 
diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
index 1737aecfcc5e..6deb8d726041 100644
--- a/arch/arm64/include/asm/kprobes.h
+++ b/arch/arm64/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -57,4 +60,5 @@ int kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr);
 void kretprobe_trampoline(void);
 void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 94b62c1fa4df..ae912304ed84 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -31,6 +31,7 @@
 #include <asm/debug-monitors.h>
 #include <asm/fixmap.h>
 #include <asm/insn.h>
+#include <asm/kprobes.h>
 
 #define AARCH64_INSN_SF_BIT	BIT(31)
 #define AARCH64_INSN_N_BIT	BIT(22)
diff --git a/arch/arm64/kernel/probes/decode-insn.h b/arch/arm64/kernel/probes/decode-insn.h
index 76d3f315407f..192ab007bacb 100644
--- a/arch/arm64/kernel/probes/decode-insn.h
+++ b/arch/arm64/kernel/probes/decode-insn.h
@@ -16,6 +16,8 @@
 #ifndef _ARM_KERNEL_KPROBES_ARM64_H
 #define _ARM_KERNEL_KPROBES_ARM64_H
 
+#include <asm/kprobes.h>
+
 /*
  * ARM strongly recommends a limit of 128 bytes between LoadExcl and
  * StoreExcl instructions in a single thread of execution. So keep the
diff --git a/arch/avr32/include/asm/kprobes.h b/arch/avr32/include/asm/kprobes.h
index 45f563ed73fd..28dfc61ad384 100644
--- a/arch/avr32/include/asm/kprobes.h
+++ b/arch/avr32/include/asm/kprobes.h
@@ -11,10 +11,14 @@
 #ifndef __ASM_AVR32_KPROBES_H
 #define __ASM_AVR32_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xd673	/* breakpoint */
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 
 typedef u16	kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xd673	/* breakpoint */
 #define MAX_INSN_SIZE		2
 #define MAX_STACK_SIZE		64	/* 32 would probably be OK */
 
@@ -46,4 +50,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif /* __ASM_AVR32_KPROBES_H */
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 9115b215fc7e..52351d3fd36e 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -50,3 +50,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index cede2a950fbf..c54f7cc1f63e 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
+generic-y += kprobes.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 7062c1be7913..051d355feae3 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 4a59cbda5091..b58b9fc49383 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index d79968d93c12..cfca7de52b37 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -78,3 +78,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index d59ac1c1858b..d7cc35451f30 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/ia64/include/asm/kprobes.h b/arch/ia64/include/asm/kprobes.h
index d5505d6f2382..0302b3664789 100644
--- a/arch/ia64/include/asm/kprobes.h
+++ b/arch/ia64/include/asm/kprobes.h
@@ -23,14 +23,19 @@
  * 2005-Apr     Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
  *              <anil.s.keshavamurthy@intel.com> adapted from i386
  */
+#include <asm-generic/kprobes.h>
+#include <asm/break.h>
+
+#define BREAK_INST	(long)(__IA64_BREAK_KPROBE << 6)
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
-#include <asm/break.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
 #define MAX_INSN_SIZE   2	/* last half is for kprobe-booster */
-#define BREAK_INST	(long)(__IA64_BREAK_KPROBE << 6)
 #define NOP_M_INST	(long)(1<<27)
 #define BRL_INST(i1, i2) ((long)((0xcL << 37) |	/* brl */ \
 				(0x1L << 12) |	/* many */ \
@@ -124,4 +129,5 @@ extern void invalidate_stacked_regs(void);
 extern void flush_register_stack(void);
 extern void arch_remove_kprobe(struct kprobe *p);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 24088f3c733c..198ad591ab41 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index c28bcdecc764..412dd23ab946 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -37,3 +37,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index c836f7e2a5e7..8371cc9b1b3c 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -58,3 +58,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index 01afb1b420f5..865ce3d96443 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/mips/include/asm/kprobes.h b/arch/mips/include/asm/kprobes.h
index daba1f9a4f79..291846d9ba83 100644
--- a/arch/mips/include/asm/kprobes.h
+++ b/arch/mips/include/asm/kprobes.h
@@ -22,6 +22,9 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/ptrace.h>
 #include <linux/types.h>
 
@@ -94,4 +97,5 @@ struct kprobe_ctlblk {
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/mn10300/include/asm/kprobes.h b/arch/mn10300/include/asm/kprobes.h
index c800b590183a..7abea0bdb549 100644
--- a/arch/mn10300/include/asm/kprobes.h
+++ b/arch/mn10300/include/asm/kprobes.h
@@ -21,13 +21,17 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xff
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 
 struct kprobe;
 
 typedef unsigned char kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xff
 #define MAX_INSN_SIZE 8
 #define MAX_STACK_SIZE 128
 
@@ -47,4 +51,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 extern void arch_remove_kprobe(struct kprobe *p);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_KPROBES_H */
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index ee6220dac1e8..d6ce7edee7e0 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -66,3 +66,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index ceafe458e295..1bf89a67317c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -74,3 +74,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index aaae8a9f6099..19d5b7e12ecf 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -31,3 +31,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h
index 97b8c1f83453..c7ee3fcbd6e2 100644
--- a/arch/powerpc/include/asm/kprobes.h
+++ b/arch/powerpc/include/asm/kprobes.h
@@ -1,5 +1,8 @@
 #ifndef _ASM_POWERPC_KPROBES_H
 #define _ASM_POWERPC_KPROBES_H
+
+#include <asm-generic/kprobes.h>
+
 #ifdef __KERNEL__
 /*
  *  Kernel Probes (KProbes)
diff --git a/arch/s390/include/asm/kprobes.h b/arch/s390/include/asm/kprobes.h
index 591e5a5279b0..84c0f9086483 100644
--- a/arch/s390/include/asm/kprobes.h
+++ b/arch/s390/include/asm/kprobes.h
@@ -27,6 +27,11 @@
  * 2005-Dec	Used as a template for s390 by Mike Grundy
  *		<grundym@us.ibm.com>
  */
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0x0002
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -37,7 +42,6 @@ struct pt_regs;
 struct kprobe;
 
 typedef u16 kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0x0002
 
 /* Maximum instruction size is 3 (16bit) halfwords: */
 #define MAX_INSN_SIZE		0x0003
@@ -91,4 +95,5 @@ int probe_is_insn_relative_long(u16 *insn);
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif	/* _ASM_S390_KPROBES_H */
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index 16ea15a3e432..6ac8a7f5c768 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -17,3 +17,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h
index 134f3980e44a..f0986f9b3844 100644
--- a/arch/sh/include/asm/kprobes.h
+++ b/arch/sh/include/asm/kprobes.h
@@ -1,13 +1,16 @@
 #ifndef __ASM_SH_KPROBES_H
 #define __ASM_SH_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xc33a
+
 #ifdef CONFIG_KPROBES
 
 #include <linux/types.h>
 #include <linux/ptrace.h>
 
 typedef insn_size_t kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xc33a
 
 #define MAX_INSN_SIZE 16
 #define MAX_STACK_SIZE 64
diff --git a/arch/sparc/include/asm/kprobes.h b/arch/sparc/include/asm/kprobes.h
index a145d798e112..49f8402035d7 100644
--- a/arch/sparc/include/asm/kprobes.h
+++ b/arch/sparc/include/asm/kprobes.h
@@ -1,13 +1,17 @@
 #ifndef _SPARC64_KPROBES_H
 #define _SPARC64_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION   0x91d02070 /* ta 0x70 */
+#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/percpu.h>
 
 typedef u32 kprobe_opcode_t;
 
-#define BREAKPOINT_INSTRUCTION   0x91d02070 /* ta 0x70 */
-#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
 #define MAX_INSN_SIZE 2
 
 #define kretprobe_blacklist_size 0
@@ -48,4 +52,6 @@ int kprobe_exceptions_notify(struct notifier_block *self,
 int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
 				      struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _SPARC64_KPROBES_H */
diff --git a/arch/tile/include/asm/kprobes.h b/arch/tile/include/asm/kprobes.h
index d8f9a83943b1..4a8b1cadca24 100644
--- a/arch/tile/include/asm/kprobes.h
+++ b/arch/tile/include/asm/kprobes.h
@@ -17,10 +17,13 @@
 #ifndef _ASM_TILE_KPROBES_H
 #define _ASM_TILE_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
-
 #include <arch/opcode.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
@@ -76,4 +79,5 @@ void arch_remove_kprobe(struct kprobe *);
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 			     unsigned long val, void *data);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_TILE_KPROBES_H */
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index d2867aa09e23..ccc5ffeaeef5 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 6671a1f08ead..5aacafb6d385 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h
index d1d1e5094c28..200581691c6e 100644
--- a/arch/x86/include/asm/kprobes.h
+++ b/arch/x86/include/asm/kprobes.h
@@ -21,6 +21,12 @@
  *
  * See arch/x86/kernel/kprobes.c for x86 kprobes history.
  */
+
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xcc
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -32,7 +38,6 @@ struct pt_regs;
 struct kprobe;
 
 typedef u8 kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xcc
 #define RELATIVEJUMP_OPCODE 0xe9
 #define RELATIVEJUMP_SIZE 5
 #define RELATIVECALL_OPCODE 0xe8
@@ -116,4 +121,6 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 extern int kprobe_int3_handler(struct pt_regs *regs);
 extern int kprobe_debug_handler(struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_X86_KPROBES_H */
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index 7b41f32a2ba0..20f524ded00e 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
new file mode 100644
index 000000000000..57af9f21d148
--- /dev/null
+++ b/include/asm-generic/kprobes.h
@@ -0,0 +1,25 @@
+#ifndef _ASM_GENERIC_KPROBES_H
+#define _ASM_GENERIC_KPROBES_H
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#ifdef CONFIG_KPROBES
+/*
+ * Blacklist ganerating macro. Specify functions which is not probed
+ * by using this macro.
+ */
+# define __NOKPROBE_SYMBOL(fname)				\
+static unsigned long __used					\
+	__attribute__((__section__("_kprobe_blacklist")))	\
+	_kbl_addr_##fname = (unsigned long)fname;
+# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
+/* Use this to forbid a kprobes attach on very low level functions */
+# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define nokprobe_inline	__always_inline
+#else
+# define NOKPROBE_SYMBOL(fname)
+# define __kprobes
+# define nokprobe_inline	inline
+#endif
+#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
+
+#endif /* _ASM_GENERIC_KPROBES_H */
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index cf0fa5d86059..dca49b4099da 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -566,12 +566,4 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 	(_________p1); \
 })
 
-/* Ignore/forbid kprobes attach on very low level functions marked by this attribute: */
-#ifdef CONFIG_KPROBES
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
-# define nokprobe_inline	__always_inline
-#else
-# define __kprobes
-# define nokprobe_inline	inline
-#endif
 #endif /* __LINUX_COMPILER_H */
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 8f6849084248..985ed79ef431 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -29,7 +29,7 @@
  *		<jkenisto@us.ibm.com>  and Prasanna S Panchamukhi
  *		<prasanna@in.ibm.com> added function-return probes.
  */
-#include <linux/compiler.h>	/* for __kprobes */
+#include <linux/compiler.h>
 #include <linux/linkage.h>
 #include <linux/list.h>
 #include <linux/notifier.h>
@@ -40,9 +40,9 @@
 #include <linux/rcupdate.h>
 #include <linux/mutex.h>
 #include <linux/ftrace.h>
+#include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
-#include <asm/kprobes.h>
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
@@ -51,6 +51,7 @@
 #define KPROBE_HIT_SSDONE	0x00000008
 
 #else /* CONFIG_KPROBES */
+#include <asm-generic/kprobes.h>
 typedef int kprobe_opcode_t;
 struct arch_specific_insn {
 	int dummy;
@@ -481,18 +482,4 @@ static inline int enable_jprobe(struct jprobe *jp)
 	return enable_kprobe(&jp->kp);
 }
 
-#ifdef CONFIG_KPROBES
-/*
- * Blacklist ganerating macro. Specify functions which is not probed
- * by using this macro.
- */
-#define __NOKPROBE_SYMBOL(fname)			\
-static unsigned long __used				\
-	__attribute__((section("_kprobe_blacklist")))	\
-	_kbl_addr_##fname = (unsigned long)fname;
-#define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
-#else
-#define NOKPROBE_SYMBOL(fname)
-#endif
-
 #endif /* _LINUX_KPROBES_H */
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 11/14] kprobes: move kprobe declarations to asm-generic/kprobes.h
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Often all is needed is these small helpers, instead of compiler.h
or a full kprobes.h. This is important for asm helpers, in fact even
some asm/kprobes.h make use of these helpers... instead just keep a
generic asm file with helpers useful for asm code with the least amount
of clutter as possible.

Likewise we need now to also address what to do about this file for both
when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
for when architectures have CONFIG_HAVE_KPROBES but have disabled
CONFIG_KPROBES.

Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
this means most architecture code cannot include asm/kprobes.h safely.
Correct this and add guards for architectures missing them. Additionally
provide architectures that not have kprobes support with the default
asm-generic solution. This lets us force asm/kprobes.h on the header
include/linux/kprobes.h always, but most importantly we can now safely
include just asm/kprobes.h on architecture code without bringing
the full kitchen sink of header files.

Two architectures already provided a guard against CONFIG_KPROBES on
its kprobes.h: sh, arch. The rest of the architectures needed gaurds
added. We avoid including any not-needed headers on asm/kprobes.h
unless kprobes have been enabled.

In a subsequent atomic change we can try now to remove compiler.h from
include/linux/kprobes.h.

During this sweep I've also identified a few architectures defining
a common macro needed for both kprobes and ftrace, that of the
definition of the breakput instruction up. Some refer to this as
BREAKPOINT_INSTRUCTION. This must be kept outside of the #ifdef
CONFIG_KPROBES guard.

v5:

o fix BREAKPOINT_INSTRUCTION dependency with kernel architecture
  ftrace implementations:  Although its correct to #ifdef CONFIG_KPROBES
  on the architecture arch/$(ARCH)/include/asm/kprobes.h when
  architectures support ftrace they will rely on the
  BREAKPOINT_INSTRUCTION definition, this needs to be kept out from
  CONFIG_KPROBES as ftrace can be enabled without kprobes. This
  fixes compilation on x86 where kprobes is disabled but ftrace is
  left enabled.

o include <asm/kprobes.h> on arch/arm64/kernel/probes/decode-insn.h

v4: introduced this patch into the series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/alpha/include/asm/Kbuild          |  1 +
 arch/arc/include/asm/kprobes.h         |  6 ++++--
 arch/arm/include/asm/kprobes.h         |  4 ++++
 arch/arm/probes/decode.h               |  1 +
 arch/arm64/include/asm/kprobes.h       |  4 ++++
 arch/arm64/kernel/insn.c               |  1 +
 arch/arm64/kernel/probes/decode-insn.h |  2 ++
 arch/avr32/include/asm/kprobes.h       |  7 ++++++-
 arch/blackfin/include/asm/Kbuild       |  1 +
 arch/c6x/include/asm/Kbuild            |  1 +
 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/kprobes.h        | 12 +++++++++---
 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/kprobes.h        |  6 +++++-
 arch/mn10300/include/asm/kprobes.h     |  7 ++++++-
 arch/nios2/include/asm/Kbuild          |  1 +
 arch/openrisc/include/asm/Kbuild       |  1 +
 arch/parisc/include/asm/Kbuild         |  1 +
 arch/powerpc/include/asm/kprobes.h     |  3 +++
 arch/s390/include/asm/kprobes.h        |  7 ++++++-
 arch/score/include/asm/Kbuild          |  1 +
 arch/sh/include/asm/kprobes.h          |  5 ++++-
 arch/sparc/include/asm/kprobes.h       | 10 ++++++++--
 arch/tile/include/asm/kprobes.h        |  6 +++++-
 arch/um/include/asm/Kbuild             |  1 +
 arch/unicore32/include/asm/Kbuild      |  1 +
 arch/x86/include/asm/kprobes.h         |  9 ++++++++-
 arch/xtensa/include/asm/Kbuild         |  1 +
 include/asm-generic/kprobes.h          | 25 +++++++++++++++++++++++++
 include/linux/compiler.h               |  8 --------
 include/linux/kprobes.h                | 19 +++----------------
 37 files changed, 122 insertions(+), 38 deletions(-)
 create mode 100644 include/asm-generic/kprobes.h

diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index f3bdc31d3c97..54d388fd026f 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += trace_clock.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/arc/include/asm/kprobes.h b/arch/arc/include/asm/kprobes.h
index 944dbedb38b5..00bdbe167615 100644
--- a/arch/arc/include/asm/kprobes.h
+++ b/arch/arc/include/asm/kprobes.h
@@ -9,6 +9,8 @@
 #ifndef _ARC_KPROBES_H
 #define _ARC_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
 #ifdef CONFIG_KPROBES
 
 typedef u16 kprobe_opcode_t;
@@ -55,6 +57,6 @@ void trap_is_kprobe(unsigned long address, struct pt_regs *regs);
 static void trap_is_kprobe(unsigned long address, struct pt_regs *regs)
 {
 }
-#endif
+#endif /* CONFIG_KPROBES */
 
-#endif
+#endif /* _ARC_KPROBES_H */
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index 3ea9be559726..59655459da59 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/notifier.h>
@@ -83,4 +86,5 @@ struct arch_optimized_insn {
 	 */
 };
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm/probes/decode.h b/arch/arm/probes/decode.h
index f9b08ba7fe73..548d622a3159 100644
--- a/arch/arm/probes/decode.h
+++ b/arch/arm/probes/decode.h
@@ -22,6 +22,7 @@
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <asm/probes.h>
+#include <asm/kprobes.h>
 
 void __init arm_probes_decode_init(void);
 
diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
index 1737aecfcc5e..6deb8d726041 100644
--- a/arch/arm64/include/asm/kprobes.h
+++ b/arch/arm64/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -57,4 +60,5 @@ int kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr);
 void kretprobe_trampoline(void);
 void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 94b62c1fa4df..ae912304ed84 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -31,6 +31,7 @@
 #include <asm/debug-monitors.h>
 #include <asm/fixmap.h>
 #include <asm/insn.h>
+#include <asm/kprobes.h>
 
 #define AARCH64_INSN_SF_BIT	BIT(31)
 #define AARCH64_INSN_N_BIT	BIT(22)
diff --git a/arch/arm64/kernel/probes/decode-insn.h b/arch/arm64/kernel/probes/decode-insn.h
index 76d3f315407f..192ab007bacb 100644
--- a/arch/arm64/kernel/probes/decode-insn.h
+++ b/arch/arm64/kernel/probes/decode-insn.h
@@ -16,6 +16,8 @@
 #ifndef _ARM_KERNEL_KPROBES_ARM64_H
 #define _ARM_KERNEL_KPROBES_ARM64_H
 
+#include <asm/kprobes.h>
+
 /*
  * ARM strongly recommends a limit of 128 bytes between LoadExcl and
  * StoreExcl instructions in a single thread of execution. So keep the
diff --git a/arch/avr32/include/asm/kprobes.h b/arch/avr32/include/asm/kprobes.h
index 45f563ed73fd..28dfc61ad384 100644
--- a/arch/avr32/include/asm/kprobes.h
+++ b/arch/avr32/include/asm/kprobes.h
@@ -11,10 +11,14 @@
 #ifndef __ASM_AVR32_KPROBES_H
 #define __ASM_AVR32_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xd673	/* breakpoint */
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 
 typedef u16	kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xd673	/* breakpoint */
 #define MAX_INSN_SIZE		2
 #define MAX_STACK_SIZE		64	/* 32 would probably be OK */
 
@@ -46,4 +50,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif /* __ASM_AVR32_KPROBES_H */
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 9115b215fc7e..52351d3fd36e 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -50,3 +50,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index cede2a950fbf..c54f7cc1f63e 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
+generic-y += kprobes.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 7062c1be7913..051d355feae3 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 4a59cbda5091..b58b9fc49383 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index d79968d93c12..cfca7de52b37 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -78,3 +78,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index d59ac1c1858b..d7cc35451f30 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/ia64/include/asm/kprobes.h b/arch/ia64/include/asm/kprobes.h
index d5505d6f2382..0302b3664789 100644
--- a/arch/ia64/include/asm/kprobes.h
+++ b/arch/ia64/include/asm/kprobes.h
@@ -23,14 +23,19 @@
  * 2005-Apr     Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
  *              <anil.s.keshavamurthy@intel.com> adapted from i386
  */
+#include <asm-generic/kprobes.h>
+#include <asm/break.h>
+
+#define BREAK_INST	(long)(__IA64_BREAK_KPROBE << 6)
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
-#include <asm/break.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
 #define MAX_INSN_SIZE   2	/* last half is for kprobe-booster */
-#define BREAK_INST	(long)(__IA64_BREAK_KPROBE << 6)
 #define NOP_M_INST	(long)(1<<27)
 #define BRL_INST(i1, i2) ((long)((0xcL << 37) |	/* brl */ \
 				(0x1L << 12) |	/* many */ \
@@ -124,4 +129,5 @@ extern void invalidate_stacked_regs(void);
 extern void flush_register_stack(void);
 extern void arch_remove_kprobe(struct kprobe *p);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 24088f3c733c..198ad591ab41 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index c28bcdecc764..412dd23ab946 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -37,3 +37,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index c836f7e2a5e7..8371cc9b1b3c 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -58,3 +58,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index 01afb1b420f5..865ce3d96443 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/mips/include/asm/kprobes.h b/arch/mips/include/asm/kprobes.h
index daba1f9a4f79..291846d9ba83 100644
--- a/arch/mips/include/asm/kprobes.h
+++ b/arch/mips/include/asm/kprobes.h
@@ -22,6 +22,9 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/ptrace.h>
 #include <linux/types.h>
 
@@ -94,4 +97,5 @@ struct kprobe_ctlblk {
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/mn10300/include/asm/kprobes.h b/arch/mn10300/include/asm/kprobes.h
index c800b590183a..7abea0bdb549 100644
--- a/arch/mn10300/include/asm/kprobes.h
+++ b/arch/mn10300/include/asm/kprobes.h
@@ -21,13 +21,17 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xff
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 
 struct kprobe;
 
 typedef unsigned char kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xff
 #define MAX_INSN_SIZE 8
 #define MAX_STACK_SIZE 128
 
@@ -47,4 +51,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 extern void arch_remove_kprobe(struct kprobe *p);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_KPROBES_H */
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index ee6220dac1e8..d6ce7edee7e0 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -66,3 +66,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index ceafe458e295..1bf89a67317c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -74,3 +74,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index aaae8a9f6099..19d5b7e12ecf 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -31,3 +31,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h
index 97b8c1f83453..c7ee3fcbd6e2 100644
--- a/arch/powerpc/include/asm/kprobes.h
+++ b/arch/powerpc/include/asm/kprobes.h
@@ -1,5 +1,8 @@
 #ifndef _ASM_POWERPC_KPROBES_H
 #define _ASM_POWERPC_KPROBES_H
+
+#include <asm-generic/kprobes.h>
+
 #ifdef __KERNEL__
 /*
  *  Kernel Probes (KProbes)
diff --git a/arch/s390/include/asm/kprobes.h b/arch/s390/include/asm/kprobes.h
index 591e5a5279b0..84c0f9086483 100644
--- a/arch/s390/include/asm/kprobes.h
+++ b/arch/s390/include/asm/kprobes.h
@@ -27,6 +27,11 @@
  * 2005-Dec	Used as a template for s390 by Mike Grundy
  *		<grundym@us.ibm.com>
  */
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0x0002
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -37,7 +42,6 @@ struct pt_regs;
 struct kprobe;
 
 typedef u16 kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0x0002
 
 /* Maximum instruction size is 3 (16bit) halfwords: */
 #define MAX_INSN_SIZE		0x0003
@@ -91,4 +95,5 @@ int probe_is_insn_relative_long(u16 *insn);
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif	/* _ASM_S390_KPROBES_H */
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index 16ea15a3e432..6ac8a7f5c768 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -17,3 +17,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h
index 134f3980e44a..f0986f9b3844 100644
--- a/arch/sh/include/asm/kprobes.h
+++ b/arch/sh/include/asm/kprobes.h
@@ -1,13 +1,16 @@
 #ifndef __ASM_SH_KPROBES_H
 #define __ASM_SH_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xc33a
+
 #ifdef CONFIG_KPROBES
 
 #include <linux/types.h>
 #include <linux/ptrace.h>
 
 typedef insn_size_t kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xc33a
 
 #define MAX_INSN_SIZE 16
 #define MAX_STACK_SIZE 64
diff --git a/arch/sparc/include/asm/kprobes.h b/arch/sparc/include/asm/kprobes.h
index a145d798e112..49f8402035d7 100644
--- a/arch/sparc/include/asm/kprobes.h
+++ b/arch/sparc/include/asm/kprobes.h
@@ -1,13 +1,17 @@
 #ifndef _SPARC64_KPROBES_H
 #define _SPARC64_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION   0x91d02070 /* ta 0x70 */
+#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/percpu.h>
 
 typedef u32 kprobe_opcode_t;
 
-#define BREAKPOINT_INSTRUCTION   0x91d02070 /* ta 0x70 */
-#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
 #define MAX_INSN_SIZE 2
 
 #define kretprobe_blacklist_size 0
@@ -48,4 +52,6 @@ int kprobe_exceptions_notify(struct notifier_block *self,
 int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
 				      struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _SPARC64_KPROBES_H */
diff --git a/arch/tile/include/asm/kprobes.h b/arch/tile/include/asm/kprobes.h
index d8f9a83943b1..4a8b1cadca24 100644
--- a/arch/tile/include/asm/kprobes.h
+++ b/arch/tile/include/asm/kprobes.h
@@ -17,10 +17,13 @@
 #ifndef _ASM_TILE_KPROBES_H
 #define _ASM_TILE_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
-
 #include <arch/opcode.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
@@ -76,4 +79,5 @@ void arch_remove_kprobe(struct kprobe *);
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 			     unsigned long val, void *data);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_TILE_KPROBES_H */
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index d2867aa09e23..ccc5ffeaeef5 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 6671a1f08ead..5aacafb6d385 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h
index d1d1e5094c28..200581691c6e 100644
--- a/arch/x86/include/asm/kprobes.h
+++ b/arch/x86/include/asm/kprobes.h
@@ -21,6 +21,12 @@
  *
  * See arch/x86/kernel/kprobes.c for x86 kprobes history.
  */
+
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xcc
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -32,7 +38,6 @@ struct pt_regs;
 struct kprobe;
 
 typedef u8 kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xcc
 #define RELATIVEJUMP_OPCODE 0xe9
 #define RELATIVEJUMP_SIZE 5
 #define RELATIVECALL_OPCODE 0xe8
@@ -116,4 +121,6 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 extern int kprobe_int3_handler(struct pt_regs *regs);
 extern int kprobe_debug_handler(struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_X86_KPROBES_H */
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index 7b41f32a2ba0..20f524ded00e 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
new file mode 100644
index 000000000000..57af9f21d148
--- /dev/null
+++ b/include/asm-generic/kprobes.h
@@ -0,0 +1,25 @@
+#ifndef _ASM_GENERIC_KPROBES_H
+#define _ASM_GENERIC_KPROBES_H
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#ifdef CONFIG_KPROBES
+/*
+ * Blacklist ganerating macro. Specify functions which is not probed
+ * by using this macro.
+ */
+# define __NOKPROBE_SYMBOL(fname)				\
+static unsigned long __used					\
+	__attribute__((__section__("_kprobe_blacklist")))	\
+	_kbl_addr_##fname = (unsigned long)fname;
+# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
+/* Use this to forbid a kprobes attach on very low level functions */
+# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define nokprobe_inline	__always_inline
+#else
+# define NOKPROBE_SYMBOL(fname)
+# define __kprobes
+# define nokprobe_inline	inline
+#endif
+#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
+
+#endif /* _ASM_GENERIC_KPROBES_H */
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index cf0fa5d86059..dca49b4099da 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -566,12 +566,4 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 	(_________p1); \
 })
 
-/* Ignore/forbid kprobes attach on very low level functions marked by this attribute: */
-#ifdef CONFIG_KPROBES
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
-# define nokprobe_inline	__always_inline
-#else
-# define __kprobes
-# define nokprobe_inline	inline
-#endif
 #endif /* __LINUX_COMPILER_H */
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 8f6849084248..985ed79ef431 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -29,7 +29,7 @@
  *		<jkenisto@us.ibm.com>  and Prasanna S Panchamukhi
  *		<prasanna@in.ibm.com> added function-return probes.
  */
-#include <linux/compiler.h>	/* for __kprobes */
+#include <linux/compiler.h>
 #include <linux/linkage.h>
 #include <linux/list.h>
 #include <linux/notifier.h>
@@ -40,9 +40,9 @@
 #include <linux/rcupdate.h>
 #include <linux/mutex.h>
 #include <linux/ftrace.h>
+#include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
-#include <asm/kprobes.h>
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
@@ -51,6 +51,7 @@
 #define KPROBE_HIT_SSDONE	0x00000008
 
 #else /* CONFIG_KPROBES */
+#include <asm-generic/kprobes.h>
 typedef int kprobe_opcode_t;
 struct arch_specific_insn {
 	int dummy;
@@ -481,18 +482,4 @@ static inline int enable_jprobe(struct jprobe *jp)
 	return enable_kprobe(&jp->kp);
 }
 
-#ifdef CONFIG_KPROBES
-/*
- * Blacklist ganerating macro. Specify functions which is not probed
- * by using this macro.
- */
-#define __NOKPROBE_SYMBOL(fname)			\
-static unsigned long __used				\
-	__attribute__((section("_kprobe_blacklist")))	\
-	_kbl_addr_##fname = (unsigned long)fname;
-#define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
-#else
-#define NOKPROBE_SYMBOL(fname)
-#endif
-
 #endif /* _LINUX_KPROBES_H */
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 11/14] kprobes: move kprobe declarations to asm-generic/kprobes.h
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

Often all is needed is these small helpers, instead of compiler.h
or a full kprobes.h. This is important for asm helpers, in fact even
some asm/kprobes.h make use of these helpers... instead just keep a
generic asm file with helpers useful for asm code with the least amount
of clutter as possible.

Likewise we need now to also address what to do about this file for both
when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
for when architectures have CONFIG_HAVE_KPROBES but have disabled
CONFIG_KPROBES.

Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
this means most architecture code cannot include asm/kprobes.h safely.
Correct this and add guards for architectures missing them. Additionally
provide architectures that not have kprobes support with the default
asm-generic solution. This lets us force asm/kprobes.h on the header
include/linux/kprobes.h always, but most importantly we can now safely
include just asm/kprobes.h on architecture code without bringing
the full kitchen sink of header files.

Two architectures already provided a guard against CONFIG_KPROBES on
its kprobes.h: sh, arch. The rest of the architectures needed gaurds
added. We avoid including any not-needed headers on asm/kprobes.h
unless kprobes have been enabled.

In a subsequent atomic change we can try now to remove compiler.h from
include/linux/kprobes.h.

During this sweep I've also identified a few architectures defining
a common macro needed for both kprobes and ftrace, that of the
definition of the breakput instruction up. Some refer to this as
BREAKPOINT_INSTRUCTION. This must be kept outside of the #ifdef
CONFIG_KPROBES guard.

v5:

o fix BREAKPOINT_INSTRUCTION dependency with kernel architecture
  ftrace implementations:  Although its correct to #ifdef CONFIG_KPROBES
  on the architecture arch/$(ARCH)/include/asm/kprobes.h when
  architectures support ftrace they will rely on the
  BREAKPOINT_INSTRUCTION definition, this needs to be kept out from
  CONFIG_KPROBES as ftrace can be enabled without kprobes. This
  fixes compilation on x86 where kprobes is disabled but ftrace is
  left enabled.

o include <asm/kprobes.h> on arch/arm64/kernel/probes/decode-insn.h

v4: introduced this patch into the series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/alpha/include/asm/Kbuild          |  1 +
 arch/arc/include/asm/kprobes.h         |  6 ++++--
 arch/arm/include/asm/kprobes.h         |  4 ++++
 arch/arm/probes/decode.h               |  1 +
 arch/arm64/include/asm/kprobes.h       |  4 ++++
 arch/arm64/kernel/insn.c               |  1 +
 arch/arm64/kernel/probes/decode-insn.h |  2 ++
 arch/avr32/include/asm/kprobes.h       |  7 ++++++-
 arch/blackfin/include/asm/Kbuild       |  1 +
 arch/c6x/include/asm/Kbuild            |  1 +
 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/kprobes.h        | 12 +++++++++---
 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/kprobes.h        |  6 +++++-
 arch/mn10300/include/asm/kprobes.h     |  7 ++++++-
 arch/nios2/include/asm/Kbuild          |  1 +
 arch/openrisc/include/asm/Kbuild       |  1 +
 arch/parisc/include/asm/Kbuild         |  1 +
 arch/powerpc/include/asm/kprobes.h     |  3 +++
 arch/s390/include/asm/kprobes.h        |  7 ++++++-
 arch/score/include/asm/Kbuild          |  1 +
 arch/sh/include/asm/kprobes.h          |  5 ++++-
 arch/sparc/include/asm/kprobes.h       | 10 ++++++++--
 arch/tile/include/asm/kprobes.h        |  6 +++++-
 arch/um/include/asm/Kbuild             |  1 +
 arch/unicore32/include/asm/Kbuild      |  1 +
 arch/x86/include/asm/kprobes.h         |  9 ++++++++-
 arch/xtensa/include/asm/Kbuild         |  1 +
 include/asm-generic/kprobes.h          | 25 +++++++++++++++++++++++++
 include/linux/compiler.h               |  8 --------
 include/linux/kprobes.h                | 19 +++----------------
 37 files changed, 122 insertions(+), 38 deletions(-)
 create mode 100644 include/asm-generic/kprobes.h

diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index f3bdc31d3c97..54d388fd026f 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += trace_clock.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/arc/include/asm/kprobes.h b/arch/arc/include/asm/kprobes.h
index 944dbedb38b5..00bdbe167615 100644
--- a/arch/arc/include/asm/kprobes.h
+++ b/arch/arc/include/asm/kprobes.h
@@ -9,6 +9,8 @@
 #ifndef _ARC_KPROBES_H
 #define _ARC_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
 #ifdef CONFIG_KPROBES
 
 typedef u16 kprobe_opcode_t;
@@ -55,6 +57,6 @@ void trap_is_kprobe(unsigned long address, struct pt_regs *regs);
 static void trap_is_kprobe(unsigned long address, struct pt_regs *regs)
 {
 }
-#endif
+#endif /* CONFIG_KPROBES */
 
-#endif
+#endif /* _ARC_KPROBES_H */
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index 3ea9be559726..59655459da59 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/notifier.h>
@@ -83,4 +86,5 @@ struct arch_optimized_insn {
 	 */
 };
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm/probes/decode.h b/arch/arm/probes/decode.h
index f9b08ba7fe73..548d622a3159 100644
--- a/arch/arm/probes/decode.h
+++ b/arch/arm/probes/decode.h
@@ -22,6 +22,7 @@
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <asm/probes.h>
+#include <asm/kprobes.h>
 
 void __init arm_probes_decode_init(void);
 
diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
index 1737aecfcc5e..6deb8d726041 100644
--- a/arch/arm64/include/asm/kprobes.h
+++ b/arch/arm64/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -57,4 +60,5 @@ int kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr);
 void kretprobe_trampoline(void);
 void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 94b62c1fa4df..ae912304ed84 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -31,6 +31,7 @@
 #include <asm/debug-monitors.h>
 #include <asm/fixmap.h>
 #include <asm/insn.h>
+#include <asm/kprobes.h>
 
 #define AARCH64_INSN_SF_BIT	BIT(31)
 #define AARCH64_INSN_N_BIT	BIT(22)
diff --git a/arch/arm64/kernel/probes/decode-insn.h b/arch/arm64/kernel/probes/decode-insn.h
index 76d3f315407f..192ab007bacb 100644
--- a/arch/arm64/kernel/probes/decode-insn.h
+++ b/arch/arm64/kernel/probes/decode-insn.h
@@ -16,6 +16,8 @@
 #ifndef _ARM_KERNEL_KPROBES_ARM64_H
 #define _ARM_KERNEL_KPROBES_ARM64_H
 
+#include <asm/kprobes.h>
+
 /*
  * ARM strongly recommends a limit of 128 bytes between LoadExcl and
  * StoreExcl instructions in a single thread of execution. So keep the
diff --git a/arch/avr32/include/asm/kprobes.h b/arch/avr32/include/asm/kprobes.h
index 45f563ed73fd..28dfc61ad384 100644
--- a/arch/avr32/include/asm/kprobes.h
+++ b/arch/avr32/include/asm/kprobes.h
@@ -11,10 +11,14 @@
 #ifndef __ASM_AVR32_KPROBES_H
 #define __ASM_AVR32_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xd673	/* breakpoint */
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 
 typedef u16	kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xd673	/* breakpoint */
 #define MAX_INSN_SIZE		2
 #define MAX_STACK_SIZE		64	/* 32 would probably be OK */
 
@@ -46,4 +50,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif /* __ASM_AVR32_KPROBES_H */
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 9115b215fc7e..52351d3fd36e 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -50,3 +50,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index cede2a950fbf..c54f7cc1f63e 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
+generic-y += kprobes.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 7062c1be7913..051d355feae3 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 4a59cbda5091..b58b9fc49383 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index d79968d93c12..cfca7de52b37 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -78,3 +78,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index d59ac1c1858b..d7cc35451f30 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/ia64/include/asm/kprobes.h b/arch/ia64/include/asm/kprobes.h
index d5505d6f2382..0302b3664789 100644
--- a/arch/ia64/include/asm/kprobes.h
+++ b/arch/ia64/include/asm/kprobes.h
@@ -23,14 +23,19 @@
  * 2005-Apr     Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
  *              <anil.s.keshavamurthy@intel.com> adapted from i386
  */
+#include <asm-generic/kprobes.h>
+#include <asm/break.h>
+
+#define BREAK_INST	(long)(__IA64_BREAK_KPROBE << 6)
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
-#include <asm/break.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
 #define MAX_INSN_SIZE   2	/* last half is for kprobe-booster */
-#define BREAK_INST	(long)(__IA64_BREAK_KPROBE << 6)
 #define NOP_M_INST	(long)(1<<27)
 #define BRL_INST(i1, i2) ((long)((0xcL << 37) |	/* brl */ \
 				(0x1L << 12) |	/* many */ \
@@ -124,4 +129,5 @@ extern void invalidate_stacked_regs(void);
 extern void flush_register_stack(void);
 extern void arch_remove_kprobe(struct kprobe *p);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 24088f3c733c..198ad591ab41 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index c28bcdecc764..412dd23ab946 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -37,3 +37,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index c836f7e2a5e7..8371cc9b1b3c 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -58,3 +58,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index 01afb1b420f5..865ce3d96443 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/mips/include/asm/kprobes.h b/arch/mips/include/asm/kprobes.h
index daba1f9a4f79..291846d9ba83 100644
--- a/arch/mips/include/asm/kprobes.h
+++ b/arch/mips/include/asm/kprobes.h
@@ -22,6 +22,9 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/ptrace.h>
 #include <linux/types.h>
 
@@ -94,4 +97,5 @@ struct kprobe_ctlblk {
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/mn10300/include/asm/kprobes.h b/arch/mn10300/include/asm/kprobes.h
index c800b590183a..7abea0bdb549 100644
--- a/arch/mn10300/include/asm/kprobes.h
+++ b/arch/mn10300/include/asm/kprobes.h
@@ -21,13 +21,17 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xff
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 
 struct kprobe;
 
 typedef unsigned char kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xff
 #define MAX_INSN_SIZE 8
 #define MAX_STACK_SIZE 128
 
@@ -47,4 +51,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 extern void arch_remove_kprobe(struct kprobe *p);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_KPROBES_H */
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index ee6220dac1e8..d6ce7edee7e0 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -66,3 +66,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index ceafe458e295..1bf89a67317c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -74,3 +74,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index aaae8a9f6099..19d5b7e12ecf 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -31,3 +31,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h
index 97b8c1f83453..c7ee3fcbd6e2 100644
--- a/arch/powerpc/include/asm/kprobes.h
+++ b/arch/powerpc/include/asm/kprobes.h
@@ -1,5 +1,8 @@
 #ifndef _ASM_POWERPC_KPROBES_H
 #define _ASM_POWERPC_KPROBES_H
+
+#include <asm-generic/kprobes.h>
+
 #ifdef __KERNEL__
 /*
  *  Kernel Probes (KProbes)
diff --git a/arch/s390/include/asm/kprobes.h b/arch/s390/include/asm/kprobes.h
index 591e5a5279b0..84c0f9086483 100644
--- a/arch/s390/include/asm/kprobes.h
+++ b/arch/s390/include/asm/kprobes.h
@@ -27,6 +27,11 @@
  * 2005-Dec	Used as a template for s390 by Mike Grundy
  *		<grundym@us.ibm.com>
  */
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0x0002
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -37,7 +42,6 @@ struct pt_regs;
 struct kprobe;
 
 typedef u16 kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0x0002
 
 /* Maximum instruction size is 3 (16bit) halfwords: */
 #define MAX_INSN_SIZE		0x0003
@@ -91,4 +95,5 @@ int probe_is_insn_relative_long(u16 *insn);
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif	/* _ASM_S390_KPROBES_H */
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index 16ea15a3e432..6ac8a7f5c768 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -17,3 +17,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h
index 134f3980e44a..f0986f9b3844 100644
--- a/arch/sh/include/asm/kprobes.h
+++ b/arch/sh/include/asm/kprobes.h
@@ -1,13 +1,16 @@
 #ifndef __ASM_SH_KPROBES_H
 #define __ASM_SH_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xc33a
+
 #ifdef CONFIG_KPROBES
 
 #include <linux/types.h>
 #include <linux/ptrace.h>
 
 typedef insn_size_t kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xc33a
 
 #define MAX_INSN_SIZE 16
 #define MAX_STACK_SIZE 64
diff --git a/arch/sparc/include/asm/kprobes.h b/arch/sparc/include/asm/kprobes.h
index a145d798e112..49f8402035d7 100644
--- a/arch/sparc/include/asm/kprobes.h
+++ b/arch/sparc/include/asm/kprobes.h
@@ -1,13 +1,17 @@
 #ifndef _SPARC64_KPROBES_H
 #define _SPARC64_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION   0x91d02070 /* ta 0x70 */
+#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/percpu.h>
 
 typedef u32 kprobe_opcode_t;
 
-#define BREAKPOINT_INSTRUCTION   0x91d02070 /* ta 0x70 */
-#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
 #define MAX_INSN_SIZE 2
 
 #define kretprobe_blacklist_size 0
@@ -48,4 +52,6 @@ int kprobe_exceptions_notify(struct notifier_block *self,
 int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
 				      struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _SPARC64_KPROBES_H */
diff --git a/arch/tile/include/asm/kprobes.h b/arch/tile/include/asm/kprobes.h
index d8f9a83943b1..4a8b1cadca24 100644
--- a/arch/tile/include/asm/kprobes.h
+++ b/arch/tile/include/asm/kprobes.h
@@ -17,10 +17,13 @@
 #ifndef _ASM_TILE_KPROBES_H
 #define _ASM_TILE_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
-
 #include <arch/opcode.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
@@ -76,4 +79,5 @@ void arch_remove_kprobe(struct kprobe *);
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 			     unsigned long val, void *data);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_TILE_KPROBES_H */
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index d2867aa09e23..ccc5ffeaeef5 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 6671a1f08ead..5aacafb6d385 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h
index d1d1e5094c28..200581691c6e 100644
--- a/arch/x86/include/asm/kprobes.h
+++ b/arch/x86/include/asm/kprobes.h
@@ -21,6 +21,12 @@
  *
  * See arch/x86/kernel/kprobes.c for x86 kprobes history.
  */
+
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xcc
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -32,7 +38,6 @@ struct pt_regs;
 struct kprobe;
 
 typedef u8 kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xcc
 #define RELATIVEJUMP_OPCODE 0xe9
 #define RELATIVEJUMP_SIZE 5
 #define RELATIVECALL_OPCODE 0xe8
@@ -116,4 +121,6 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 extern int kprobe_int3_handler(struct pt_regs *regs);
 extern int kprobe_debug_handler(struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_X86_KPROBES_H */
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index 7b41f32a2ba0..20f524ded00e 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
new file mode 100644
index 000000000000..57af9f21d148
--- /dev/null
+++ b/include/asm-generic/kprobes.h
@@ -0,0 +1,25 @@
+#ifndef _ASM_GENERIC_KPROBES_H
+#define _ASM_GENERIC_KPROBES_H
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#ifdef CONFIG_KPROBES
+/*
+ * Blacklist ganerating macro. Specify functions which is not probed
+ * by using this macro.
+ */
+# define __NOKPROBE_SYMBOL(fname)				\
+static unsigned long __used					\
+	__attribute__((__section__("_kprobe_blacklist")))	\
+	_kbl_addr_##fname = (unsigned long)fname;
+# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
+/* Use this to forbid a kprobes attach on very low level functions */
+# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define nokprobe_inline	__always_inline
+#else
+# define NOKPROBE_SYMBOL(fname)
+# define __kprobes
+# define nokprobe_inline	inline
+#endif
+#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
+
+#endif /* _ASM_GENERIC_KPROBES_H */
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index cf0fa5d86059..dca49b4099da 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -566,12 +566,4 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 	(_________p1); \
 })
 
-/* Ignore/forbid kprobes attach on very low level functions marked by this attribute: */
-#ifdef CONFIG_KPROBES
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
-# define nokprobe_inline	__always_inline
-#else
-# define __kprobes
-# define nokprobe_inline	inline
-#endif
 #endif /* __LINUX_COMPILER_H */
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 8f6849084248..985ed79ef431 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -29,7 +29,7 @@
  *		<jkenisto@us.ibm.com>  and Prasanna S Panchamukhi
  *		<prasanna@in.ibm.com> added function-return probes.
  */
-#include <linux/compiler.h>	/* for __kprobes */
+#include <linux/compiler.h>
 #include <linux/linkage.h>
 #include <linux/list.h>
 #include <linux/notifier.h>
@@ -40,9 +40,9 @@
 #include <linux/rcupdate.h>
 #include <linux/mutex.h>
 #include <linux/ftrace.h>
+#include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
-#include <asm/kprobes.h>
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
@@ -51,6 +51,7 @@
 #define KPROBE_HIT_SSDONE	0x00000008
 
 #else /* CONFIG_KPROBES */
+#include <asm-generic/kprobes.h>
 typedef int kprobe_opcode_t;
 struct arch_specific_insn {
 	int dummy;
@@ -481,18 +482,4 @@ static inline int enable_jprobe(struct jprobe *jp)
 	return enable_kprobe(&jp->kp);
 }
 
-#ifdef CONFIG_KPROBES
-/*
- * Blacklist ganerating macro. Specify functions which is not probed
- * by using this macro.
- */
-#define __NOKPROBE_SYMBOL(fname)			\
-static unsigned long __used				\
-	__attribute__((section("_kprobe_blacklist")))	\
-	_kbl_addr_##fname = (unsigned long)fname;
-#define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
-#else
-#define NOKPROBE_SYMBOL(fname)
-#endif
-
 #endif /* _LINUX_KPROBES_H */
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 12/14] kprobes: port .kprobes.text to section range
  2016-12-22  2:37     ` Luis R. Rodriguez
  (?)
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

kprobe makes use of two custom sections, each custom section
is folded into one of the standard Linux sections types as follows,
it currently relies on the linker script to fold the custom section
onto the respective Linux section:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist
range .text         .kprobes.text        __kprobes_text_start     __kprobes_text_end

This ports the .kprobes.text custom section to the standard
Linux ranges API allowing us remove all the custom kprobe section
declarations from the linker script.

Tested with CONFIG_KPROBES_SANITY_TEST, it passes with:

Kprobe smoke test: started
Kprobe smoke test: passed successfully

Then tested CONFIG_SAMPLE_KPROBES on do_fork, and the kprobe bites
and kicks as expected.

Also ran ./ftracetest with no issues:

sudo ./ftracetest
== Ftrace unit tests =[1] Basic trace file check	[PASS]
[2] Basic test for tracers	[PASS]
[3] Basic trace clock test	[PASS]
[4] Basic event tracing check	[PASS]
[5] event tracing - enable/disable with event level files	[PASS]
[6] event tracing - restricts events based on pid	[PASS]
[7] event tracing - enable/disable with subsystem level files	[PASS]
[8] event tracing - enable/disable with top level files	[PASS]
[9] ftrace - function graph filters with stack tracer	[PASS]
[10] ftrace - function graph filters	[PASS]
[11] ftrace - function glob filters	[PASS]
[12] ftrace - function profiler with function tracing	[PASS]
[13] Test creation and deletion of trace instances while setting an event	[PASS]
[14] Test creation and deletion of trace instances	[PASS]
[15] Kprobe dynamic event - adding and removing	[PASS]
[16] Kprobe dynamic event - busy event check	[PASS]
[17] Kprobe dynamic event with arguments	[PASS]
[18] Kprobes event arguments with types	[PASS]
[19] Kprobe dynamic event with function tracer	[PASS]
[20] Kretprobe dynamic event with arguments	[PASS]
[21] event trigger - test event enable/disable trigger	[PASS]
[22] event trigger - test trigger filter	[PASS]
[23] event trigger - test histogram modifiers	[PASS]
[24] event trigger - test histogram trigger	[PASS]
[25] event trigger - test multiple histogram triggers	[PASS]
[26] event trigger - test snapshot-trigger	[PASS]
[27] event trigger - test stacktrace-trigger	[PASS]
[28] event trigger - test traceon/off trigger	[PASS]

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

v4:

o arm64 build fixes with allmodconfig

o build fix suggested for avr32 with allnoconfig, otherwise we end up with:

arch/avr32/kernel/built-in.o: In function `save_full_context_ex':
(.ex.text+0x1c4): relocation truncated to fit: R_AVR32_16N_PCREL against
symbol `debug_trampoline' defined in .text.rng.kprobes.any section in
arch/avr32/kernel/built-in.o
arch/avr32/kernel/built-in.o: In function `debug_exit_work':
(.text.rng.kprobes.any+0xa8): relocation truncated to fit:
R_AVR32_16N_PCREL against `.ex.text'+3aa
make: *** [Makefile:953: vmlinux] Error 1

o open-code section use on scripts/ code -- folks to prefer the
  simplicity over dealing with having more tool code access kernel
  headers.

o NOPE: include #include <asm-generic/ranges.h> on compiler.h -- solves
  a few 0-day compilation issues

v3:

o after v2 arch/arm/kernel/vmlinux-xip.lds.S got kprobe support,
  this just removes the custom linker script reference to kprobes as
  that is no longer needed with linker tables.

o split kprobe linker table and kprobe section ranges use into
  two separate patches. This should make it easier to review and
  also demos both distinct use types, one a linker table another
  a simple section range.

v2: introduced this patch in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arc/kernel/vmlinux.lds.S        |  1 -
 arch/arm/kernel/entry-armv.S         |  3 ++-
 arch/arm/kernel/vmlinux-xip.lds.S    |  1 -
 arch/arm/kernel/vmlinux.lds.S        |  1 -
 arch/arm64/kernel/armv8_deprecated.c |  1 +
 arch/arm64/kernel/probes/kprobes.c   |  4 ++--
 arch/arm64/kernel/vmlinux.lds.S      |  1 -
 arch/avr32/kernel/entry-avr32b.S     | 13 +++++++++++--
 arch/avr32/kernel/vmlinux.lds.S      |  1 -
 arch/blackfin/kernel/vmlinux.lds.S   |  1 -
 arch/c6x/kernel/vmlinux.lds.S        |  1 -
 arch/hexagon/kernel/vmlinux.lds.S    |  1 -
 arch/ia64/kernel/jprobes.S           |  3 ++-
 arch/ia64/kernel/vmlinux.lds.S       |  1 -
 arch/ia64/lib/flush.S                |  6 +++---
 arch/metag/kernel/vmlinux.lds.S      |  1 -
 arch/microblaze/kernel/vmlinux.lds.S |  1 -
 arch/mips/kernel/vmlinux.lds.S       |  1 -
 arch/mn10300/kernel/vmlinux.lds.S    |  1 -
 arch/nios2/kernel/vmlinux.lds.S      |  1 -
 arch/openrisc/kernel/vmlinux.lds.S   |  1 -
 arch/parisc/kernel/vmlinux.lds.S     |  1 -
 arch/powerpc/include/asm/ppc_asm.h   |  1 +
 arch/powerpc/kernel/vmlinux.lds.S    |  1 -
 arch/s390/kernel/entry.S             |  5 +++--
 arch/s390/kernel/kprobes.c           |  6 +++---
 arch/s390/kernel/mcount.S            |  3 ++-
 arch/s390/kernel/vmlinux.lds.S       |  1 -
 arch/score/kernel/vmlinux.lds.S      |  1 -
 arch/sh/kernel/vmlinux.lds.S         |  1 -
 arch/sparc/kernel/vmlinux.lds.S      |  1 -
 arch/sparc/mm/ultra.S                |  3 ++-
 arch/tile/kernel/vmlinux.lds.S       |  1 -
 arch/x86/kernel/kprobes/core.c       | 11 +++++------
 arch/x86/kernel/vmlinux.lds.S        |  1 -
 include/asm-generic/kprobes.h        |  3 ++-
 include/asm-generic/sections.h       |  2 --
 include/asm-generic/vmlinux.lds.h    |  2 +-
 include/linux/kprobes.h              |  3 +++
 kernel/kprobes.c                     |  6 ++++--
 scripts/mod/modpost.c                |  2 +-
 scripts/recordmcount.c               |  2 +-
 scripts/recordmcount.pl              |  2 +-
 43 files changed, 50 insertions(+), 54 deletions(-)

diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S
index f35ed578e007..dd05c86eb96e 100644
--- a/arch/arc/kernel/vmlinux.lds.S
+++ b/arch/arc/kernel/vmlinux.lds.S
@@ -91,7 +91,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 9f157e7c51e7..c455b491b6d3 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -34,6 +34,7 @@
 #include "entry-header.S"
 #include <asm/entry-macro-multi.S>
 #include <asm/probes.h>
+#include <asm/ranges.h>
 
 /*
  * Interrupt handling.
@@ -83,7 +84,7 @@
 	.endm
 
 #ifdef CONFIG_KPROBES
-	.section	.kprobes.text,"ax",%progbits
+	set_section_rng_type(.text, kprobes, ax, %progbits)
 #else
 	.text
 #endif
diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S
index 37b2a11af345..1a84f84b8165 100644
--- a/arch/arm/kernel/vmlinux-xip.lds.S
+++ b/arch/arm/kernel/vmlinux-xip.lds.S
@@ -103,7 +103,6 @@ SECTIONS
 			SCHED_TEXT
 			CPUIDLE_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index f7f55df0bf7b..1e278e6c3506 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -114,7 +114,6 @@ SECTIONS
 			CPUIDLE_TEXT
 			LOCK_TEXT
 			HYPERVISOR_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index 04de188a36c9..b509a68af3c4 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -21,6 +21,7 @@
 #include <asm/traps.h>
 #include <asm/uaccess.h>
 #include <asm/cpufeature.h>
+#include <asm/kprobes.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace-events-emulation.h"
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index 1decd2b2c730..7fbcfdf4e9e2 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/stop_machine.h>
 #include <linux/stringify.h>
+#include <linux/ranges.h>
 #include <asm/traps.h>
 #include <asm/ptrace.h>
 #include <asm/cacheflush.h>
@@ -540,8 +541,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
-	if ((addr >= (unsigned long)__kprobes_text_start &&
-	    addr < (unsigned long)__kprobes_text_end) ||
+	if (SECTION_RANGE_ADDR_WITHIN(kprobes, addr) ||
 	    (addr >= (unsigned long)__entry_text_start &&
 	    addr < (unsigned long)__entry_text_end) ||
 	    (addr >= (unsigned long)__idmap_text_start &&
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index b8deffa9e1bf..c68e5d528706 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -124,7 +124,6 @@ SECTIONS
 			SCHED_TEXT
 			CPUIDLE_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			HYPERVISOR_TEXT
 			IDMAP_TEXT
 			HIBERNATE_TEXT
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index 7301f4806bbe..7b2a5c5ef047 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -23,6 +23,7 @@
 #include <asm/sysreg.h>
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
+#include <asm/ranges.h>
 
 #ifdef CONFIG_PREEMPT
 # define preempt_stop		mask_interrupts
@@ -605,7 +606,11 @@ fault_exit_work:
 	brcc	fault_resume_user
 	rjmp	enter_monitor_mode
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(.text, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	handle_debug, @function
 handle_debug:
 	sub	sp, 4		/* r12_orig */
@@ -826,7 +831,11 @@ irq_level\level:
 	IRQ_LEVEL 2
 	IRQ_LEVEL 3
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(.text, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	enter_monitor_mode, @function
 enter_monitor_mode:
 	/*
diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S
index 17f2730eb497..04627a9c178e 100644
--- a/arch/avr32/kernel/vmlinux.lds.S
+++ b/arch/avr32/kernel/vmlinux.lds.S
@@ -49,7 +49,6 @@ SECTIONS
 		_stext = .;
 		*(.ex.text)
 		*(.irq.text)
-		KPROBES_TEXT
 		TEXT_TEXT
 		SCHED_TEXT
 		CPUIDLE_TEXT
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 68069a120055..93220ff65014 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -37,7 +37,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 #ifdef CONFIG_ROMKERNEL
 		__sinittext = .;
 		INIT_TEXT
diff --git a/arch/c6x/kernel/vmlinux.lds.S b/arch/c6x/kernel/vmlinux.lds.S
index a1a5c166bc9b..a41d43b8254b 100644
--- a/arch/c6x/kernel/vmlinux.lds.S
+++ b/arch/c6x/kernel/vmlinux.lds.S
@@ -74,7 +74,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S
index ec87e67feb19..7e6f68584b55 100644
--- a/arch/hexagon/kernel/vmlinux.lds.S
+++ b/arch/hexagon/kernel/vmlinux.lds.S
@@ -52,7 +52,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 	}
 	_etext = .;
diff --git a/arch/ia64/kernel/jprobes.S b/arch/ia64/kernel/jprobes.S
index f69389c7be1d..71adc7132e22 100644
--- a/arch/ia64/kernel/jprobes.S
+++ b/arch/ia64/kernel/jprobes.S
@@ -46,11 +46,12 @@
  */
 #include <asm/asmmacro.h>
 #include <asm/break.h>
+#include <asm/ranges.h>
 
 	/*
 	 * void jprobe_break(void)
 	 */
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 ENTRY(jprobe_break)
 	break.m __IA64_BREAK_JPROBE
 END(jprobe_break)
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index f89d20c97412..3ff6edf913d2 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -48,7 +48,6 @@ SECTIONS {
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.gnu.linkonce.t*)
 	}
 
diff --git a/arch/ia64/lib/flush.S b/arch/ia64/lib/flush.S
index 9a5a2f9fad13..dec1b180d618 100644
--- a/arch/ia64/lib/flush.S
+++ b/arch/ia64/lib/flush.S
@@ -9,7 +9,7 @@
 
 #include <asm/asmmacro.h>
 #include <asm/export.h>
-
+#include <asm/ranges.h>
 
 	/*
 	 * flush_icache_range(start,end)
@@ -21,7 +21,7 @@
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(.text, kprobes, ax)
 GLOBAL_ENTRY(flush_icache_range)
 
 	.prologue
@@ -74,7 +74,7 @@ EXPORT_SYMBOL_GPL(flush_icache_range)
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(.text, kprobes, ax)
 GLOBAL_ENTRY(clflush_cache_range)
 
 	.prologue
diff --git a/arch/metag/kernel/vmlinux.lds.S b/arch/metag/kernel/vmlinux.lds.S
index e6c700eaf207..b18386d2250f 100644
--- a/arch/metag/kernel/vmlinux.lds.S
+++ b/arch/metag/kernel/vmlinux.lds.S
@@ -23,7 +23,6 @@ SECTIONS
 	SCHED_TEXT
 	CPUIDLE_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	IRQENTRY_TEXT
 	SOFTIRQENTRY_TEXT
 	*(.text.*)
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
index 289d0e7f3e3a..aadee2229ac6 100644
--- a/arch/microblaze/kernel/vmlinux.lds.S
+++ b/arch/microblaze/kernel/vmlinux.lds.S
@@ -35,7 +35,6 @@ SECTIONS {
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		. = ALIGN (4) ;
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index f0a0e6d62be3..44e21812c544 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -57,7 +57,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.*)
diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S
index 2d5f1c3f1afb..552ef00a3da5 100644
--- a/arch/mn10300/kernel/vmlinux.lds.S
+++ b/arch/mn10300/kernel/vmlinux.lds.S
@@ -32,7 +32,6 @@ SECTIONS
 	SCHED_TEXT
 	CPUIDLE_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0xcb
diff --git a/arch/nios2/kernel/vmlinux.lds.S b/arch/nios2/kernel/vmlinux.lds.S
index 6a8045bb1a77..aae4a00c4056 100644
--- a/arch/nios2/kernel/vmlinux.lds.S
+++ b/arch/nios2/kernel/vmlinux.lds.S
@@ -41,7 +41,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 	} =0
 	_etext = .;
 
diff --git a/arch/openrisc/kernel/vmlinux.lds.S b/arch/openrisc/kernel/vmlinux.lds.S
index 514f474249b0..bbf3b8acf5d3 100644
--- a/arch/openrisc/kernel/vmlinux.lds.S
+++ b/arch/openrisc/kernel/vmlinux.lds.S
@@ -55,7 +55,6 @@ SECTIONS
 	  SCHED_TEXT
 	  CPUIDLE_TEXT
 	  LOCK_TEXT
-	  KPROBES_TEXT
 	  IRQENTRY_TEXT
 	  SOFTIRQENTRY_TEXT
 	  *(.fixup)
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 3d6ef1b29c6a..edbd6d9487dc 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -71,7 +71,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.do_softirq)
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 025833b8df9f..0846413b3a2e 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,6 +9,7 @@
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
 #include <asm/firmware.h>
+#include <asm/ranges.h>
 
 #ifdef __ASSEMBLY__
 
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 8cd940c72895..2285664abb52 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -112,7 +112,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		MEM_KEEP(init.text)
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 97298c58b2be..847e2e1df89c 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -24,6 +24,7 @@
 #include <asm/setup.h>
 #include <asm/nmi.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
 __PT_R0      =	__PT_GPRS
 __PT_R1      =	__PT_GPRS + 8
@@ -169,7 +170,7 @@ _PIF_WORK	= (_PIF_PER_TRAP)
 		tm	off+\addr, \mask
 	.endm
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 .Ldummy:
 	/*
 	 * This nop exists only in order to avoid that __switch_to starts at
@@ -986,7 +987,7 @@ ENTRY(restart_int_handler)
 	brc	2,2b
 3:	j	3b
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 
 #ifdef CONFIG_CHECK_STACK
 /*
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index fdb40424acfe..d49241fef651 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -289,9 +289,9 @@ static void kprobe_reenter_check(struct kprobe_ctlblk *kcb, struct kprobe *p)
 	case KPROBE_REENTER:
 	default:
 		/*
-		 * A kprobe on the code path to single step an instruction
-		 * is a BUG. The code path resides in the .kprobes.text
-		 * section and is executed with interrupts disabled.
+		 * A kprobe on the code path to single step an instruction is a
+		 * BUG. The code path resides in the kprobes section range and
+		 * is executed with interrupts disabled.
 		 */
 		printk(KERN_EMERG "Invalid kprobe detected at %p.\n", p->addr);
 		dump_kprobe(p);
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S
index 9a17e4475d27..9d76056609f7 100644
--- a/arch/s390/kernel/mcount.S
+++ b/arch/s390/kernel/mcount.S
@@ -10,8 +10,9 @@
 #include <asm/ftrace.h>
 #include <asm/ptrace.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 
 ENTRY(ftrace_stub)
 	br	%r14
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 3667d20e997f..b2df6d9bab09 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -37,7 +37,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/score/kernel/vmlinux.lds.S b/arch/score/kernel/vmlinux.lds.S
index 4117890b1db1..a8b14f3ed474 100644
--- a/arch/score/kernel/vmlinux.lds.S
+++ b/arch/score/kernel/vmlinux.lds.S
@@ -42,7 +42,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.text.*)
 		*(.fixup)
 		. = ALIGN (4) ;
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 5b9a3cc90c58..58d9ba796f7a 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -38,7 +38,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 572db686f845..0ee41b0071e5 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -51,7 +51,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.gnu.warning)
diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S
index 5d2fd6cd3189..ee9f648549c0 100644
--- a/arch/sparc/mm/ultra.S
+++ b/arch/sparc/mm/ultra.S
@@ -16,6 +16,7 @@
 #include <asm/cacheflush.h>
 #include <asm/hypervisor.h>
 #include <asm/cpudata.h>
+#include <asm/ranges.h>
 
 	/* Basically, most of the Spitfire vs. Cheetah madness
 	 * has to do with the fact that Cheetah does not support
@@ -185,7 +186,7 @@ __spitfire_flush_tlb_mm_slow:
 /*
  * The following code flushes one page_size worth.
  */
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 	.align		32
 	.globl		__flush_icache_page
 __flush_icache_page:	/* %o0 = phys_page */
diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S
index e1baf094fba4..85d03ce6c0a0 100644
--- a/arch/tile/kernel/vmlinux.lds.S
+++ b/arch/tile/kernel/vmlinux.lds.S
@@ -44,7 +44,6 @@ SECTIONS
     SCHED_TEXT
     CPUIDLE_TEXT
     LOCK_TEXT
-    KPROBES_TEXT
     IRQENTRY_TEXT
     SOFTIRQENTRY_TEXT
     __fix_text_end = .;   /* tile-cpack won't rearrange before this */
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index d9d8d16b69db..b28be8dd14c6 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -580,9 +580,9 @@ static int reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
 	case KPROBE_REENTER:
 		/* A probe has been hit in the codepath leading up to, or just
 		 * after, single-stepping of a probed instruction. This entire
-		 * codepath should strictly reside in .kprobes.text section.
-		 * Raise a BUG or we'll continue in an endless reentering loop
-		 * and eventually a stack overflow.
+		 * codepath should strictly reside in the kprobes section
+		 * range. Raise a BUG or we'll continue in an endless
+		 * reentering loop and eventually a stack overflow.
 		 */
 		printk(KERN_WARNING "Unrecoverable kprobe detected at %p.\n",
 		       p->addr);
@@ -1133,10 +1133,9 @@ NOKPROBE_SYMBOL(longjmp_break_handler);
 
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
-	return  (addr >= (unsigned long)__kprobes_text_start &&
-		 addr < (unsigned long)__kprobes_text_end) ||
+	return  (SECTION_RANGE_ADDR_WITHIN(kprobes, addr) ||
 		(addr >= (unsigned long)__entry_text_start &&
-		 addr < (unsigned long)__entry_text_end);
+		 addr < (unsigned long)__entry_text_end));
 }
 
 int __init arch_init_kprobes(void)
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index e79f15f108a8..4c16fadb9ac6 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -99,7 +99,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		ENTRY_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 57af9f21d148..02a26b975187 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,6 +3,7 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
@@ -13,7 +14,7 @@ static unsigned long __used					\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define __kprobes	__LINUX_RANGE(.text, kprobes)
 # define nokprobe_inline	__always_inline
 #else
 # define NOKPROBE_SYMBOL(fname)
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index b145ae8d9cbe..f3340f2772bb 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -26,7 +26,6 @@
  * Following global variables are optional and may be unavailable on some
  * architectures and/or kernel configurations.
  *	_text, _data
- *	__kprobes_text_start, __kprobes_text_end
  *	__entry_text_start, __entry_text_end
  *	__ctors_start, __ctors_end
  */
@@ -38,7 +37,6 @@ extern char _sinittext[], _einittext[];
 extern char __start_data_ro_after_init[], __end_data_ro_after_init[];
 extern char _end[];
 extern char __per_cpu_load[], __per_cpu_start[], __per_cpu_end[];
-extern char __kprobes_text_start[], __kprobes_text_end[];
 extern char __entry_text_start[], __entry_text_end[];
 extern char __start_rodata[], __end_rodata[];
 
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 37b99537d5a9..499caf5b4361 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -471,7 +471,7 @@
 #define KPROBES_TEXT							\
 		ALIGN_FUNCTION();					\
 		VMLINUX_SYMBOL(__kprobes_text_start) = .;		\
-		*(.kprobes.text)					\
+		*(.text..rng.kprobes.any)				\
 		VMLINUX_SYMBOL(__kprobes_text_end) = .;
 
 #define ENTRY_TEXT							\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 985ed79ef431..445cc6fe7afa 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -43,6 +43,9 @@
 #include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
+#include <linux/ranges.h>
+
+DECLARE_SECTION_RANGE(kprobes);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index d63095472ea9..c79f0b04383f 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1328,8 +1328,7 @@ static int register_aggr_kprobe(struct kprobe *orig_p, struct kprobe *p)
 bool __weak arch_within_kprobe_blacklist(unsigned long addr)
 {
 	/* The __kprobes marked functions and entry code must not be probed */
-	return addr >= (unsigned long)__kprobes_text_start &&
-	       addr < (unsigned long)__kprobes_text_end;
+	return SECTION_RANGE_ADDR_WITHIN(kprobes, addr);
 }
 
 bool within_kprobe_blacklist(unsigned long addr)
@@ -2129,6 +2128,9 @@ static struct notifier_block kprobe_module_nb = {
 extern unsigned long __start_kprobe_blacklist[];
 extern unsigned long __stop_kprobe_blacklist[];
 
+/* Actual kprobes section range */
+DEFINE_SECTION_RANGE(kprobes, .text);
+
 static int __init init_kprobes(void)
 {
 	int i, err = 0;
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 29c89a6bad3d..2b442234c69b 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -894,7 +894,7 @@ static void check_section(const char *modname, struct elf_info *elf,
 
 #define DATA_SECTIONS ".data", ".data.rel"
 #define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \
-		".kprobes.text", ".cpuidle.text"
+		".text..rng.kprobes.any", ".cpuidle.text"
 #define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
 		".fixup", ".entry.text", ".exception.text", ".text.*", \
 		".coldtext"
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index aeb34223167c..6e95f3f87db1 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -417,7 +417,7 @@ is_mcounted_section_name(char const *const txtname)
 		strcmp(".spinlock.text", txtname) = 0 ||
 		strcmp(".irqentry.text", txtname) = 0 ||
 		strcmp(".softirqentry.text", txtname) = 0 ||
-		strcmp(".kprobes.text", txtname) = 0 ||
+		strcmp(".text..rng.kprobes.any", txtname) = 0 ||
 		strcmp(".cpuidle.text", txtname) = 0 ||
 		strcmp(".text.unlikely", txtname) = 0;
 }
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 0b6002b36f20..15e2fa37c489 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -135,7 +135,7 @@ my %text_sections = (
      ".spinlock.text" => 1,
      ".irqentry.text" => 1,
      ".softirqentry.text" => 1,
-     ".kprobes.text" => 1,
+     ".text..rng.kprobes.any" => 1,
      ".cpuidle.text" => 1,
      ".text.unlikely" => 1,
 );
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 12/14] kprobes: port .kprobes.text to section range
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

kprobe makes use of two custom sections, each custom section
is folded into one of the standard Linux sections types as follows,
it currently relies on the linker script to fold the custom section
onto the respective Linux section:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist
range .text         .kprobes.text        __kprobes_text_start     __kprobes_text_end

This ports the .kprobes.text custom section to the standard
Linux ranges API allowing us remove all the custom kprobe section
declarations from the linker script.

Tested with CONFIG_KPROBES_SANITY_TEST, it passes with:

Kprobe smoke test: started
Kprobe smoke test: passed successfully

Then tested CONFIG_SAMPLE_KPROBES on do_fork, and the kprobe bites
and kicks as expected.

Also ran ./ftracetest with no issues:

sudo ./ftracetest
=== Ftrace unit tests ===
[1] Basic trace file check	[PASS]
[2] Basic test for tracers	[PASS]
[3] Basic trace clock test	[PASS]
[4] Basic event tracing check	[PASS]
[5] event tracing - enable/disable with event level files	[PASS]
[6] event tracing - restricts events based on pid	[PASS]
[7] event tracing - enable/disable with subsystem level files	[PASS]
[8] event tracing - enable/disable with top level files	[PASS]
[9] ftrace - function graph filters with stack tracer	[PASS]
[10] ftrace - function graph filters	[PASS]
[11] ftrace - function glob filters	[PASS]
[12] ftrace - function profiler with function tracing	[PASS]
[13] Test creation and deletion of trace instances while setting an event	[PASS]
[14] Test creation and deletion of trace instances	[PASS]
[15] Kprobe dynamic event - adding and removing	[PASS]
[16] Kprobe dynamic event - busy event check	[PASS]
[17] Kprobe dynamic event with arguments	[PASS]
[18] Kprobes event arguments with types	[PASS]
[19] Kprobe dynamic event with function tracer	[PASS]
[20] Kretprobe dynamic event with arguments	[PASS]
[21] event trigger - test event enable/disable trigger	[PASS]
[22] event trigger - test trigger filter	[PASS]
[23] event trigger - test histogram modifiers	[PASS]
[24] event trigger - test histogram trigger	[PASS]
[25] event trigger - test multiple histogram triggers	[PASS]
[26] event trigger - test snapshot-trigger	[PASS]
[27] event trigger - test stacktrace-trigger	[PASS]
[28] event trigger - test traceon/off trigger	[PASS]

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

v4:

o arm64 build fixes with allmodconfig

o build fix suggested for avr32 with allnoconfig, otherwise we end up with:

arch/avr32/kernel/built-in.o: In function `save_full_context_ex':
(.ex.text+0x1c4): relocation truncated to fit: R_AVR32_16N_PCREL against
symbol `debug_trampoline' defined in .text.rng.kprobes.any section in
arch/avr32/kernel/built-in.o
arch/avr32/kernel/built-in.o: In function `debug_exit_work':
(.text.rng.kprobes.any+0xa8): relocation truncated to fit:
R_AVR32_16N_PCREL against `.ex.text'+3aa
make: *** [Makefile:953: vmlinux] Error 1

o open-code section use on scripts/ code -- folks to prefer the
  simplicity over dealing with having more tool code access kernel
  headers.

o NOPE: include #include <asm-generic/ranges.h> on compiler.h -- solves
  a few 0-day compilation issues

v3:

o after v2 arch/arm/kernel/vmlinux-xip.lds.S got kprobe support,
  this just removes the custom linker script reference to kprobes as
  that is no longer needed with linker tables.

o split kprobe linker table and kprobe section ranges use into
  two separate patches. This should make it easier to review and
  also demos both distinct use types, one a linker table another
  a simple section range.

v2: introduced this patch in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arc/kernel/vmlinux.lds.S        |  1 -
 arch/arm/kernel/entry-armv.S         |  3 ++-
 arch/arm/kernel/vmlinux-xip.lds.S    |  1 -
 arch/arm/kernel/vmlinux.lds.S        |  1 -
 arch/arm64/kernel/armv8_deprecated.c |  1 +
 arch/arm64/kernel/probes/kprobes.c   |  4 ++--
 arch/arm64/kernel/vmlinux.lds.S      |  1 -
 arch/avr32/kernel/entry-avr32b.S     | 13 +++++++++++--
 arch/avr32/kernel/vmlinux.lds.S      |  1 -
 arch/blackfin/kernel/vmlinux.lds.S   |  1 -
 arch/c6x/kernel/vmlinux.lds.S        |  1 -
 arch/hexagon/kernel/vmlinux.lds.S    |  1 -
 arch/ia64/kernel/jprobes.S           |  3 ++-
 arch/ia64/kernel/vmlinux.lds.S       |  1 -
 arch/ia64/lib/flush.S                |  6 +++---
 arch/metag/kernel/vmlinux.lds.S      |  1 -
 arch/microblaze/kernel/vmlinux.lds.S |  1 -
 arch/mips/kernel/vmlinux.lds.S       |  1 -
 arch/mn10300/kernel/vmlinux.lds.S    |  1 -
 arch/nios2/kernel/vmlinux.lds.S      |  1 -
 arch/openrisc/kernel/vmlinux.lds.S   |  1 -
 arch/parisc/kernel/vmlinux.lds.S     |  1 -
 arch/powerpc/include/asm/ppc_asm.h   |  1 +
 arch/powerpc/kernel/vmlinux.lds.S    |  1 -
 arch/s390/kernel/entry.S             |  5 +++--
 arch/s390/kernel/kprobes.c           |  6 +++---
 arch/s390/kernel/mcount.S            |  3 ++-
 arch/s390/kernel/vmlinux.lds.S       |  1 -
 arch/score/kernel/vmlinux.lds.S      |  1 -
 arch/sh/kernel/vmlinux.lds.S         |  1 -
 arch/sparc/kernel/vmlinux.lds.S      |  1 -
 arch/sparc/mm/ultra.S                |  3 ++-
 arch/tile/kernel/vmlinux.lds.S       |  1 -
 arch/x86/kernel/kprobes/core.c       | 11 +++++------
 arch/x86/kernel/vmlinux.lds.S        |  1 -
 include/asm-generic/kprobes.h        |  3 ++-
 include/asm-generic/sections.h       |  2 --
 include/asm-generic/vmlinux.lds.h    |  2 +-
 include/linux/kprobes.h              |  3 +++
 kernel/kprobes.c                     |  6 ++++--
 scripts/mod/modpost.c                |  2 +-
 scripts/recordmcount.c               |  2 +-
 scripts/recordmcount.pl              |  2 +-
 43 files changed, 50 insertions(+), 54 deletions(-)

diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S
index f35ed578e007..dd05c86eb96e 100644
--- a/arch/arc/kernel/vmlinux.lds.S
+++ b/arch/arc/kernel/vmlinux.lds.S
@@ -91,7 +91,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 9f157e7c51e7..c455b491b6d3 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -34,6 +34,7 @@
 #include "entry-header.S"
 #include <asm/entry-macro-multi.S>
 #include <asm/probes.h>
+#include <asm/ranges.h>
 
 /*
  * Interrupt handling.
@@ -83,7 +84,7 @@
 	.endm
 
 #ifdef CONFIG_KPROBES
-	.section	.kprobes.text,"ax",%progbits
+	set_section_rng_type(.text, kprobes, ax, %progbits)
 #else
 	.text
 #endif
diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S
index 37b2a11af345..1a84f84b8165 100644
--- a/arch/arm/kernel/vmlinux-xip.lds.S
+++ b/arch/arm/kernel/vmlinux-xip.lds.S
@@ -103,7 +103,6 @@ SECTIONS
 			SCHED_TEXT
 			CPUIDLE_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index f7f55df0bf7b..1e278e6c3506 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -114,7 +114,6 @@ SECTIONS
 			CPUIDLE_TEXT
 			LOCK_TEXT
 			HYPERVISOR_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index 04de188a36c9..b509a68af3c4 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -21,6 +21,7 @@
 #include <asm/traps.h>
 #include <asm/uaccess.h>
 #include <asm/cpufeature.h>
+#include <asm/kprobes.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace-events-emulation.h"
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index 1decd2b2c730..7fbcfdf4e9e2 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/stop_machine.h>
 #include <linux/stringify.h>
+#include <linux/ranges.h>
 #include <asm/traps.h>
 #include <asm/ptrace.h>
 #include <asm/cacheflush.h>
@@ -540,8 +541,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
-	if ((addr >= (unsigned long)__kprobes_text_start &&
-	    addr < (unsigned long)__kprobes_text_end) ||
+	if (SECTION_RANGE_ADDR_WITHIN(kprobes, addr) ||
 	    (addr >= (unsigned long)__entry_text_start &&
 	    addr < (unsigned long)__entry_text_end) ||
 	    (addr >= (unsigned long)__idmap_text_start &&
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index b8deffa9e1bf..c68e5d528706 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -124,7 +124,6 @@ SECTIONS
 			SCHED_TEXT
 			CPUIDLE_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			HYPERVISOR_TEXT
 			IDMAP_TEXT
 			HIBERNATE_TEXT
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index 7301f4806bbe..7b2a5c5ef047 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -23,6 +23,7 @@
 #include <asm/sysreg.h>
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
+#include <asm/ranges.h>
 
 #ifdef CONFIG_PREEMPT
 # define preempt_stop		mask_interrupts
@@ -605,7 +606,11 @@ fault_exit_work:
 	brcc	fault_resume_user
 	rjmp	enter_monitor_mode
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(.text, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	handle_debug, @function
 handle_debug:
 	sub	sp, 4		/* r12_orig */
@@ -826,7 +831,11 @@ irq_level\level:
 	IRQ_LEVEL 2
 	IRQ_LEVEL 3
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(.text, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	enter_monitor_mode, @function
 enter_monitor_mode:
 	/*
diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S
index 17f2730eb497..04627a9c178e 100644
--- a/arch/avr32/kernel/vmlinux.lds.S
+++ b/arch/avr32/kernel/vmlinux.lds.S
@@ -49,7 +49,6 @@ SECTIONS
 		_stext = .;
 		*(.ex.text)
 		*(.irq.text)
-		KPROBES_TEXT
 		TEXT_TEXT
 		SCHED_TEXT
 		CPUIDLE_TEXT
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 68069a120055..93220ff65014 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -37,7 +37,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 #ifdef CONFIG_ROMKERNEL
 		__sinittext = .;
 		INIT_TEXT
diff --git a/arch/c6x/kernel/vmlinux.lds.S b/arch/c6x/kernel/vmlinux.lds.S
index a1a5c166bc9b..a41d43b8254b 100644
--- a/arch/c6x/kernel/vmlinux.lds.S
+++ b/arch/c6x/kernel/vmlinux.lds.S
@@ -74,7 +74,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S
index ec87e67feb19..7e6f68584b55 100644
--- a/arch/hexagon/kernel/vmlinux.lds.S
+++ b/arch/hexagon/kernel/vmlinux.lds.S
@@ -52,7 +52,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 	}
 	_etext = .;
diff --git a/arch/ia64/kernel/jprobes.S b/arch/ia64/kernel/jprobes.S
index f69389c7be1d..71adc7132e22 100644
--- a/arch/ia64/kernel/jprobes.S
+++ b/arch/ia64/kernel/jprobes.S
@@ -46,11 +46,12 @@
  */
 #include <asm/asmmacro.h>
 #include <asm/break.h>
+#include <asm/ranges.h>
 
 	/*
 	 * void jprobe_break(void)
 	 */
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 ENTRY(jprobe_break)
 	break.m __IA64_BREAK_JPROBE
 END(jprobe_break)
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index f89d20c97412..3ff6edf913d2 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -48,7 +48,6 @@ SECTIONS {
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.gnu.linkonce.t*)
 	}
 
diff --git a/arch/ia64/lib/flush.S b/arch/ia64/lib/flush.S
index 9a5a2f9fad13..dec1b180d618 100644
--- a/arch/ia64/lib/flush.S
+++ b/arch/ia64/lib/flush.S
@@ -9,7 +9,7 @@
 
 #include <asm/asmmacro.h>
 #include <asm/export.h>
-
+#include <asm/ranges.h>
 
 	/*
 	 * flush_icache_range(start,end)
@@ -21,7 +21,7 @@
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(.text, kprobes, ax)
 GLOBAL_ENTRY(flush_icache_range)
 
 	.prologue
@@ -74,7 +74,7 @@ EXPORT_SYMBOL_GPL(flush_icache_range)
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(.text, kprobes, ax)
 GLOBAL_ENTRY(clflush_cache_range)
 
 	.prologue
diff --git a/arch/metag/kernel/vmlinux.lds.S b/arch/metag/kernel/vmlinux.lds.S
index e6c700eaf207..b18386d2250f 100644
--- a/arch/metag/kernel/vmlinux.lds.S
+++ b/arch/metag/kernel/vmlinux.lds.S
@@ -23,7 +23,6 @@ SECTIONS
 	SCHED_TEXT
 	CPUIDLE_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	IRQENTRY_TEXT
 	SOFTIRQENTRY_TEXT
 	*(.text.*)
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
index 289d0e7f3e3a..aadee2229ac6 100644
--- a/arch/microblaze/kernel/vmlinux.lds.S
+++ b/arch/microblaze/kernel/vmlinux.lds.S
@@ -35,7 +35,6 @@ SECTIONS {
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		. = ALIGN (4) ;
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index f0a0e6d62be3..44e21812c544 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -57,7 +57,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.*)
diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S
index 2d5f1c3f1afb..552ef00a3da5 100644
--- a/arch/mn10300/kernel/vmlinux.lds.S
+++ b/arch/mn10300/kernel/vmlinux.lds.S
@@ -32,7 +32,6 @@ SECTIONS
 	SCHED_TEXT
 	CPUIDLE_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0xcb
diff --git a/arch/nios2/kernel/vmlinux.lds.S b/arch/nios2/kernel/vmlinux.lds.S
index 6a8045bb1a77..aae4a00c4056 100644
--- a/arch/nios2/kernel/vmlinux.lds.S
+++ b/arch/nios2/kernel/vmlinux.lds.S
@@ -41,7 +41,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 	} =0
 	_etext = .;
 
diff --git a/arch/openrisc/kernel/vmlinux.lds.S b/arch/openrisc/kernel/vmlinux.lds.S
index 514f474249b0..bbf3b8acf5d3 100644
--- a/arch/openrisc/kernel/vmlinux.lds.S
+++ b/arch/openrisc/kernel/vmlinux.lds.S
@@ -55,7 +55,6 @@ SECTIONS
 	  SCHED_TEXT
 	  CPUIDLE_TEXT
 	  LOCK_TEXT
-	  KPROBES_TEXT
 	  IRQENTRY_TEXT
 	  SOFTIRQENTRY_TEXT
 	  *(.fixup)
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 3d6ef1b29c6a..edbd6d9487dc 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -71,7 +71,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.do_softirq)
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 025833b8df9f..0846413b3a2e 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,6 +9,7 @@
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
 #include <asm/firmware.h>
+#include <asm/ranges.h>
 
 #ifdef __ASSEMBLY__
 
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 8cd940c72895..2285664abb52 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -112,7 +112,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		MEM_KEEP(init.text)
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 97298c58b2be..847e2e1df89c 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -24,6 +24,7 @@
 #include <asm/setup.h>
 #include <asm/nmi.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
 __PT_R0      =	__PT_GPRS
 __PT_R1      =	__PT_GPRS + 8
@@ -169,7 +170,7 @@ _PIF_WORK	= (_PIF_PER_TRAP)
 		tm	off+\addr, \mask
 	.endm
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 .Ldummy:
 	/*
 	 * This nop exists only in order to avoid that __switch_to starts at
@@ -986,7 +987,7 @@ ENTRY(restart_int_handler)
 	brc	2,2b
 3:	j	3b
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 
 #ifdef CONFIG_CHECK_STACK
 /*
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index fdb40424acfe..d49241fef651 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -289,9 +289,9 @@ static void kprobe_reenter_check(struct kprobe_ctlblk *kcb, struct kprobe *p)
 	case KPROBE_REENTER:
 	default:
 		/*
-		 * A kprobe on the code path to single step an instruction
-		 * is a BUG. The code path resides in the .kprobes.text
-		 * section and is executed with interrupts disabled.
+		 * A kprobe on the code path to single step an instruction is a
+		 * BUG. The code path resides in the kprobes section range and
+		 * is executed with interrupts disabled.
 		 */
 		printk(KERN_EMERG "Invalid kprobe detected at %p.\n", p->addr);
 		dump_kprobe(p);
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S
index 9a17e4475d27..9d76056609f7 100644
--- a/arch/s390/kernel/mcount.S
+++ b/arch/s390/kernel/mcount.S
@@ -10,8 +10,9 @@
 #include <asm/ftrace.h>
 #include <asm/ptrace.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 
 ENTRY(ftrace_stub)
 	br	%r14
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 3667d20e997f..b2df6d9bab09 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -37,7 +37,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/score/kernel/vmlinux.lds.S b/arch/score/kernel/vmlinux.lds.S
index 4117890b1db1..a8b14f3ed474 100644
--- a/arch/score/kernel/vmlinux.lds.S
+++ b/arch/score/kernel/vmlinux.lds.S
@@ -42,7 +42,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.text.*)
 		*(.fixup)
 		. = ALIGN (4) ;
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 5b9a3cc90c58..58d9ba796f7a 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -38,7 +38,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 572db686f845..0ee41b0071e5 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -51,7 +51,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.gnu.warning)
diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S
index 5d2fd6cd3189..ee9f648549c0 100644
--- a/arch/sparc/mm/ultra.S
+++ b/arch/sparc/mm/ultra.S
@@ -16,6 +16,7 @@
 #include <asm/cacheflush.h>
 #include <asm/hypervisor.h>
 #include <asm/cpudata.h>
+#include <asm/ranges.h>
 
 	/* Basically, most of the Spitfire vs. Cheetah madness
 	 * has to do with the fact that Cheetah does not support
@@ -185,7 +186,7 @@ __spitfire_flush_tlb_mm_slow:
 /*
  * The following code flushes one page_size worth.
  */
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 	.align		32
 	.globl		__flush_icache_page
 __flush_icache_page:	/* %o0 = phys_page */
diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S
index e1baf094fba4..85d03ce6c0a0 100644
--- a/arch/tile/kernel/vmlinux.lds.S
+++ b/arch/tile/kernel/vmlinux.lds.S
@@ -44,7 +44,6 @@ SECTIONS
     SCHED_TEXT
     CPUIDLE_TEXT
     LOCK_TEXT
-    KPROBES_TEXT
     IRQENTRY_TEXT
     SOFTIRQENTRY_TEXT
     __fix_text_end = .;   /* tile-cpack won't rearrange before this */
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index d9d8d16b69db..b28be8dd14c6 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -580,9 +580,9 @@ static int reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
 	case KPROBE_REENTER:
 		/* A probe has been hit in the codepath leading up to, or just
 		 * after, single-stepping of a probed instruction. This entire
-		 * codepath should strictly reside in .kprobes.text section.
-		 * Raise a BUG or we'll continue in an endless reentering loop
-		 * and eventually a stack overflow.
+		 * codepath should strictly reside in the kprobes section
+		 * range. Raise a BUG or we'll continue in an endless
+		 * reentering loop and eventually a stack overflow.
 		 */
 		printk(KERN_WARNING "Unrecoverable kprobe detected at %p.\n",
 		       p->addr);
@@ -1133,10 +1133,9 @@ NOKPROBE_SYMBOL(longjmp_break_handler);
 
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
-	return  (addr >= (unsigned long)__kprobes_text_start &&
-		 addr < (unsigned long)__kprobes_text_end) ||
+	return  (SECTION_RANGE_ADDR_WITHIN(kprobes, addr) ||
 		(addr >= (unsigned long)__entry_text_start &&
-		 addr < (unsigned long)__entry_text_end);
+		 addr < (unsigned long)__entry_text_end));
 }
 
 int __init arch_init_kprobes(void)
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index e79f15f108a8..4c16fadb9ac6 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -99,7 +99,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		ENTRY_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 57af9f21d148..02a26b975187 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,6 +3,7 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
@@ -13,7 +14,7 @@ static unsigned long __used					\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define __kprobes	__LINUX_RANGE(.text, kprobes)
 # define nokprobe_inline	__always_inline
 #else
 # define NOKPROBE_SYMBOL(fname)
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index b145ae8d9cbe..f3340f2772bb 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -26,7 +26,6 @@
  * Following global variables are optional and may be unavailable on some
  * architectures and/or kernel configurations.
  *	_text, _data
- *	__kprobes_text_start, __kprobes_text_end
  *	__entry_text_start, __entry_text_end
  *	__ctors_start, __ctors_end
  */
@@ -38,7 +37,6 @@ extern char _sinittext[], _einittext[];
 extern char __start_data_ro_after_init[], __end_data_ro_after_init[];
 extern char _end[];
 extern char __per_cpu_load[], __per_cpu_start[], __per_cpu_end[];
-extern char __kprobes_text_start[], __kprobes_text_end[];
 extern char __entry_text_start[], __entry_text_end[];
 extern char __start_rodata[], __end_rodata[];
 
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 37b99537d5a9..499caf5b4361 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -471,7 +471,7 @@
 #define KPROBES_TEXT							\
 		ALIGN_FUNCTION();					\
 		VMLINUX_SYMBOL(__kprobes_text_start) = .;		\
-		*(.kprobes.text)					\
+		*(.text..rng.kprobes.any)				\
 		VMLINUX_SYMBOL(__kprobes_text_end) = .;
 
 #define ENTRY_TEXT							\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 985ed79ef431..445cc6fe7afa 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -43,6 +43,9 @@
 #include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
+#include <linux/ranges.h>
+
+DECLARE_SECTION_RANGE(kprobes);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index d63095472ea9..c79f0b04383f 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1328,8 +1328,7 @@ static int register_aggr_kprobe(struct kprobe *orig_p, struct kprobe *p)
 bool __weak arch_within_kprobe_blacklist(unsigned long addr)
 {
 	/* The __kprobes marked functions and entry code must not be probed */
-	return addr >= (unsigned long)__kprobes_text_start &&
-	       addr < (unsigned long)__kprobes_text_end;
+	return SECTION_RANGE_ADDR_WITHIN(kprobes, addr);
 }
 
 bool within_kprobe_blacklist(unsigned long addr)
@@ -2129,6 +2128,9 @@ static struct notifier_block kprobe_module_nb = {
 extern unsigned long __start_kprobe_blacklist[];
 extern unsigned long __stop_kprobe_blacklist[];
 
+/* Actual kprobes section range */
+DEFINE_SECTION_RANGE(kprobes, .text);
+
 static int __init init_kprobes(void)
 {
 	int i, err = 0;
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 29c89a6bad3d..2b442234c69b 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -894,7 +894,7 @@ static void check_section(const char *modname, struct elf_info *elf,
 
 #define DATA_SECTIONS ".data", ".data.rel"
 #define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \
-		".kprobes.text", ".cpuidle.text"
+		".text..rng.kprobes.any", ".cpuidle.text"
 #define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
 		".fixup", ".entry.text", ".exception.text", ".text.*", \
 		".coldtext"
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index aeb34223167c..6e95f3f87db1 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -417,7 +417,7 @@ is_mcounted_section_name(char const *const txtname)
 		strcmp(".spinlock.text", txtname) == 0 ||
 		strcmp(".irqentry.text", txtname) == 0 ||
 		strcmp(".softirqentry.text", txtname) == 0 ||
-		strcmp(".kprobes.text", txtname) == 0 ||
+		strcmp(".text..rng.kprobes.any", txtname) == 0 ||
 		strcmp(".cpuidle.text", txtname) == 0 ||
 		strcmp(".text.unlikely", txtname) == 0;
 }
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 0b6002b36f20..15e2fa37c489 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -135,7 +135,7 @@ my %text_sections = (
      ".spinlock.text" => 1,
      ".irqentry.text" => 1,
      ".softirqentry.text" => 1,
-     ".kprobes.text" => 1,
+     ".text..rng.kprobes.any" => 1,
      ".cpuidle.text" => 1,
      ".text.unlikely" => 1,
 );
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 12/14] kprobes: port .kprobes.text to section range
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

kprobe makes use of two custom sections, each custom section
is folded into one of the standard Linux sections types as follows,
it currently relies on the linker script to fold the custom section
onto the respective Linux section:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist
range .text         .kprobes.text        __kprobes_text_start     __kprobes_text_end

This ports the .kprobes.text custom section to the standard
Linux ranges API allowing us remove all the custom kprobe section
declarations from the linker script.

Tested with CONFIG_KPROBES_SANITY_TEST, it passes with:

Kprobe smoke test: started
Kprobe smoke test: passed successfully

Then tested CONFIG_SAMPLE_KPROBES on do_fork, and the kprobe bites
and kicks as expected.

Also ran ./ftracetest with no issues:

sudo ./ftracetest
=== Ftrace unit tests ===
[1] Basic trace file check	[PASS]
[2] Basic test for tracers	[PASS]
[3] Basic trace clock test	[PASS]
[4] Basic event tracing check	[PASS]
[5] event tracing - enable/disable with event level files	[PASS]
[6] event tracing - restricts events based on pid	[PASS]
[7] event tracing - enable/disable with subsystem level files	[PASS]
[8] event tracing - enable/disable with top level files	[PASS]
[9] ftrace - function graph filters with stack tracer	[PASS]
[10] ftrace - function graph filters	[PASS]
[11] ftrace - function glob filters	[PASS]
[12] ftrace - function profiler with function tracing	[PASS]
[13] Test creation and deletion of trace instances while setting an event	[PASS]
[14] Test creation and deletion of trace instances	[PASS]
[15] Kprobe dynamic event - adding and removing	[PASS]
[16] Kprobe dynamic event - busy event check	[PASS]
[17] Kprobe dynamic event with arguments	[PASS]
[18] Kprobes event arguments with types	[PASS]
[19] Kprobe dynamic event with function tracer	[PASS]
[20] Kretprobe dynamic event with arguments	[PASS]
[21] event trigger - test event enable/disable trigger	[PASS]
[22] event trigger - test trigger filter	[PASS]
[23] event trigger - test histogram modifiers	[PASS]
[24] event trigger - test histogram trigger	[PASS]
[25] event trigger - test multiple histogram triggers	[PASS]
[26] event trigger - test snapshot-trigger	[PASS]
[27] event trigger - test stacktrace-trigger	[PASS]
[28] event trigger - test traceon/off trigger	[PASS]

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

v4:

o arm64 build fixes with allmodconfig

o build fix suggested for avr32 with allnoconfig, otherwise we end up with:

arch/avr32/kernel/built-in.o: In function `save_full_context_ex':
(.ex.text+0x1c4): relocation truncated to fit: R_AVR32_16N_PCREL against
symbol `debug_trampoline' defined in .text.rng.kprobes.any section in
arch/avr32/kernel/built-in.o
arch/avr32/kernel/built-in.o: In function `debug_exit_work':
(.text.rng.kprobes.any+0xa8): relocation truncated to fit:
R_AVR32_16N_PCREL against `.ex.text'+3aa
make: *** [Makefile:953: vmlinux] Error 1

o open-code section use on scripts/ code -- folks to prefer the
  simplicity over dealing with having more tool code access kernel
  headers.

o NOPE: include #include <asm-generic/ranges.h> on compiler.h -- solves
  a few 0-day compilation issues

v3:

o after v2 arch/arm/kernel/vmlinux-xip.lds.S got kprobe support,
  this just removes the custom linker script reference to kprobes as
  that is no longer needed with linker tables.

o split kprobe linker table and kprobe section ranges use into
  two separate patches. This should make it easier to review and
  also demos both distinct use types, one a linker table another
  a simple section range.

v2: introduced this patch in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arc/kernel/vmlinux.lds.S        |  1 -
 arch/arm/kernel/entry-armv.S         |  3 ++-
 arch/arm/kernel/vmlinux-xip.lds.S    |  1 -
 arch/arm/kernel/vmlinux.lds.S        |  1 -
 arch/arm64/kernel/armv8_deprecated.c |  1 +
 arch/arm64/kernel/probes/kprobes.c   |  4 ++--
 arch/arm64/kernel/vmlinux.lds.S      |  1 -
 arch/avr32/kernel/entry-avr32b.S     | 13 +++++++++++--
 arch/avr32/kernel/vmlinux.lds.S      |  1 -
 arch/blackfin/kernel/vmlinux.lds.S   |  1 -
 arch/c6x/kernel/vmlinux.lds.S        |  1 -
 arch/hexagon/kernel/vmlinux.lds.S    |  1 -
 arch/ia64/kernel/jprobes.S           |  3 ++-
 arch/ia64/kernel/vmlinux.lds.S       |  1 -
 arch/ia64/lib/flush.S                |  6 +++---
 arch/metag/kernel/vmlinux.lds.S      |  1 -
 arch/microblaze/kernel/vmlinux.lds.S |  1 -
 arch/mips/kernel/vmlinux.lds.S       |  1 -
 arch/mn10300/kernel/vmlinux.lds.S    |  1 -
 arch/nios2/kernel/vmlinux.lds.S      |  1 -
 arch/openrisc/kernel/vmlinux.lds.S   |  1 -
 arch/parisc/kernel/vmlinux.lds.S     |  1 -
 arch/powerpc/include/asm/ppc_asm.h   |  1 +
 arch/powerpc/kernel/vmlinux.lds.S    |  1 -
 arch/s390/kernel/entry.S             |  5 +++--
 arch/s390/kernel/kprobes.c           |  6 +++---
 arch/s390/kernel/mcount.S            |  3 ++-
 arch/s390/kernel/vmlinux.lds.S       |  1 -
 arch/score/kernel/vmlinux.lds.S      |  1 -
 arch/sh/kernel/vmlinux.lds.S         |  1 -
 arch/sparc/kernel/vmlinux.lds.S      |  1 -
 arch/sparc/mm/ultra.S                |  3 ++-
 arch/tile/kernel/vmlinux.lds.S       |  1 -
 arch/x86/kernel/kprobes/core.c       | 11 +++++------
 arch/x86/kernel/vmlinux.lds.S        |  1 -
 include/asm-generic/kprobes.h        |  3 ++-
 include/asm-generic/sections.h       |  2 --
 include/asm-generic/vmlinux.lds.h    |  2 +-
 include/linux/kprobes.h              |  3 +++
 kernel/kprobes.c                     |  6 ++++--
 scripts/mod/modpost.c                |  2 +-
 scripts/recordmcount.c               |  2 +-
 scripts/recordmcount.pl              |  2 +-
 43 files changed, 50 insertions(+), 54 deletions(-)

diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S
index f35ed578e007..dd05c86eb96e 100644
--- a/arch/arc/kernel/vmlinux.lds.S
+++ b/arch/arc/kernel/vmlinux.lds.S
@@ -91,7 +91,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 9f157e7c51e7..c455b491b6d3 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -34,6 +34,7 @@
 #include "entry-header.S"
 #include <asm/entry-macro-multi.S>
 #include <asm/probes.h>
+#include <asm/ranges.h>
 
 /*
  * Interrupt handling.
@@ -83,7 +84,7 @@
 	.endm
 
 #ifdef CONFIG_KPROBES
-	.section	.kprobes.text,"ax",%progbits
+	set_section_rng_type(.text, kprobes, ax, %progbits)
 #else
 	.text
 #endif
diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S
index 37b2a11af345..1a84f84b8165 100644
--- a/arch/arm/kernel/vmlinux-xip.lds.S
+++ b/arch/arm/kernel/vmlinux-xip.lds.S
@@ -103,7 +103,6 @@ SECTIONS
 			SCHED_TEXT
 			CPUIDLE_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index f7f55df0bf7b..1e278e6c3506 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -114,7 +114,6 @@ SECTIONS
 			CPUIDLE_TEXT
 			LOCK_TEXT
 			HYPERVISOR_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index 04de188a36c9..b509a68af3c4 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -21,6 +21,7 @@
 #include <asm/traps.h>
 #include <asm/uaccess.h>
 #include <asm/cpufeature.h>
+#include <asm/kprobes.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace-events-emulation.h"
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index 1decd2b2c730..7fbcfdf4e9e2 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/stop_machine.h>
 #include <linux/stringify.h>
+#include <linux/ranges.h>
 #include <asm/traps.h>
 #include <asm/ptrace.h>
 #include <asm/cacheflush.h>
@@ -540,8 +541,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
-	if ((addr >= (unsigned long)__kprobes_text_start &&
-	    addr < (unsigned long)__kprobes_text_end) ||
+	if (SECTION_RANGE_ADDR_WITHIN(kprobes, addr) ||
 	    (addr >= (unsigned long)__entry_text_start &&
 	    addr < (unsigned long)__entry_text_end) ||
 	    (addr >= (unsigned long)__idmap_text_start &&
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index b8deffa9e1bf..c68e5d528706 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -124,7 +124,6 @@ SECTIONS
 			SCHED_TEXT
 			CPUIDLE_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			HYPERVISOR_TEXT
 			IDMAP_TEXT
 			HIBERNATE_TEXT
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index 7301f4806bbe..7b2a5c5ef047 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -23,6 +23,7 @@
 #include <asm/sysreg.h>
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
+#include <asm/ranges.h>
 
 #ifdef CONFIG_PREEMPT
 # define preempt_stop		mask_interrupts
@@ -605,7 +606,11 @@ fault_exit_work:
 	brcc	fault_resume_user
 	rjmp	enter_monitor_mode
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(.text, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	handle_debug, @function
 handle_debug:
 	sub	sp, 4		/* r12_orig */
@@ -826,7 +831,11 @@ irq_level\level:
 	IRQ_LEVEL 2
 	IRQ_LEVEL 3
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(.text, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	enter_monitor_mode, @function
 enter_monitor_mode:
 	/*
diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S
index 17f2730eb497..04627a9c178e 100644
--- a/arch/avr32/kernel/vmlinux.lds.S
+++ b/arch/avr32/kernel/vmlinux.lds.S
@@ -49,7 +49,6 @@ SECTIONS
 		_stext = .;
 		*(.ex.text)
 		*(.irq.text)
-		KPROBES_TEXT
 		TEXT_TEXT
 		SCHED_TEXT
 		CPUIDLE_TEXT
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 68069a120055..93220ff65014 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -37,7 +37,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 #ifdef CONFIG_ROMKERNEL
 		__sinittext = .;
 		INIT_TEXT
diff --git a/arch/c6x/kernel/vmlinux.lds.S b/arch/c6x/kernel/vmlinux.lds.S
index a1a5c166bc9b..a41d43b8254b 100644
--- a/arch/c6x/kernel/vmlinux.lds.S
+++ b/arch/c6x/kernel/vmlinux.lds.S
@@ -74,7 +74,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S
index ec87e67feb19..7e6f68584b55 100644
--- a/arch/hexagon/kernel/vmlinux.lds.S
+++ b/arch/hexagon/kernel/vmlinux.lds.S
@@ -52,7 +52,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 	}
 	_etext = .;
diff --git a/arch/ia64/kernel/jprobes.S b/arch/ia64/kernel/jprobes.S
index f69389c7be1d..71adc7132e22 100644
--- a/arch/ia64/kernel/jprobes.S
+++ b/arch/ia64/kernel/jprobes.S
@@ -46,11 +46,12 @@
  */
 #include <asm/asmmacro.h>
 #include <asm/break.h>
+#include <asm/ranges.h>
 
 	/*
 	 * void jprobe_break(void)
 	 */
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 ENTRY(jprobe_break)
 	break.m __IA64_BREAK_JPROBE
 END(jprobe_break)
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index f89d20c97412..3ff6edf913d2 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -48,7 +48,6 @@ SECTIONS {
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.gnu.linkonce.t*)
 	}
 
diff --git a/arch/ia64/lib/flush.S b/arch/ia64/lib/flush.S
index 9a5a2f9fad13..dec1b180d618 100644
--- a/arch/ia64/lib/flush.S
+++ b/arch/ia64/lib/flush.S
@@ -9,7 +9,7 @@
 
 #include <asm/asmmacro.h>
 #include <asm/export.h>
-
+#include <asm/ranges.h>
 
 	/*
 	 * flush_icache_range(start,end)
@@ -21,7 +21,7 @@
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(.text, kprobes, ax)
 GLOBAL_ENTRY(flush_icache_range)
 
 	.prologue
@@ -74,7 +74,7 @@ EXPORT_SYMBOL_GPL(flush_icache_range)
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(.text, kprobes, ax)
 GLOBAL_ENTRY(clflush_cache_range)
 
 	.prologue
diff --git a/arch/metag/kernel/vmlinux.lds.S b/arch/metag/kernel/vmlinux.lds.S
index e6c700eaf207..b18386d2250f 100644
--- a/arch/metag/kernel/vmlinux.lds.S
+++ b/arch/metag/kernel/vmlinux.lds.S
@@ -23,7 +23,6 @@ SECTIONS
 	SCHED_TEXT
 	CPUIDLE_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	IRQENTRY_TEXT
 	SOFTIRQENTRY_TEXT
 	*(.text.*)
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
index 289d0e7f3e3a..aadee2229ac6 100644
--- a/arch/microblaze/kernel/vmlinux.lds.S
+++ b/arch/microblaze/kernel/vmlinux.lds.S
@@ -35,7 +35,6 @@ SECTIONS {
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		. = ALIGN (4) ;
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index f0a0e6d62be3..44e21812c544 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -57,7 +57,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.*)
diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S
index 2d5f1c3f1afb..552ef00a3da5 100644
--- a/arch/mn10300/kernel/vmlinux.lds.S
+++ b/arch/mn10300/kernel/vmlinux.lds.S
@@ -32,7 +32,6 @@ SECTIONS
 	SCHED_TEXT
 	CPUIDLE_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0xcb
diff --git a/arch/nios2/kernel/vmlinux.lds.S b/arch/nios2/kernel/vmlinux.lds.S
index 6a8045bb1a77..aae4a00c4056 100644
--- a/arch/nios2/kernel/vmlinux.lds.S
+++ b/arch/nios2/kernel/vmlinux.lds.S
@@ -41,7 +41,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 	} =0
 	_etext = .;
 
diff --git a/arch/openrisc/kernel/vmlinux.lds.S b/arch/openrisc/kernel/vmlinux.lds.S
index 514f474249b0..bbf3b8acf5d3 100644
--- a/arch/openrisc/kernel/vmlinux.lds.S
+++ b/arch/openrisc/kernel/vmlinux.lds.S
@@ -55,7 +55,6 @@ SECTIONS
 	  SCHED_TEXT
 	  CPUIDLE_TEXT
 	  LOCK_TEXT
-	  KPROBES_TEXT
 	  IRQENTRY_TEXT
 	  SOFTIRQENTRY_TEXT
 	  *(.fixup)
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 3d6ef1b29c6a..edbd6d9487dc 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -71,7 +71,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.do_softirq)
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 025833b8df9f..0846413b3a2e 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,6 +9,7 @@
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
 #include <asm/firmware.h>
+#include <asm/ranges.h>
 
 #ifdef __ASSEMBLY__
 
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 8cd940c72895..2285664abb52 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -112,7 +112,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		MEM_KEEP(init.text)
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 97298c58b2be..847e2e1df89c 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -24,6 +24,7 @@
 #include <asm/setup.h>
 #include <asm/nmi.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
 __PT_R0      =	__PT_GPRS
 __PT_R1      =	__PT_GPRS + 8
@@ -169,7 +170,7 @@ _PIF_WORK	= (_PIF_PER_TRAP)
 		tm	off+\addr, \mask
 	.endm
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 .Ldummy:
 	/*
 	 * This nop exists only in order to avoid that __switch_to starts at
@@ -986,7 +987,7 @@ ENTRY(restart_int_handler)
 	brc	2,2b
 3:	j	3b
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 
 #ifdef CONFIG_CHECK_STACK
 /*
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index fdb40424acfe..d49241fef651 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -289,9 +289,9 @@ static void kprobe_reenter_check(struct kprobe_ctlblk *kcb, struct kprobe *p)
 	case KPROBE_REENTER:
 	default:
 		/*
-		 * A kprobe on the code path to single step an instruction
-		 * is a BUG. The code path resides in the .kprobes.text
-		 * section and is executed with interrupts disabled.
+		 * A kprobe on the code path to single step an instruction is a
+		 * BUG. The code path resides in the kprobes section range and
+		 * is executed with interrupts disabled.
 		 */
 		printk(KERN_EMERG "Invalid kprobe detected at %p.\n", p->addr);
 		dump_kprobe(p);
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S
index 9a17e4475d27..9d76056609f7 100644
--- a/arch/s390/kernel/mcount.S
+++ b/arch/s390/kernel/mcount.S
@@ -10,8 +10,9 @@
 #include <asm/ftrace.h>
 #include <asm/ptrace.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 
 ENTRY(ftrace_stub)
 	br	%r14
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 3667d20e997f..b2df6d9bab09 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -37,7 +37,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/score/kernel/vmlinux.lds.S b/arch/score/kernel/vmlinux.lds.S
index 4117890b1db1..a8b14f3ed474 100644
--- a/arch/score/kernel/vmlinux.lds.S
+++ b/arch/score/kernel/vmlinux.lds.S
@@ -42,7 +42,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.text.*)
 		*(.fixup)
 		. = ALIGN (4) ;
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 5b9a3cc90c58..58d9ba796f7a 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -38,7 +38,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 572db686f845..0ee41b0071e5 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -51,7 +51,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.gnu.warning)
diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S
index 5d2fd6cd3189..ee9f648549c0 100644
--- a/arch/sparc/mm/ultra.S
+++ b/arch/sparc/mm/ultra.S
@@ -16,6 +16,7 @@
 #include <asm/cacheflush.h>
 #include <asm/hypervisor.h>
 #include <asm/cpudata.h>
+#include <asm/ranges.h>
 
 	/* Basically, most of the Spitfire vs. Cheetah madness
 	 * has to do with the fact that Cheetah does not support
@@ -185,7 +186,7 @@ __spitfire_flush_tlb_mm_slow:
 /*
  * The following code flushes one page_size worth.
  */
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 	.align		32
 	.globl		__flush_icache_page
 __flush_icache_page:	/* %o0 = phys_page */
diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S
index e1baf094fba4..85d03ce6c0a0 100644
--- a/arch/tile/kernel/vmlinux.lds.S
+++ b/arch/tile/kernel/vmlinux.lds.S
@@ -44,7 +44,6 @@ SECTIONS
     SCHED_TEXT
     CPUIDLE_TEXT
     LOCK_TEXT
-    KPROBES_TEXT
     IRQENTRY_TEXT
     SOFTIRQENTRY_TEXT
     __fix_text_end = .;   /* tile-cpack won't rearrange before this */
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index d9d8d16b69db..b28be8dd14c6 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -580,9 +580,9 @@ static int reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
 	case KPROBE_REENTER:
 		/* A probe has been hit in the codepath leading up to, or just
 		 * after, single-stepping of a probed instruction. This entire
-		 * codepath should strictly reside in .kprobes.text section.
-		 * Raise a BUG or we'll continue in an endless reentering loop
-		 * and eventually a stack overflow.
+		 * codepath should strictly reside in the kprobes section
+		 * range. Raise a BUG or we'll continue in an endless
+		 * reentering loop and eventually a stack overflow.
 		 */
 		printk(KERN_WARNING "Unrecoverable kprobe detected at %p.\n",
 		       p->addr);
@@ -1133,10 +1133,9 @@ NOKPROBE_SYMBOL(longjmp_break_handler);
 
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
-	return  (addr >= (unsigned long)__kprobes_text_start &&
-		 addr < (unsigned long)__kprobes_text_end) ||
+	return  (SECTION_RANGE_ADDR_WITHIN(kprobes, addr) ||
 		(addr >= (unsigned long)__entry_text_start &&
-		 addr < (unsigned long)__entry_text_end);
+		 addr < (unsigned long)__entry_text_end));
 }
 
 int __init arch_init_kprobes(void)
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index e79f15f108a8..4c16fadb9ac6 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -99,7 +99,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		ENTRY_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 57af9f21d148..02a26b975187 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,6 +3,7 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
@@ -13,7 +14,7 @@ static unsigned long __used					\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define __kprobes	__LINUX_RANGE(.text, kprobes)
 # define nokprobe_inline	__always_inline
 #else
 # define NOKPROBE_SYMBOL(fname)
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index b145ae8d9cbe..f3340f2772bb 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -26,7 +26,6 @@
  * Following global variables are optional and may be unavailable on some
  * architectures and/or kernel configurations.
  *	_text, _data
- *	__kprobes_text_start, __kprobes_text_end
  *	__entry_text_start, __entry_text_end
  *	__ctors_start, __ctors_end
  */
@@ -38,7 +37,6 @@ extern char _sinittext[], _einittext[];
 extern char __start_data_ro_after_init[], __end_data_ro_after_init[];
 extern char _end[];
 extern char __per_cpu_load[], __per_cpu_start[], __per_cpu_end[];
-extern char __kprobes_text_start[], __kprobes_text_end[];
 extern char __entry_text_start[], __entry_text_end[];
 extern char __start_rodata[], __end_rodata[];
 
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 37b99537d5a9..499caf5b4361 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -471,7 +471,7 @@
 #define KPROBES_TEXT							\
 		ALIGN_FUNCTION();					\
 		VMLINUX_SYMBOL(__kprobes_text_start) = .;		\
-		*(.kprobes.text)					\
+		*(.text..rng.kprobes.any)				\
 		VMLINUX_SYMBOL(__kprobes_text_end) = .;
 
 #define ENTRY_TEXT							\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 985ed79ef431..445cc6fe7afa 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -43,6 +43,9 @@
 #include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
+#include <linux/ranges.h>
+
+DECLARE_SECTION_RANGE(kprobes);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index d63095472ea9..c79f0b04383f 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1328,8 +1328,7 @@ static int register_aggr_kprobe(struct kprobe *orig_p, struct kprobe *p)
 bool __weak arch_within_kprobe_blacklist(unsigned long addr)
 {
 	/* The __kprobes marked functions and entry code must not be probed */
-	return addr >= (unsigned long)__kprobes_text_start &&
-	       addr < (unsigned long)__kprobes_text_end;
+	return SECTION_RANGE_ADDR_WITHIN(kprobes, addr);
 }
 
 bool within_kprobe_blacklist(unsigned long addr)
@@ -2129,6 +2128,9 @@ static struct notifier_block kprobe_module_nb = {
 extern unsigned long __start_kprobe_blacklist[];
 extern unsigned long __stop_kprobe_blacklist[];
 
+/* Actual kprobes section range */
+DEFINE_SECTION_RANGE(kprobes, .text);
+
 static int __init init_kprobes(void)
 {
 	int i, err = 0;
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 29c89a6bad3d..2b442234c69b 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -894,7 +894,7 @@ static void check_section(const char *modname, struct elf_info *elf,
 
 #define DATA_SECTIONS ".data", ".data.rel"
 #define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \
-		".kprobes.text", ".cpuidle.text"
+		".text..rng.kprobes.any", ".cpuidle.text"
 #define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
 		".fixup", ".entry.text", ".exception.text", ".text.*", \
 		".coldtext"
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index aeb34223167c..6e95f3f87db1 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -417,7 +417,7 @@ is_mcounted_section_name(char const *const txtname)
 		strcmp(".spinlock.text", txtname) == 0 ||
 		strcmp(".irqentry.text", txtname) == 0 ||
 		strcmp(".softirqentry.text", txtname) == 0 ||
-		strcmp(".kprobes.text", txtname) == 0 ||
+		strcmp(".text..rng.kprobes.any", txtname) == 0 ||
 		strcmp(".cpuidle.text", txtname) == 0 ||
 		strcmp(".text.unlikely", txtname) == 0;
 }
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 0b6002b36f20..15e2fa37c489 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -135,7 +135,7 @@ my %text_sections = (
      ".spinlock.text" => 1,
      ".irqentry.text" => 1,
      ".softirqentry.text" => 1,
-     ".kprobes.text" => 1,
+     ".text..rng.kprobes.any" => 1,
      ".cpuidle.text" => 1,
      ".text.unlikely" => 1,
 );
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 13/14] kprobes: port blacklist kprobes to linker table
  2016-12-22  2:37     ` Luis R. Rodriguez
  (?)
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

kprobe makes use of two sections, the one dealing with the actual
kprobes was recently ported using the standard section range API.
The blacklist functionality of kprobes is still using a custom
section and declaring its custom section using the linker script
as follows:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist

This ports the _kprobe_blacklist custom section to the standard
Linux linker table API allowing us remove all the custom blacklist
kprobe section declarations from the linker script.

This has been tested by trying to register a kprobe on a blacklisted
symbol (these are declared with NOKPROBE_SYMBOL()), and confirms that
this fails to work as expected. This was tested with:

 # insmod samples/kprobes/kprobe_example.ko symbol="get_kprobe"

This fails to load as expected with:

insmod: ERROR: could not insert module samples/kprobes/kprobe_example.ko: Invalid parameters

v5: Use push_section_tbl() for _ASM_NOKPROBE() for x86, and
    _ASM_NOKPROBE_SYMBOL() on powerpc
v4: ported over _ASM_NOKPROBE_SYMBOL() on powerpc and
    ASM_NOKPROBE() on x86
v3: this patch was introduced in this series

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/powerpc/include/asm/ppc_asm.h |  4 ++--
 arch/x86/include/asm/asm.h         |  4 +++-
 include/asm-generic/kprobes.h      |  4 ++--
 include/asm-generic/vmlinux.lds.h  | 10 ----------
 include/linux/kprobes.h            |  2 ++
 kernel/kprobes.c                   | 11 ++++-------
 6 files changed, 13 insertions(+), 22 deletions(-)

diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 0846413b3a2e..20cd9c00eef5 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,7 +9,7 @@
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
 #include <asm/firmware.h>
-#include <asm/ranges.h>
+#include <asm/tables.h>
 
 #ifdef __ASSEMBLY__
 
@@ -266,7 +266,7 @@ GLUE(.,name):
  */
 #ifdef CONFIG_KPROBES
 #define _ASM_NOKPROBE_SYMBOL(entry)			\
-	.pushsection "_kprobe_blacklist","aw";		\
+	push_section_tbl(.init.data, _kprobe_blacklist, any, aw); \
 	PPC_LONG (entry) ;				\
 	.popsection
 #else
diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
index 7acb51c49fec..48b1bc85c0e6 100644
--- a/arch/x86/include/asm/asm.h
+++ b/arch/x86/include/asm/asm.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_ASM_H
 #define _ASM_X86_ASM_H
 
+#include <asm/tables.h>
+
 #ifdef __ASSEMBLY__
 # define __ASM_FORM(x)	x
 # define __ASM_FORM_RAW(x)     x
@@ -74,7 +76,7 @@
 	_ASM_EXTABLE_HANDLE(from, to, ex_handler_ext)
 
 # define _ASM_NOKPROBE(entry)					\
-	.pushsection "_kprobe_blacklist","aw" ;			\
+	push_section_tbl_any(.init.data, _kprobe_blacklist, aw);\
 	_ASM_ALIGN ;						\
 	_ASM_PTR (entry);					\
 	.popsection
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 02a26b975187..7d29a208390e 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,14 +3,14 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <linux/tables.h>
 #include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
  */
 # define __NOKPROBE_SYMBOL(fname)				\
-static unsigned long __used					\
-	__attribute__((__section__("_kprobe_blacklist")))	\
+static LINKTABLE_INIT_DATA(_kprobe_blacklist, all)		\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 499caf5b4361..9f062af1f728 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -114,15 +114,6 @@
 #define BRANCH_PROFILE()
 #endif
 
-#ifdef CONFIG_KPROBES
-#define KPROBE_BLACKLIST()	. = ALIGN(8);				      \
-				VMLINUX_SYMBOL(__start_kprobe_blacklist) = .; \
-				KEEP(*(_kprobe_blacklist))		      \
-				VMLINUX_SYMBOL(__stop_kprobe_blacklist) = .;
-#else
-#define KPROBE_BLACKLIST()
-#endif
-
 #ifdef CONFIG_EVENT_TRACING
 #define FTRACE_EVENTS()	. = ALIGN(8);					\
 			VMLINUX_SYMBOL(__start_ftrace_events) = .;	\
@@ -551,7 +542,6 @@
 	*(.init.rodata)							\
 	FTRACE_EVENTS()							\
 	TRACE_SYSCALLS()						\
-	KPROBE_BLACKLIST()						\
 	MEM_DISCARD(init.rodata)					\
 	CLK_OF_TABLES()							\
 	RESERVEDMEM_OF_TABLES()						\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 445cc6fe7afa..2707820cbb56 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -44,8 +44,10 @@
 
 #ifdef CONFIG_KPROBES
 #include <linux/ranges.h>
+#include <linux/tables.h>
 
 DECLARE_SECTION_RANGE(kprobes);
+DECLARE_LINKTABLE(unsigned long, _kprobe_blacklist);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index c79f0b04383f..2bbfc30237ec 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -2053,14 +2053,13 @@ NOKPROBE_SYMBOL(dump_kprobe);
  * since a kprobe need not necessarily be at the beginning
  * of a function.
  */
-static int __init populate_kprobe_blacklist(unsigned long *start,
-					     unsigned long *end)
+static int __init populate_kprobe_blacklist(void)
 {
 	unsigned long *iter;
 	struct kprobe_blacklist_entry *ent;
 	unsigned long entry, offset = 0, size = 0;
 
-	for (iter = start; iter < end; iter++) {
+	LINKTABLE_FOR_EACH(iter, _kprobe_blacklist) {
 		entry = arch_deref_entry_point((void *)*iter);
 
 		if (!kernel_text_address(entry) ||
@@ -2125,8 +2124,7 @@ static struct notifier_block kprobe_module_nb = {
 };
 
 /* Markers of _kprobe_blacklist section */
-extern unsigned long __start_kprobe_blacklist[];
-extern unsigned long __stop_kprobe_blacklist[];
+DEFINE_LINKTABLE_INIT_DATA(unsigned long, _kprobe_blacklist);
 
 /* Actual kprobes section range */
 DEFINE_SECTION_RANGE(kprobes, .text);
@@ -2143,8 +2141,7 @@ static int __init init_kprobes(void)
 		raw_spin_lock_init(&(kretprobe_table_locks[i].lock));
 	}
 
-	err = populate_kprobe_blacklist(__start_kprobe_blacklist,
-					__stop_kprobe_blacklist);
+	err = populate_kprobe_blacklist();
 	if (err) {
 		pr_err("kprobes: failed to populate blacklist: %d\n", err);
 		pr_err("Please take care of using kprobes.\n");
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 13/14] kprobes: port blacklist kprobes to linker table
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

kprobe makes use of two sections, the one dealing with the actual
kprobes was recently ported using the standard section range API.
The blacklist functionality of kprobes is still using a custom
section and declaring its custom section using the linker script
as follows:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist

This ports the _kprobe_blacklist custom section to the standard
Linux linker table API allowing us remove all the custom blacklist
kprobe section declarations from the linker script.

This has been tested by trying to register a kprobe on a blacklisted
symbol (these are declared with NOKPROBE_SYMBOL()), and confirms that
this fails to work as expected. This was tested with:

 # insmod samples/kprobes/kprobe_example.ko symbol="get_kprobe"

This fails to load as expected with:

insmod: ERROR: could not insert module samples/kprobes/kprobe_example.ko: Invalid parameters

v5: Use push_section_tbl() for _ASM_NOKPROBE() for x86, and
    _ASM_NOKPROBE_SYMBOL() on powerpc
v4: ported over _ASM_NOKPROBE_SYMBOL() on powerpc and
    ASM_NOKPROBE() on x86
v3: this patch was introduced in this series

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/powerpc/include/asm/ppc_asm.h |  4 ++--
 arch/x86/include/asm/asm.h         |  4 +++-
 include/asm-generic/kprobes.h      |  4 ++--
 include/asm-generic/vmlinux.lds.h  | 10 ----------
 include/linux/kprobes.h            |  2 ++
 kernel/kprobes.c                   | 11 ++++-------
 6 files changed, 13 insertions(+), 22 deletions(-)

diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 0846413b3a2e..20cd9c00eef5 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,7 +9,7 @@
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
 #include <asm/firmware.h>
-#include <asm/ranges.h>
+#include <asm/tables.h>
 
 #ifdef __ASSEMBLY__
 
@@ -266,7 +266,7 @@ GLUE(.,name):
  */
 #ifdef CONFIG_KPROBES
 #define _ASM_NOKPROBE_SYMBOL(entry)			\
-	.pushsection "_kprobe_blacklist","aw";		\
+	push_section_tbl(.init.data, _kprobe_blacklist, any, aw); \
 	PPC_LONG (entry) ;				\
 	.popsection
 #else
diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
index 7acb51c49fec..48b1bc85c0e6 100644
--- a/arch/x86/include/asm/asm.h
+++ b/arch/x86/include/asm/asm.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_ASM_H
 #define _ASM_X86_ASM_H
 
+#include <asm/tables.h>
+
 #ifdef __ASSEMBLY__
 # define __ASM_FORM(x)	x
 # define __ASM_FORM_RAW(x)     x
@@ -74,7 +76,7 @@
 	_ASM_EXTABLE_HANDLE(from, to, ex_handler_ext)
 
 # define _ASM_NOKPROBE(entry)					\
-	.pushsection "_kprobe_blacklist","aw" ;			\
+	push_section_tbl_any(.init.data, _kprobe_blacklist, aw);\
 	_ASM_ALIGN ;						\
 	_ASM_PTR (entry);					\
 	.popsection
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 02a26b975187..7d29a208390e 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,14 +3,14 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <linux/tables.h>
 #include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
  */
 # define __NOKPROBE_SYMBOL(fname)				\
-static unsigned long __used					\
-	__attribute__((__section__("_kprobe_blacklist")))	\
+static LINKTABLE_INIT_DATA(_kprobe_blacklist, all)		\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 499caf5b4361..9f062af1f728 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -114,15 +114,6 @@
 #define BRANCH_PROFILE()
 #endif
 
-#ifdef CONFIG_KPROBES
-#define KPROBE_BLACKLIST()	. = ALIGN(8);				      \
-				VMLINUX_SYMBOL(__start_kprobe_blacklist) = .; \
-				KEEP(*(_kprobe_blacklist))		      \
-				VMLINUX_SYMBOL(__stop_kprobe_blacklist) = .;
-#else
-#define KPROBE_BLACKLIST()
-#endif
-
 #ifdef CONFIG_EVENT_TRACING
 #define FTRACE_EVENTS()	. = ALIGN(8);					\
 			VMLINUX_SYMBOL(__start_ftrace_events) = .;	\
@@ -551,7 +542,6 @@
 	*(.init.rodata)							\
 	FTRACE_EVENTS()							\
 	TRACE_SYSCALLS()						\
-	KPROBE_BLACKLIST()						\
 	MEM_DISCARD(init.rodata)					\
 	CLK_OF_TABLES()							\
 	RESERVEDMEM_OF_TABLES()						\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 445cc6fe7afa..2707820cbb56 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -44,8 +44,10 @@
 
 #ifdef CONFIG_KPROBES
 #include <linux/ranges.h>
+#include <linux/tables.h>
 
 DECLARE_SECTION_RANGE(kprobes);
+DECLARE_LINKTABLE(unsigned long, _kprobe_blacklist);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index c79f0b04383f..2bbfc30237ec 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -2053,14 +2053,13 @@ NOKPROBE_SYMBOL(dump_kprobe);
  * since a kprobe need not necessarily be at the beginning
  * of a function.
  */
-static int __init populate_kprobe_blacklist(unsigned long *start,
-					     unsigned long *end)
+static int __init populate_kprobe_blacklist(void)
 {
 	unsigned long *iter;
 	struct kprobe_blacklist_entry *ent;
 	unsigned long entry, offset = 0, size = 0;
 
-	for (iter = start; iter < end; iter++) {
+	LINKTABLE_FOR_EACH(iter, _kprobe_blacklist) {
 		entry = arch_deref_entry_point((void *)*iter);
 
 		if (!kernel_text_address(entry) ||
@@ -2125,8 +2124,7 @@ static struct notifier_block kprobe_module_nb = {
 };
 
 /* Markers of _kprobe_blacklist section */
-extern unsigned long __start_kprobe_blacklist[];
-extern unsigned long __stop_kprobe_blacklist[];
+DEFINE_LINKTABLE_INIT_DATA(unsigned long, _kprobe_blacklist);
 
 /* Actual kprobes section range */
 DEFINE_SECTION_RANGE(kprobes, .text);
@@ -2143,8 +2141,7 @@ static int __init init_kprobes(void)
 		raw_spin_lock_init(&(kretprobe_table_locks[i].lock));
 	}
 
-	err = populate_kprobe_blacklist(__start_kprobe_blacklist,
-					__stop_kprobe_blacklist);
+	err = populate_kprobe_blacklist();
 	if (err) {
 		pr_err("kprobes: failed to populate blacklist: %d\n", err);
 		pr_err("Please take care of using kprobes.\n");
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 13/14] kprobes: port blacklist kprobes to linker table
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

kprobe makes use of two sections, the one dealing with the actual
kprobes was recently ported using the standard section range API.
The blacklist functionality of kprobes is still using a custom
section and declaring its custom section using the linker script
as follows:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist

This ports the _kprobe_blacklist custom section to the standard
Linux linker table API allowing us remove all the custom blacklist
kprobe section declarations from the linker script.

This has been tested by trying to register a kprobe on a blacklisted
symbol (these are declared with NOKPROBE_SYMBOL()), and confirms that
this fails to work as expected. This was tested with:

 # insmod samples/kprobes/kprobe_example.ko symbol="get_kprobe"

This fails to load as expected with:

insmod: ERROR: could not insert module samples/kprobes/kprobe_example.ko: Invalid parameters

v5: Use push_section_tbl() for _ASM_NOKPROBE() for x86, and
    _ASM_NOKPROBE_SYMBOL() on powerpc
v4: ported over _ASM_NOKPROBE_SYMBOL() on powerpc and
    ASM_NOKPROBE() on x86
v3: this patch was introduced in this series

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/powerpc/include/asm/ppc_asm.h |  4 ++--
 arch/x86/include/asm/asm.h         |  4 +++-
 include/asm-generic/kprobes.h      |  4 ++--
 include/asm-generic/vmlinux.lds.h  | 10 ----------
 include/linux/kprobes.h            |  2 ++
 kernel/kprobes.c                   | 11 ++++-------
 6 files changed, 13 insertions(+), 22 deletions(-)

diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 0846413b3a2e..20cd9c00eef5 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,7 +9,7 @@
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
 #include <asm/firmware.h>
-#include <asm/ranges.h>
+#include <asm/tables.h>
 
 #ifdef __ASSEMBLY__
 
@@ -266,7 +266,7 @@ GLUE(.,name):
  */
 #ifdef CONFIG_KPROBES
 #define _ASM_NOKPROBE_SYMBOL(entry)			\
-	.pushsection "_kprobe_blacklist","aw";		\
+	push_section_tbl(.init.data, _kprobe_blacklist, any, aw); \
 	PPC_LONG (entry) ;				\
 	.popsection
 #else
diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
index 7acb51c49fec..48b1bc85c0e6 100644
--- a/arch/x86/include/asm/asm.h
+++ b/arch/x86/include/asm/asm.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_ASM_H
 #define _ASM_X86_ASM_H
 
+#include <asm/tables.h>
+
 #ifdef __ASSEMBLY__
 # define __ASM_FORM(x)	x
 # define __ASM_FORM_RAW(x)     x
@@ -74,7 +76,7 @@
 	_ASM_EXTABLE_HANDLE(from, to, ex_handler_ext)
 
 # define _ASM_NOKPROBE(entry)					\
-	.pushsection "_kprobe_blacklist","aw" ;			\
+	push_section_tbl_any(.init.data, _kprobe_blacklist, aw);\
 	_ASM_ALIGN ;						\
 	_ASM_PTR (entry);					\
 	.popsection
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 02a26b975187..7d29a208390e 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,14 +3,14 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <linux/tables.h>
 #include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
  */
 # define __NOKPROBE_SYMBOL(fname)				\
-static unsigned long __used					\
-	__attribute__((__section__("_kprobe_blacklist")))	\
+static LINKTABLE_INIT_DATA(_kprobe_blacklist, all)		\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 499caf5b4361..9f062af1f728 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -114,15 +114,6 @@
 #define BRANCH_PROFILE()
 #endif
 
-#ifdef CONFIG_KPROBES
-#define KPROBE_BLACKLIST()	. = ALIGN(8);				      \
-				VMLINUX_SYMBOL(__start_kprobe_blacklist) = .; \
-				KEEP(*(_kprobe_blacklist))		      \
-				VMLINUX_SYMBOL(__stop_kprobe_blacklist) = .;
-#else
-#define KPROBE_BLACKLIST()
-#endif
-
 #ifdef CONFIG_EVENT_TRACING
 #define FTRACE_EVENTS()	. = ALIGN(8);					\
 			VMLINUX_SYMBOL(__start_ftrace_events) = .;	\
@@ -551,7 +542,6 @@
 	*(.init.rodata)							\
 	FTRACE_EVENTS()							\
 	TRACE_SYSCALLS()						\
-	KPROBE_BLACKLIST()						\
 	MEM_DISCARD(init.rodata)					\
 	CLK_OF_TABLES()							\
 	RESERVEDMEM_OF_TABLES()						\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 445cc6fe7afa..2707820cbb56 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -44,8 +44,10 @@
 
 #ifdef CONFIG_KPROBES
 #include <linux/ranges.h>
+#include <linux/tables.h>
 
 DECLARE_SECTION_RANGE(kprobes);
+DECLARE_LINKTABLE(unsigned long, _kprobe_blacklist);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index c79f0b04383f..2bbfc30237ec 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -2053,14 +2053,13 @@ NOKPROBE_SYMBOL(dump_kprobe);
  * since a kprobe need not necessarily be at the beginning
  * of a function.
  */
-static int __init populate_kprobe_blacklist(unsigned long *start,
-					     unsigned long *end)
+static int __init populate_kprobe_blacklist(void)
 {
 	unsigned long *iter;
 	struct kprobe_blacklist_entry *ent;
 	unsigned long entry, offset = 0, size = 0;
 
-	for (iter = start; iter < end; iter++) {
+	LINKTABLE_FOR_EACH(iter, _kprobe_blacklist) {
 		entry = arch_deref_entry_point((void *)*iter);
 
 		if (!kernel_text_address(entry) ||
@@ -2125,8 +2124,7 @@ static struct notifier_block kprobe_module_nb = {
 };
 
 /* Markers of _kprobe_blacklist section */
-extern unsigned long __start_kprobe_blacklist[];
-extern unsigned long __stop_kprobe_blacklist[];
+DEFINE_LINKTABLE_INIT_DATA(unsigned long, _kprobe_blacklist);
 
 /* Actual kprobes section range */
 DEFINE_SECTION_RANGE(kprobes, .text);
@@ -2143,8 +2141,7 @@ static int __init init_kprobes(void)
 		raw_spin_lock_init(&(kretprobe_table_locks[i].lock));
 	}
 
-	err = populate_kprobe_blacklist(__start_kprobe_blacklist,
-					__stop_kprobe_blacklist);
+	err = populate_kprobe_blacklist();
 	if (err) {
 		pr_err("kprobes: failed to populate blacklist: %d\n", err);
 		pr_err("Please take care of using kprobes.\n");
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 14/14] lib: add linker tables test driver
  2016-12-22  2:37     ` Luis R. Rodriguez
  (?)
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

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


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 14/14] lib: add linker tables test driver
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

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


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v5 14/14] lib: add linker tables test driver
@ 2016-12-22  2:38       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:38 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

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


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v2 0/6] tools: add linker table userspace sandbox
  2016-08-19 21:41     ` mcgrof
  (?)
@ 2016-12-22  2:39       ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:39 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This v2 is just bump refresh from the v1. The last series did not receive
any criticism, however as expected there was much more substantial feedback
on the real kernel side. This series just refreshes all the userspace code
to work with the latest changes made in kernel space.

This patch is the second part to the linker table work, the first part
is the kernel work. I've split it up to make it easier to review. All the
code is present on my linux-next 20161221-linker-tables-v5 branch on
kernel.org [1], if you check that code out you can disregard the last patch
as it was a debug patch to force enable a driver on 0-day and Guenter's
testbed.

[0] https://lkml.kernel.org/r/1471642875-5957-1-git-send-email-mcgrof@kernel.org
[1] https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h 161221-linker-tables-v5

Luis R. Rodriguez (6):
  tools: add a userspace tools bug.h
  tools: add init.h for tools
  tools: add __used and enable to override
  tools: expand export.h with VMLINUX_SYMBOL()
  tools: add __section() to compiler.h
  tools: add userspace linker table sandbox

 Documentation/sections/linker-tables.rst           |   4 +-
 MAINTAINERS                                        |   1 +
 include/linux/tables.h                             |   5 +-
 tools/Makefile                                     |   3 +-
 .../arch/x86/include/generated/asm/section-core.h  |   1 +
 tools/arch/x86/include/generated/ranges.h          |   1 +
 tools/arch/x86/include/generated/tables.h          |   1 +
 tools/include/asm-generic/bug.h                    |  24 +
 tools/include/asm-generic/ranges.h                 |  93 +++
 tools/include/asm-generic/section-core.h           | 348 +++++++++++
 tools/include/asm-generic/tables.h                 |  48 ++
 tools/include/linux/bug.h                          |   6 +
 tools/include/linux/compiler.h                     |   8 +
 tools/include/linux/export.h                       |  22 +
 tools/include/linux/init.h                         |   9 +
 tools/include/linux/kernel.h                       |   2 +
 tools/include/linux/ranges.h                       | 183 ++++++
 tools/include/linux/sections.h                     |  87 +++
 tools/include/linux/string.h                       |   1 +
 tools/include/linux/tables.h                       | 684 +++++++++++++++++++++
 tools/linker-tables/.gitignore                     |   2 +
 tools/linker-tables/Makefile                       | 184 ++++++
 tools/linker-tables/README                         | 114 ++++
 tools/linker-tables/arch/x86/include/asm/asm.h     |  17 +
 tools/linker-tables/arch/x86/include/asm/boot.h    |   1 +
 .../linker-tables/arch/x86/include/asm/bootparam.h |  32 +
 tools/linker-tables/arch/x86/include/asm/kprobes.h |   7 +
 .../linker-tables/arch/x86/include/asm/ps_const.h  |  23 +
 tools/linker-tables/arch/x86/include/asm/ranges.h  |   6 +
 .../arch/x86/include/asm/section-core.h            |   1 +
 tools/linker-tables/arch/x86/include/asm/setup.h   |   6 +
 tools/linker-tables/arch/x86/include/asm/tables.h  |   6 +
 tools/linker-tables/arch/x86/include/asm/x86.h     |   4 +
 .../arch/x86/include/asm/x86_init_fn.h             | 169 +++++
 tools/linker-tables/arch/x86/kernel/alpha.c        |   9 +
 tools/linker-tables/arch/x86/kernel/alternative.c  |  31 +
 tools/linker-tables/arch/x86/kernel/beta.c         |   9 +
 tools/linker-tables/arch/x86/kernel/head64.c       |  58 ++
 tools/linker-tables/arch/x86/kernel/init.c         |  42 ++
 tools/linker-tables/arch/x86/kernel/kasan.c        |  10 +
 tools/linker-tables/arch/x86/kernel/kprobes.c      |  51 ++
 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S  | 277 +++++++++
 tools/linker-tables/arch/x86/mm/init.c             |  10 +
 tools/linker-tables/arch/x86/xen/init.c            |  13 +
 tools/linker-tables/drivers/acme.c                 |  32 +
 tools/linker-tables/drivers/synth/common.c         |  16 +
 tools/linker-tables/drivers/synth/common.h         |   2 +
 tools/linker-tables/drivers/synth/main.c           |  35 ++
 tools/linker-tables/drivers/synth/or.S             |  39 ++
 tools/linker-tables/drivers/synth/synth.h          |   2 +
 tools/linker-tables/drivers/xen-driver.c           |  11 +
 .../include/asm-generic/arch_init_fn.h             |  50 ++
 tools/linker-tables/include/asm-generic/kprobes.h  |  26 +
 tools/linker-tables/include/linux/bitops.h         |   6 +
 tools/linker-tables/include/linux/init.h           |  40 ++
 tools/linker-tables/include/linux/kasan.h          |   5 +
 tools/linker-tables/include/linux/kernel.h         |   2 +
 tools/linker-tables/include/linux/kprobes.h        |  11 +
 tools/linker-tables/include/linux/module.h         |  14 +
 tools/linker-tables/include/linux/mutex.h          |  17 +
 tools/linker-tables/include/linux/pci.h            |   7 +
 tools/linker-tables/include/linux/printk.h         |  26 +
 tools/linker-tables/include/linux/ps_const.h       |  46 ++
 tools/linker-tables/include/linux/sched.h          |   9 +
 tools/linker-tables/include/linux/spinlock.h       |  13 +
 tools/linker-tables/include/linux/start_kernel.h   |   1 +
 tools/linker-tables/include/linux/types.h          |  13 +
 tools/linker-tables/include/linux/workqueue.h      |  51 ++
 tools/linker-tables/include/xen/xen.h              |   4 +
 tools/linker-tables/kernel/locking/mutex.c         |  28 +
 tools/linker-tables/kernel/locking/spinlock.c      |  26 +
 tools/linker-tables/kernel/main.c                  |  32 +
 tools/linker-tables/kernel/workqueue.c             |  43 ++
 tools/linker-tables/lib/string.c                   |  26 +
 tools/linker-tables/main.c                         |  20 +
 tools/linker-tables/pci-quirks.c                   |  13 +
 tools/linker-tables/pci.c                          |  29 +
 77 files changed, 3303 insertions(+), 5 deletions(-)
 create mode 100644 tools/arch/x86/include/generated/asm/section-core.h
 create mode 100644 tools/arch/x86/include/generated/ranges.h
 create mode 100644 tools/arch/x86/include/generated/tables.h
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/asm-generic/ranges.h
 create mode 100644 tools/include/asm-generic/section-core.h
 create mode 100644 tools/include/asm-generic/tables.h
 create mode 100644 tools/include/linux/bug.h
 create mode 100644 tools/include/linux/init.h
 create mode 100644 tools/include/linux/ranges.h
 create mode 100644 tools/include/linux/sections.h
 create mode 100644 tools/include/linux/tables.h
 create mode 100644 tools/linker-tables/.gitignore
 create mode 100644 tools/linker-tables/Makefile
 create mode 100644 tools/linker-tables/README
 create mode 100644 tools/linker-tables/arch/x86/include/asm/asm.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/boot.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/bootparam.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/kprobes.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ps_const.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ranges.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/section-core.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/setup.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/tables.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
 create mode 100644 tools/linker-tables/arch/x86/kernel/alpha.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/alternative.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/beta.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/head64.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/init.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kasan.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kprobes.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
 create mode 100644 tools/linker-tables/arch/x86/mm/init.c
 create mode 100644 tools/linker-tables/arch/x86/xen/init.c
 create mode 100644 tools/linker-tables/drivers/acme.c
 create mode 100644 tools/linker-tables/drivers/synth/common.c
 create mode 100644 tools/linker-tables/drivers/synth/common.h
 create mode 100644 tools/linker-tables/drivers/synth/main.c
 create mode 100644 tools/linker-tables/drivers/synth/or.S
 create mode 100644 tools/linker-tables/drivers/synth/synth.h
 create mode 100644 tools/linker-tables/drivers/xen-driver.c
 create mode 100644 tools/linker-tables/include/asm-generic/arch_init_fn.h
 create mode 100644 tools/linker-tables/include/asm-generic/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/bitops.h
 create mode 100644 tools/linker-tables/include/linux/init.h
 create mode 100644 tools/linker-tables/include/linux/kasan.h
 create mode 100644 tools/linker-tables/include/linux/kernel.h
 create mode 100644 tools/linker-tables/include/linux/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/module.h
 create mode 100644 tools/linker-tables/include/linux/mutex.h
 create mode 100644 tools/linker-tables/include/linux/pci.h
 create mode 100644 tools/linker-tables/include/linux/printk.h
 create mode 100644 tools/linker-tables/include/linux/ps_const.h
 create mode 100644 tools/linker-tables/include/linux/sched.h
 create mode 100644 tools/linker-tables/include/linux/spinlock.h
 create mode 100644 tools/linker-tables/include/linux/start_kernel.h
 create mode 100644 tools/linker-tables/include/linux/types.h
 create mode 100644 tools/linker-tables/include/linux/workqueue.h
 create mode 100644 tools/linker-tables/include/xen/xen.h
 create mode 100644 tools/linker-tables/kernel/locking/mutex.c
 create mode 100644 tools/linker-tables/kernel/locking/spinlock.c
 create mode 100644 tools/linker-tables/kernel/main.c
 create mode 100644 tools/linker-tables/kernel/workqueue.c
 create mode 100644 tools/linker-tables/lib/string.c
 create mode 100644 tools/linker-tables/main.c
 create mode 100644 tools/linker-tables/pci-quirks.c
 create mode 100644 tools/linker-tables/pci.c

-- 
2.10.1


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v2 0/6] tools: add linker table userspace sandbox
@ 2016-12-22  2:39       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:39 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This v2 is just bump refresh from the v1. The last series did not receive
any criticism, however as expected there was much more substantial feedback
on the real kernel side. This series just refreshes all the userspace code
to work with the latest changes made in kernel space.

This patch is the second part to the linker table work, the first part
is the kernel work. I've split it up to make it easier to review. All the
code is present on my linux-next 20161221-linker-tables-v5 branch on
kernel.org [1], if you check that code out you can disregard the last patch
as it was a debug patch to force enable a driver on 0-day and Guenter's
testbed.

[0] https://lkml.kernel.org/r/1471642875-5957-1-git-send-email-mcgrof@kernel.org
[1] https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h=20161221-linker-tables-v5

Luis R. Rodriguez (6):
  tools: add a userspace tools bug.h
  tools: add init.h for tools
  tools: add __used and enable to override
  tools: expand export.h with VMLINUX_SYMBOL()
  tools: add __section() to compiler.h
  tools: add userspace linker table sandbox

 Documentation/sections/linker-tables.rst           |   4 +-
 MAINTAINERS                                        |   1 +
 include/linux/tables.h                             |   5 +-
 tools/Makefile                                     |   3 +-
 .../arch/x86/include/generated/asm/section-core.h  |   1 +
 tools/arch/x86/include/generated/ranges.h          |   1 +
 tools/arch/x86/include/generated/tables.h          |   1 +
 tools/include/asm-generic/bug.h                    |  24 +
 tools/include/asm-generic/ranges.h                 |  93 +++
 tools/include/asm-generic/section-core.h           | 348 +++++++++++
 tools/include/asm-generic/tables.h                 |  48 ++
 tools/include/linux/bug.h                          |   6 +
 tools/include/linux/compiler.h                     |   8 +
 tools/include/linux/export.h                       |  22 +
 tools/include/linux/init.h                         |   9 +
 tools/include/linux/kernel.h                       |   2 +
 tools/include/linux/ranges.h                       | 183 ++++++
 tools/include/linux/sections.h                     |  87 +++
 tools/include/linux/string.h                       |   1 +
 tools/include/linux/tables.h                       | 684 +++++++++++++++++++++
 tools/linker-tables/.gitignore                     |   2 +
 tools/linker-tables/Makefile                       | 184 ++++++
 tools/linker-tables/README                         | 114 ++++
 tools/linker-tables/arch/x86/include/asm/asm.h     |  17 +
 tools/linker-tables/arch/x86/include/asm/boot.h    |   1 +
 .../linker-tables/arch/x86/include/asm/bootparam.h |  32 +
 tools/linker-tables/arch/x86/include/asm/kprobes.h |   7 +
 .../linker-tables/arch/x86/include/asm/ps_const.h  |  23 +
 tools/linker-tables/arch/x86/include/asm/ranges.h  |   6 +
 .../arch/x86/include/asm/section-core.h            |   1 +
 tools/linker-tables/arch/x86/include/asm/setup.h   |   6 +
 tools/linker-tables/arch/x86/include/asm/tables.h  |   6 +
 tools/linker-tables/arch/x86/include/asm/x86.h     |   4 +
 .../arch/x86/include/asm/x86_init_fn.h             | 169 +++++
 tools/linker-tables/arch/x86/kernel/alpha.c        |   9 +
 tools/linker-tables/arch/x86/kernel/alternative.c  |  31 +
 tools/linker-tables/arch/x86/kernel/beta.c         |   9 +
 tools/linker-tables/arch/x86/kernel/head64.c       |  58 ++
 tools/linker-tables/arch/x86/kernel/init.c         |  42 ++
 tools/linker-tables/arch/x86/kernel/kasan.c        |  10 +
 tools/linker-tables/arch/x86/kernel/kprobes.c      |  51 ++
 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S  | 277 +++++++++
 tools/linker-tables/arch/x86/mm/init.c             |  10 +
 tools/linker-tables/arch/x86/xen/init.c            |  13 +
 tools/linker-tables/drivers/acme.c                 |  32 +
 tools/linker-tables/drivers/synth/common.c         |  16 +
 tools/linker-tables/drivers/synth/common.h         |   2 +
 tools/linker-tables/drivers/synth/main.c           |  35 ++
 tools/linker-tables/drivers/synth/or.S             |  39 ++
 tools/linker-tables/drivers/synth/synth.h          |   2 +
 tools/linker-tables/drivers/xen-driver.c           |  11 +
 .../include/asm-generic/arch_init_fn.h             |  50 ++
 tools/linker-tables/include/asm-generic/kprobes.h  |  26 +
 tools/linker-tables/include/linux/bitops.h         |   6 +
 tools/linker-tables/include/linux/init.h           |  40 ++
 tools/linker-tables/include/linux/kasan.h          |   5 +
 tools/linker-tables/include/linux/kernel.h         |   2 +
 tools/linker-tables/include/linux/kprobes.h        |  11 +
 tools/linker-tables/include/linux/module.h         |  14 +
 tools/linker-tables/include/linux/mutex.h          |  17 +
 tools/linker-tables/include/linux/pci.h            |   7 +
 tools/linker-tables/include/linux/printk.h         |  26 +
 tools/linker-tables/include/linux/ps_const.h       |  46 ++
 tools/linker-tables/include/linux/sched.h          |   9 +
 tools/linker-tables/include/linux/spinlock.h       |  13 +
 tools/linker-tables/include/linux/start_kernel.h   |   1 +
 tools/linker-tables/include/linux/types.h          |  13 +
 tools/linker-tables/include/linux/workqueue.h      |  51 ++
 tools/linker-tables/include/xen/xen.h              |   4 +
 tools/linker-tables/kernel/locking/mutex.c         |  28 +
 tools/linker-tables/kernel/locking/spinlock.c      |  26 +
 tools/linker-tables/kernel/main.c                  |  32 +
 tools/linker-tables/kernel/workqueue.c             |  43 ++
 tools/linker-tables/lib/string.c                   |  26 +
 tools/linker-tables/main.c                         |  20 +
 tools/linker-tables/pci-quirks.c                   |  13 +
 tools/linker-tables/pci.c                          |  29 +
 77 files changed, 3303 insertions(+), 5 deletions(-)
 create mode 100644 tools/arch/x86/include/generated/asm/section-core.h
 create mode 100644 tools/arch/x86/include/generated/ranges.h
 create mode 100644 tools/arch/x86/include/generated/tables.h
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/asm-generic/ranges.h
 create mode 100644 tools/include/asm-generic/section-core.h
 create mode 100644 tools/include/asm-generic/tables.h
 create mode 100644 tools/include/linux/bug.h
 create mode 100644 tools/include/linux/init.h
 create mode 100644 tools/include/linux/ranges.h
 create mode 100644 tools/include/linux/sections.h
 create mode 100644 tools/include/linux/tables.h
 create mode 100644 tools/linker-tables/.gitignore
 create mode 100644 tools/linker-tables/Makefile
 create mode 100644 tools/linker-tables/README
 create mode 100644 tools/linker-tables/arch/x86/include/asm/asm.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/boot.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/bootparam.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/kprobes.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ps_const.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ranges.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/section-core.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/setup.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/tables.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
 create mode 100644 tools/linker-tables/arch/x86/kernel/alpha.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/alternative.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/beta.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/head64.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/init.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kasan.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kprobes.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
 create mode 100644 tools/linker-tables/arch/x86/mm/init.c
 create mode 100644 tools/linker-tables/arch/x86/xen/init.c
 create mode 100644 tools/linker-tables/drivers/acme.c
 create mode 100644 tools/linker-tables/drivers/synth/common.c
 create mode 100644 tools/linker-tables/drivers/synth/common.h
 create mode 100644 tools/linker-tables/drivers/synth/main.c
 create mode 100644 tools/linker-tables/drivers/synth/or.S
 create mode 100644 tools/linker-tables/drivers/synth/synth.h
 create mode 100644 tools/linker-tables/drivers/xen-driver.c
 create mode 100644 tools/linker-tables/include/asm-generic/arch_init_fn.h
 create mode 100644 tools/linker-tables/include/asm-generic/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/bitops.h
 create mode 100644 tools/linker-tables/include/linux/init.h
 create mode 100644 tools/linker-tables/include/linux/kasan.h
 create mode 100644 tools/linker-tables/include/linux/kernel.h
 create mode 100644 tools/linker-tables/include/linux/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/module.h
 create mode 100644 tools/linker-tables/include/linux/mutex.h
 create mode 100644 tools/linker-tables/include/linux/pci.h
 create mode 100644 tools/linker-tables/include/linux/printk.h
 create mode 100644 tools/linker-tables/include/linux/ps_const.h
 create mode 100644 tools/linker-tables/include/linux/sched.h
 create mode 100644 tools/linker-tables/include/linux/spinlock.h
 create mode 100644 tools/linker-tables/include/linux/start_kernel.h
 create mode 100644 tools/linker-tables/include/linux/types.h
 create mode 100644 tools/linker-tables/include/linux/workqueue.h
 create mode 100644 tools/linker-tables/include/xen/xen.h
 create mode 100644 tools/linker-tables/kernel/locking/mutex.c
 create mode 100644 tools/linker-tables/kernel/locking/spinlock.c
 create mode 100644 tools/linker-tables/kernel/main.c
 create mode 100644 tools/linker-tables/kernel/workqueue.c
 create mode 100644 tools/linker-tables/lib/string.c
 create mode 100644 tools/linker-tables/main.c
 create mode 100644 tools/linker-tables/pci-quirks.c
 create mode 100644 tools/linker-tables/pci.c

-- 
2.10.1


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v2 0/6] tools: add linker table userspace sandbox
@ 2016-12-22  2:39       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:39 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

This v2 is just bump refresh from the v1. The last series did not receive
any criticism, however as expected there was much more substantial feedback
on the real kernel side. This series just refreshes all the userspace code
to work with the latest changes made in kernel space.

This patch is the second part to the linker table work, the first part
is the kernel work. I've split it up to make it easier to review. All the
code is present on my linux-next 20161221-linker-tables-v5 branch on
kernel.org [1], if you check that code out you can disregard the last patch
as it was a debug patch to force enable a driver on 0-day and Guenter's
testbed.

[0] https://lkml.kernel.org/r/1471642875-5957-1-git-send-email-mcgrof@kernel.org
[1] https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h=20161221-linker-tables-v5

Luis R. Rodriguez (6):
  tools: add a userspace tools bug.h
  tools: add init.h for tools
  tools: add __used and enable to override
  tools: expand export.h with VMLINUX_SYMBOL()
  tools: add __section() to compiler.h
  tools: add userspace linker table sandbox

 Documentation/sections/linker-tables.rst           |   4 +-
 MAINTAINERS                                        |   1 +
 include/linux/tables.h                             |   5 +-
 tools/Makefile                                     |   3 +-
 .../arch/x86/include/generated/asm/section-core.h  |   1 +
 tools/arch/x86/include/generated/ranges.h          |   1 +
 tools/arch/x86/include/generated/tables.h          |   1 +
 tools/include/asm-generic/bug.h                    |  24 +
 tools/include/asm-generic/ranges.h                 |  93 +++
 tools/include/asm-generic/section-core.h           | 348 +++++++++++
 tools/include/asm-generic/tables.h                 |  48 ++
 tools/include/linux/bug.h                          |   6 +
 tools/include/linux/compiler.h                     |   8 +
 tools/include/linux/export.h                       |  22 +
 tools/include/linux/init.h                         |   9 +
 tools/include/linux/kernel.h                       |   2 +
 tools/include/linux/ranges.h                       | 183 ++++++
 tools/include/linux/sections.h                     |  87 +++
 tools/include/linux/string.h                       |   1 +
 tools/include/linux/tables.h                       | 684 +++++++++++++++++++++
 tools/linker-tables/.gitignore                     |   2 +
 tools/linker-tables/Makefile                       | 184 ++++++
 tools/linker-tables/README                         | 114 ++++
 tools/linker-tables/arch/x86/include/asm/asm.h     |  17 +
 tools/linker-tables/arch/x86/include/asm/boot.h    |   1 +
 .../linker-tables/arch/x86/include/asm/bootparam.h |  32 +
 tools/linker-tables/arch/x86/include/asm/kprobes.h |   7 +
 .../linker-tables/arch/x86/include/asm/ps_const.h  |  23 +
 tools/linker-tables/arch/x86/include/asm/ranges.h  |   6 +
 .../arch/x86/include/asm/section-core.h            |   1 +
 tools/linker-tables/arch/x86/include/asm/setup.h   |   6 +
 tools/linker-tables/arch/x86/include/asm/tables.h  |   6 +
 tools/linker-tables/arch/x86/include/asm/x86.h     |   4 +
 .../arch/x86/include/asm/x86_init_fn.h             | 169 +++++
 tools/linker-tables/arch/x86/kernel/alpha.c        |   9 +
 tools/linker-tables/arch/x86/kernel/alternative.c  |  31 +
 tools/linker-tables/arch/x86/kernel/beta.c         |   9 +
 tools/linker-tables/arch/x86/kernel/head64.c       |  58 ++
 tools/linker-tables/arch/x86/kernel/init.c         |  42 ++
 tools/linker-tables/arch/x86/kernel/kasan.c        |  10 +
 tools/linker-tables/arch/x86/kernel/kprobes.c      |  51 ++
 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S  | 277 +++++++++
 tools/linker-tables/arch/x86/mm/init.c             |  10 +
 tools/linker-tables/arch/x86/xen/init.c            |  13 +
 tools/linker-tables/drivers/acme.c                 |  32 +
 tools/linker-tables/drivers/synth/common.c         |  16 +
 tools/linker-tables/drivers/synth/common.h         |   2 +
 tools/linker-tables/drivers/synth/main.c           |  35 ++
 tools/linker-tables/drivers/synth/or.S             |  39 ++
 tools/linker-tables/drivers/synth/synth.h          |   2 +
 tools/linker-tables/drivers/xen-driver.c           |  11 +
 .../include/asm-generic/arch_init_fn.h             |  50 ++
 tools/linker-tables/include/asm-generic/kprobes.h  |  26 +
 tools/linker-tables/include/linux/bitops.h         |   6 +
 tools/linker-tables/include/linux/init.h           |  40 ++
 tools/linker-tables/include/linux/kasan.h          |   5 +
 tools/linker-tables/include/linux/kernel.h         |   2 +
 tools/linker-tables/include/linux/kprobes.h        |  11 +
 tools/linker-tables/include/linux/module.h         |  14 +
 tools/linker-tables/include/linux/mutex.h          |  17 +
 tools/linker-tables/include/linux/pci.h            |   7 +
 tools/linker-tables/include/linux/printk.h         |  26 +
 tools/linker-tables/include/linux/ps_const.h       |  46 ++
 tools/linker-tables/include/linux/sched.h          |   9 +
 tools/linker-tables/include/linux/spinlock.h       |  13 +
 tools/linker-tables/include/linux/start_kernel.h   |   1 +
 tools/linker-tables/include/linux/types.h          |  13 +
 tools/linker-tables/include/linux/workqueue.h      |  51 ++
 tools/linker-tables/include/xen/xen.h              |   4 +
 tools/linker-tables/kernel/locking/mutex.c         |  28 +
 tools/linker-tables/kernel/locking/spinlock.c      |  26 +
 tools/linker-tables/kernel/main.c                  |  32 +
 tools/linker-tables/kernel/workqueue.c             |  43 ++
 tools/linker-tables/lib/string.c                   |  26 +
 tools/linker-tables/main.c                         |  20 +
 tools/linker-tables/pci-quirks.c                   |  13 +
 tools/linker-tables/pci.c                          |  29 +
 77 files changed, 3303 insertions(+), 5 deletions(-)
 create mode 100644 tools/arch/x86/include/generated/asm/section-core.h
 create mode 100644 tools/arch/x86/include/generated/ranges.h
 create mode 100644 tools/arch/x86/include/generated/tables.h
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/asm-generic/ranges.h
 create mode 100644 tools/include/asm-generic/section-core.h
 create mode 100644 tools/include/asm-generic/tables.h
 create mode 100644 tools/include/linux/bug.h
 create mode 100644 tools/include/linux/init.h
 create mode 100644 tools/include/linux/ranges.h
 create mode 100644 tools/include/linux/sections.h
 create mode 100644 tools/include/linux/tables.h
 create mode 100644 tools/linker-tables/.gitignore
 create mode 100644 tools/linker-tables/Makefile
 create mode 100644 tools/linker-tables/README
 create mode 100644 tools/linker-tables/arch/x86/include/asm/asm.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/boot.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/bootparam.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/kprobes.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ps_const.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ranges.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/section-core.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/setup.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/tables.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
 create mode 100644 tools/linker-tables/arch/x86/kernel/alpha.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/alternative.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/beta.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/head64.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/init.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kasan.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kprobes.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
 create mode 100644 tools/linker-tables/arch/x86/mm/init.c
 create mode 100644 tools/linker-tables/arch/x86/xen/init.c
 create mode 100644 tools/linker-tables/drivers/acme.c
 create mode 100644 tools/linker-tables/drivers/synth/common.c
 create mode 100644 tools/linker-tables/drivers/synth/common.h
 create mode 100644 tools/linker-tables/drivers/synth/main.c
 create mode 100644 tools/linker-tables/drivers/synth/or.S
 create mode 100644 tools/linker-tables/drivers/synth/synth.h
 create mode 100644 tools/linker-tables/drivers/xen-driver.c
 create mode 100644 tools/linker-tables/include/asm-generic/arch_init_fn.h
 create mode 100644 tools/linker-tables/include/asm-generic/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/bitops.h
 create mode 100644 tools/linker-tables/include/linux/init.h
 create mode 100644 tools/linker-tables/include/linux/kasan.h
 create mode 100644 tools/linker-tables/include/linux/kernel.h
 create mode 100644 tools/linker-tables/include/linux/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/module.h
 create mode 100644 tools/linker-tables/include/linux/mutex.h
 create mode 100644 tools/linker-tables/include/linux/pci.h
 create mode 100644 tools/linker-tables/include/linux/printk.h
 create mode 100644 tools/linker-tables/include/linux/ps_const.h
 create mode 100644 tools/linker-tables/include/linux/sched.h
 create mode 100644 tools/linker-tables/include/linux/spinlock.h
 create mode 100644 tools/linker-tables/include/linux/start_kernel.h
 create mode 100644 tools/linker-tables/include/linux/types.h
 create mode 100644 tools/linker-tables/include/linux/workqueue.h
 create mode 100644 tools/linker-tables/include/xen/xen.h
 create mode 100644 tools/linker-tables/kernel/locking/mutex.c
 create mode 100644 tools/linker-tables/kernel/locking/spinlock.c
 create mode 100644 tools/linker-tables/kernel/main.c
 create mode 100644 tools/linker-tables/kernel/workqueue.c
 create mode 100644 tools/linker-tables/lib/string.c
 create mode 100644 tools/linker-tables/main.c
 create mode 100644 tools/linker-tables/pci-quirks.c
 create mode 100644 tools/linker-tables/pci.c

-- 
2.10.1


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v2 1/6] tools: add a userspace tools bug.h
  2016-12-22  2:39       ` Luis R. Rodriguez
  (?)
@ 2016-12-22  2:39         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:39 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This will be used later by the userspace linker-tables sandbox.
As a convenience, include bug.h on kernel.h -- this is not done
on upstream kernel.h, however most header files do include bug.h
eventually, if we were to only add the ones that need it we'd
need to copy a lot of headers to tools for the ony purpose of
includeing bug.h. This simplifies that.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/asm-generic/bug.h | 24 ++++++++++++++++++++++++
 tools/include/linux/bug.h       |  6 ++++++
 tools/include/linux/kernel.h    |  2 ++
 3 files changed, 32 insertions(+)
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/linux/bug.h

diff --git a/tools/include/asm-generic/bug.h b/tools/include/asm-generic/bug.h
new file mode 100644
index 000000000000..7b0f48b60dbe
--- /dev/null
+++ b/tools/include/asm-generic/bug.h
@@ -0,0 +1,24 @@
+#ifndef __TOOLS_ASM_GENERIC_BUG
+#define __TOOLS_ASM_GENERIC_BUG
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define BUG() do {										\
+	fprintf(stderr, "----------------------------------------------------------\n");	\
+	fprintf (stderr, "BUG on %s at %s: %i\n", __func__, __FILE__, __LINE__);		\
+	abort();										\
+}												\
+while (0)
+
+#define BUG_ON(cond) do { if (cond) BUG(); } while (0)
+
+#define WARN_ON(__test) do {									\
+	if (__test) {										\
+		fprintf(stderr, "----------------------------------------------------------\n");\
+		fprintf (stderr, "WARN_ON on %s at %s: %i\n", __func__, __FILE__, __LINE__);	\
+	}											\
+}												\
+while (0)
+
+#endif /* __TOOLS_ASM_GENERIC_BUG */
diff --git a/tools/include/linux/bug.h b/tools/include/linux/bug.h
new file mode 100644
index 000000000000..9be515b40b5c
--- /dev/null
+++ b/tools/include/linux/bug.h
@@ -0,0 +1,6 @@
+#ifndef _TOOLS_LINUX_BUG_H
+#define _TOOLS_LINUX_BUG_H
+
+#include <asm-generic/bug.h>
+
+#endif /* _TOOLS_LINUX_BUG_H */
diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
index 28607db02bd3..3d385a6d4fc1 100644
--- a/tools/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -5,6 +5,8 @@
 #include <stddef.h>
 #include <assert.h>
 
+#include <linux/bug.h>
+
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 
 #define PERF_ALIGN(x, a)	__PERF_ALIGN_MASK(x, (typeof(x))(a)-1)
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v2 1/6] tools: add a userspace tools bug.h
@ 2016-12-22  2:39         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:39 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This will be used later by the userspace linker-tables sandbox.
As a convenience, include bug.h on kernel.h -- this is not done
on upstream kernel.h, however most header files do include bug.h
eventually, if we were to only add the ones that need it we'd
need to copy a lot of headers to tools for the ony purpose of
includeing bug.h. This simplifies that.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/asm-generic/bug.h | 24 ++++++++++++++++++++++++
 tools/include/linux/bug.h       |  6 ++++++
 tools/include/linux/kernel.h    |  2 ++
 3 files changed, 32 insertions(+)
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/linux/bug.h

diff --git a/tools/include/asm-generic/bug.h b/tools/include/asm-generic/bug.h
new file mode 100644
index 000000000000..7b0f48b60dbe
--- /dev/null
+++ b/tools/include/asm-generic/bug.h
@@ -0,0 +1,24 @@
+#ifndef __TOOLS_ASM_GENERIC_BUG
+#define __TOOLS_ASM_GENERIC_BUG
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define BUG() do {										\
+	fprintf(stderr, "----------------------------------------------------------\n");	\
+	fprintf (stderr, "BUG on %s at %s: %i\n", __func__, __FILE__, __LINE__);		\
+	abort();										\
+}												\
+while (0)
+
+#define BUG_ON(cond) do { if (cond) BUG(); } while (0)
+
+#define WARN_ON(__test) do {									\
+	if (__test) {										\
+		fprintf(stderr, "----------------------------------------------------------\n");\
+		fprintf (stderr, "WARN_ON on %s at %s: %i\n", __func__, __FILE__, __LINE__);	\
+	}											\
+}												\
+while (0)
+
+#endif /* __TOOLS_ASM_GENERIC_BUG */
diff --git a/tools/include/linux/bug.h b/tools/include/linux/bug.h
new file mode 100644
index 000000000000..9be515b40b5c
--- /dev/null
+++ b/tools/include/linux/bug.h
@@ -0,0 +1,6 @@
+#ifndef _TOOLS_LINUX_BUG_H
+#define _TOOLS_LINUX_BUG_H
+
+#include <asm-generic/bug.h>
+
+#endif /* _TOOLS_LINUX_BUG_H */
diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
index 28607db02bd3..3d385a6d4fc1 100644
--- a/tools/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -5,6 +5,8 @@
 #include <stddef.h>
 #include <assert.h>
 
+#include <linux/bug.h>
+
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 
 #define PERF_ALIGN(x, a)	__PERF_ALIGN_MASK(x, (typeof(x))(a)-1)
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v2 1/6] tools: add a userspace tools bug.h
@ 2016-12-22  2:39         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:39 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

This will be used later by the userspace linker-tables sandbox.
As a convenience, include bug.h on kernel.h -- this is not done
on upstream kernel.h, however most header files do include bug.h
eventually, if we were to only add the ones that need it we'd
need to copy a lot of headers to tools for the ony purpose of
includeing bug.h. This simplifies that.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/asm-generic/bug.h | 24 ++++++++++++++++++++++++
 tools/include/linux/bug.h       |  6 ++++++
 tools/include/linux/kernel.h    |  2 ++
 3 files changed, 32 insertions(+)
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/linux/bug.h

diff --git a/tools/include/asm-generic/bug.h b/tools/include/asm-generic/bug.h
new file mode 100644
index 000000000000..7b0f48b60dbe
--- /dev/null
+++ b/tools/include/asm-generic/bug.h
@@ -0,0 +1,24 @@
+#ifndef __TOOLS_ASM_GENERIC_BUG
+#define __TOOLS_ASM_GENERIC_BUG
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define BUG() do {										\
+	fprintf(stderr, "----------------------------------------------------------\n");	\
+	fprintf (stderr, "BUG on %s at %s: %i\n", __func__, __FILE__, __LINE__);		\
+	abort();										\
+}												\
+while (0)
+
+#define BUG_ON(cond) do { if (cond) BUG(); } while (0)
+
+#define WARN_ON(__test) do {									\
+	if (__test) {										\
+		fprintf(stderr, "----------------------------------------------------------\n");\
+		fprintf (stderr, "WARN_ON on %s at %s: %i\n", __func__, __FILE__, __LINE__);	\
+	}											\
+}												\
+while (0)
+
+#endif /* __TOOLS_ASM_GENERIC_BUG */
diff --git a/tools/include/linux/bug.h b/tools/include/linux/bug.h
new file mode 100644
index 000000000000..9be515b40b5c
--- /dev/null
+++ b/tools/include/linux/bug.h
@@ -0,0 +1,6 @@
+#ifndef _TOOLS_LINUX_BUG_H
+#define _TOOLS_LINUX_BUG_H
+
+#include <asm-generic/bug.h>
+
+#endif /* _TOOLS_LINUX_BUG_H */
diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
index 28607db02bd3..3d385a6d4fc1 100644
--- a/tools/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -5,6 +5,8 @@
 #include <stddef.h>
 #include <assert.h>
 
+#include <linux/bug.h>
+
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 
 #define PERF_ALIGN(x, a)	__PERF_ALIGN_MASK(x, (typeof(x))(a)-1)
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v2 2/6] tools: add init.h for tools
  2016-12-22  2:39       ` Luis R. Rodriguez
  (?)
@ 2016-12-22  2:39         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:39 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Start off with just __ref -- we enalbe you to override, if you do
that then you can define your own. The way you'd use this, if you
do override, is define your own __ref and then use include_next.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/init.h | 9 +++++++++
 1 file changed, 9 insertions(+)
 create mode 100644 tools/include/linux/init.h

diff --git a/tools/include/linux/init.h b/tools/include/linux/init.h
new file mode 100644
index 000000000000..6d970a360a05
--- /dev/null
+++ b/tools/include/linux/init.h
@@ -0,0 +1,9 @@
+#ifndef _TOOLS_LINUX_INIT_H
+#define _TOOLS_LINUX_INIT_H
+
+/* this means you can add your own to fit you own userspace needs */
+#ifndef __ref
+#define __ref
+#endif
+
+#endif /* _TOOLS_LINUX_INIT_H */
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v2 2/6] tools: add init.h for tools
@ 2016-12-22  2:39         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:39 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Start off with just __ref -- we enalbe you to override, if you do
that then you can define your own. The way you'd use this, if you
do override, is define your own __ref and then use include_next.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/init.h | 9 +++++++++
 1 file changed, 9 insertions(+)
 create mode 100644 tools/include/linux/init.h

diff --git a/tools/include/linux/init.h b/tools/include/linux/init.h
new file mode 100644
index 000000000000..6d970a360a05
--- /dev/null
+++ b/tools/include/linux/init.h
@@ -0,0 +1,9 @@
+#ifndef _TOOLS_LINUX_INIT_H
+#define _TOOLS_LINUX_INIT_H
+
+/* this means you can add your own to fit you own userspace needs */
+#ifndef __ref
+#define __ref
+#endif
+
+#endif /* _TOOLS_LINUX_INIT_H */
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v2 2/6] tools: add init.h for tools
@ 2016-12-22  2:39         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:39 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

Start off with just __ref -- we enalbe you to override, if you do
that then you can define your own. The way you'd use this, if you
do override, is define your own __ref and then use include_next.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/init.h | 9 +++++++++
 1 file changed, 9 insertions(+)
 create mode 100644 tools/include/linux/init.h

diff --git a/tools/include/linux/init.h b/tools/include/linux/init.h
new file mode 100644
index 000000000000..6d970a360a05
--- /dev/null
+++ b/tools/include/linux/init.h
@@ -0,0 +1,9 @@
+#ifndef _TOOLS_LINUX_INIT_H
+#define _TOOLS_LINUX_INIT_H
+
+/* this means you can add your own to fit you own userspace needs */
+#ifndef __ref
+#define __ref
+#endif
+
+#endif /* _TOOLS_LINUX_INIT_H */
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v2 3/6] tools: add __used and enable to override
  2016-12-22  2:39       ` Luis R. Rodriguez
  (?)
@ 2016-12-22  2:39         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:39 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This adds __used, to be used later in the userspace linker-tables
sandbox. If any userspace applicaiton wants to override they can
add their own definition and then use include_next.

This definition should probably suffice for most uses cases though.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index e33fc1df3935..556c991de212 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -5,6 +5,12 @@
 /* The "volatile" is due to gcc bugs */
 #define barrier() __asm__ __volatile__("": : :"memory")
 
+
+/* You can override as you see fit on your userspace tool */
+#ifndef __used
+#define __used          __attribute__((__used__))
+#endif
+
 #ifndef __always_inline
 # define __always_inline	inline __attribute__((always_inline))
 #endif
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v2 3/6] tools: add __used and enable to override
@ 2016-12-22  2:39         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:39 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This adds __used, to be used later in the userspace linker-tables
sandbox. If any userspace applicaiton wants to override they can
add their own definition and then use include_next.

This definition should probably suffice for most uses cases though.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index e33fc1df3935..556c991de212 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -5,6 +5,12 @@
 /* The "volatile" is due to gcc bugs */
 #define barrier() __asm__ __volatile__("": : :"memory")
 
+
+/* You can override as you see fit on your userspace tool */
+#ifndef __used
+#define __used          __attribute__((__used__))
+#endif
+
 #ifndef __always_inline
 # define __always_inline	inline __attribute__((always_inline))
 #endif
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v2 3/6] tools: add __used and enable to override
@ 2016-12-22  2:39         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:39 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

This adds __used, to be used later in the userspace linker-tables
sandbox. If any userspace applicaiton wants to override they can
add their own definition and then use include_next.

This definition should probably suffice for most uses cases though.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index e33fc1df3935..556c991de212 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -5,6 +5,12 @@
 /* The "volatile" is due to gcc bugs */
 #define barrier() __asm__ __volatile__("": : :"memory")
 
+
+/* You can override as you see fit on your userspace tool */
+#ifndef __used
+#define __used          __attribute__((__used__))
+#endif
+
 #ifndef __always_inline
 # define __always_inline	inline __attribute__((always_inline))
 #endif
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v2 4/6] tools: expand export.h with VMLINUX_SYMBOL()
  2016-12-22  2:39       ` Luis R. Rodriguez
  (?)
@ 2016-12-22  2:39         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:39 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This will be used later by the linker-table userspace sandbox.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/export.h | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/tools/include/linux/export.h b/tools/include/linux/export.h
index d07e586b9ba0..cb7d6b490e08 100644
--- a/tools/include/linux/export.h
+++ b/tools/include/linux/export.h
@@ -1,6 +1,28 @@
 #ifndef _TOOLS_LINUX_EXPORT_H_
 #define _TOOLS_LINUX_EXPORT_H_
 
+/*
+ * Export symbols from the kernel to modules.  Forked from module.h
+ * to reduce the amount of pointless cruft we feed to gcc when only
+ * exporting a simple symbol or two.
+ *
+ * Try not to add #includes here.  It slows compilation and makes kernel
+ * hackers place grumpy comments in header files.
+ */
+
+/* Some toolchains use a `_' prefix for all user symbols. */
+#ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX
+#define __VMLINUX_SYMBOL(x) _##x
+#define __VMLINUX_SYMBOL_STR(x) "_" #x
+#else
+#define __VMLINUX_SYMBOL(x) x
+#define __VMLINUX_SYMBOL_STR(x) #x
+#endif
+
+/* Indirect, so macros are expanded before pasting. */
+#define VMLINUX_SYMBOL(x) __VMLINUX_SYMBOL(x)
+#define VMLINUX_SYMBOL_STR(x) __VMLINUX_SYMBOL_STR(x)
+
 #define EXPORT_SYMBOL(sym)
 #define EXPORT_SYMBOL_GPL(sym)
 #define EXPORT_SYMBOL_GPL_FUTURE(sym)
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v2 4/6] tools: expand export.h with VMLINUX_SYMBOL()
@ 2016-12-22  2:39         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:39 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This will be used later by the linker-table userspace sandbox.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/export.h | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/tools/include/linux/export.h b/tools/include/linux/export.h
index d07e586b9ba0..cb7d6b490e08 100644
--- a/tools/include/linux/export.h
+++ b/tools/include/linux/export.h
@@ -1,6 +1,28 @@
 #ifndef _TOOLS_LINUX_EXPORT_H_
 #define _TOOLS_LINUX_EXPORT_H_
 
+/*
+ * Export symbols from the kernel to modules.  Forked from module.h
+ * to reduce the amount of pointless cruft we feed to gcc when only
+ * exporting a simple symbol or two.
+ *
+ * Try not to add #includes here.  It slows compilation and makes kernel
+ * hackers place grumpy comments in header files.
+ */
+
+/* Some toolchains use a `_' prefix for all user symbols. */
+#ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX
+#define __VMLINUX_SYMBOL(x) _##x
+#define __VMLINUX_SYMBOL_STR(x) "_" #x
+#else
+#define __VMLINUX_SYMBOL(x) x
+#define __VMLINUX_SYMBOL_STR(x) #x
+#endif
+
+/* Indirect, so macros are expanded before pasting. */
+#define VMLINUX_SYMBOL(x) __VMLINUX_SYMBOL(x)
+#define VMLINUX_SYMBOL_STR(x) __VMLINUX_SYMBOL_STR(x)
+
 #define EXPORT_SYMBOL(sym)
 #define EXPORT_SYMBOL_GPL(sym)
 #define EXPORT_SYMBOL_GPL_FUTURE(sym)
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v2 4/6] tools: expand export.h with VMLINUX_SYMBOL()
@ 2016-12-22  2:39         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:39 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

This will be used later by the linker-table userspace sandbox.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/export.h | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/tools/include/linux/export.h b/tools/include/linux/export.h
index d07e586b9ba0..cb7d6b490e08 100644
--- a/tools/include/linux/export.h
+++ b/tools/include/linux/export.h
@@ -1,6 +1,28 @@
 #ifndef _TOOLS_LINUX_EXPORT_H_
 #define _TOOLS_LINUX_EXPORT_H_
 
+/*
+ * Export symbols from the kernel to modules.  Forked from module.h
+ * to reduce the amount of pointless cruft we feed to gcc when only
+ * exporting a simple symbol or two.
+ *
+ * Try not to add #includes here.  It slows compilation and makes kernel
+ * hackers place grumpy comments in header files.
+ */
+
+/* Some toolchains use a `_' prefix for all user symbols. */
+#ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX
+#define __VMLINUX_SYMBOL(x) _##x
+#define __VMLINUX_SYMBOL_STR(x) "_" #x
+#else
+#define __VMLINUX_SYMBOL(x) x
+#define __VMLINUX_SYMBOL_STR(x) #x
+#endif
+
+/* Indirect, so macros are expanded before pasting. */
+#define VMLINUX_SYMBOL(x) __VMLINUX_SYMBOL(x)
+#define VMLINUX_SYMBOL_STR(x) __VMLINUX_SYMBOL_STR(x)
+
 #define EXPORT_SYMBOL(sym)
 #define EXPORT_SYMBOL_GPL(sym)
 #define EXPORT_SYMBOL_GPL_FUTURE(sym)
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v2 5/6] tools: add __section() to compiler.h
  2016-12-22  2:39       ` Luis R. Rodriguez
  (?)
@ 2016-12-22  2:39         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:39 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This will be used later by the userspace linker table.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index 556c991de212..6321265df00a 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -132,4 +132,6 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 #define WRITE_ONCE(x, val) \
 	({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
 
+#define __section(S)	__attribute__ ((__section__(#S)))
+
 #endif /* _TOOLS_LINUX_COMPILER_H */
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v2 5/6] tools: add __section() to compiler.h
@ 2016-12-22  2:39         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:39 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This will be used later by the userspace linker table.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index 556c991de212..6321265df00a 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -132,4 +132,6 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 #define WRITE_ONCE(x, val) \
 	({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
 
+#define __section(S)	__attribute__ ((__section__(#S)))
+
 #endif /* _TOOLS_LINUX_COMPILER_H */
-- 
2.10.1

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v2 5/6] tools: add __section() to compiler.h
@ 2016-12-22  2:39         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:39 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

This will be used later by the userspace linker table.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index 556c991de212..6321265df00a 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -132,4 +132,6 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 #define WRITE_ONCE(x, val) \
 	({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
 
+#define __section(S)	__attribute__ ((__section__(#S)))
+
 #endif /* _TOOLS_LINUX_COMPILER_H */
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v2 6/6] tools: add userspace linker table sandbox
  2016-12-22  2:39       ` Luis R. Rodriguez
@ 2016-12-22  2:39         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:39 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Add a userspace sandbox to allow easy experimentation and
test extensions with linker tables, section ranges and the
new section core definitions.

The userspace sandbox tries to mimic the Linux kernel development
flow as much as possible, it however relies on and uses libc. Support
is currently only provided to x86_64.

Demo run:

cd tools/linker-tables
make clean; make;
./demo
Initializing x86 bare metal world
x86-init: Number of init entries: 8
Initializing memory ...
Completed initializing memory !
Initializing pci ...
PCI fixup size: 1
Demo: Using LINKTABLE_FOR_EACH
foo_fixup
Demo: Using LINKTABLE_RUN_ALL
foo_fixup
Completed initializing pci !
Number of init entries: 1
Initializing kprobes ...
== OK: test_kprobe_0001 within range!
== OK: test_kprobe_0002 not in range as expected!
Completed initializing kprobes !
Initializing kasan ...
Early init for Kasan...
Completed initializing kasan !
Initializing beta ...
Completed initializing beta !
Initializing alpha ...
Completed initializing alpha !
Booting bare metal
Calling start_kernel()...
ACME: Initializing ...
ACME: Finished init ... !
Synthetics: synth_init_or(2) returns: 0xDEADBEEF
Synthetics: ps_shr(0xDEADBEEF, get_demo_shr) returns: 0x0000DEAD

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clashes with compiler generated
  sections.

o moves tools/include/linux/printk.h to tools
  linker-table/include/linux/printk.h -- we cannot generalize this
  just yet, more work is needed in terms of providing a namespace for
  headers for types of ports of kernel functionality to userspace.

o Adjust code according to the latest discussions for the linker
  tables API (section name macros are now gone).

o Give CONFIG_HAVE_ARCH_PS_CONST for x86 another good 'ol college try,
  still fails, but this is just a demo anyway. We can amend and fix
  make this more optimized for x86 later. Thanks Boris!

v4: this patch is new in this series -- added to the kenrel as
    suggested by Boris, as otherwise it'd be really hard to keep
    an external userspace repository in sync.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/linker-tables.rst           |   4 +-
 MAINTAINERS                                        |   1 +
 include/linux/tables.h                             |   5 +-
 tools/Makefile                                     |   3 +-
 .../arch/x86/include/generated/asm/section-core.h  |   1 +
 tools/arch/x86/include/generated/ranges.h          |   1 +
 tools/arch/x86/include/generated/tables.h          |   1 +
 tools/include/asm-generic/ranges.h                 |  93 +++
 tools/include/asm-generic/section-core.h           | 348 +++++++++++
 tools/include/asm-generic/tables.h                 |  48 ++
 tools/include/linux/ranges.h                       | 183 ++++++
 tools/include/linux/sections.h                     |  87 +++
 tools/include/linux/string.h                       |   1 +
 tools/include/linux/tables.h                       | 684 +++++++++++++++++++++
 tools/linker-tables/.gitignore                     |   2 +
 tools/linker-tables/Makefile                       | 184 ++++++
 tools/linker-tables/README                         | 114 ++++
 tools/linker-tables/arch/x86/include/asm/asm.h     |  17 +
 tools/linker-tables/arch/x86/include/asm/boot.h    |   1 +
 .../linker-tables/arch/x86/include/asm/bootparam.h |  32 +
 tools/linker-tables/arch/x86/include/asm/kprobes.h |   7 +
 .../linker-tables/arch/x86/include/asm/ps_const.h  |  23 +
 tools/linker-tables/arch/x86/include/asm/ranges.h  |   6 +
 .../arch/x86/include/asm/section-core.h            |   1 +
 tools/linker-tables/arch/x86/include/asm/setup.h   |   6 +
 tools/linker-tables/arch/x86/include/asm/tables.h  |   6 +
 tools/linker-tables/arch/x86/include/asm/x86.h     |   4 +
 .../arch/x86/include/asm/x86_init_fn.h             | 169 +++++
 tools/linker-tables/arch/x86/kernel/alpha.c        |   9 +
 tools/linker-tables/arch/x86/kernel/alternative.c  |  31 +
 tools/linker-tables/arch/x86/kernel/beta.c         |   9 +
 tools/linker-tables/arch/x86/kernel/head64.c       |  58 ++
 tools/linker-tables/arch/x86/kernel/init.c         |  42 ++
 tools/linker-tables/arch/x86/kernel/kasan.c        |  10 +
 tools/linker-tables/arch/x86/kernel/kprobes.c      |  51 ++
 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S  | 277 +++++++++
 tools/linker-tables/arch/x86/mm/init.c             |  10 +
 tools/linker-tables/arch/x86/xen/init.c            |  13 +
 tools/linker-tables/drivers/acme.c                 |  32 +
 tools/linker-tables/drivers/synth/common.c         |  16 +
 tools/linker-tables/drivers/synth/common.h         |   2 +
 tools/linker-tables/drivers/synth/main.c           |  35 ++
 tools/linker-tables/drivers/synth/or.S             |  39 ++
 tools/linker-tables/drivers/synth/synth.h          |   2 +
 tools/linker-tables/drivers/xen-driver.c           |  11 +
 .../include/asm-generic/arch_init_fn.h             |  50 ++
 tools/linker-tables/include/asm-generic/kprobes.h  |  26 +
 tools/linker-tables/include/linux/bitops.h         |   6 +
 tools/linker-tables/include/linux/init.h           |  40 ++
 tools/linker-tables/include/linux/kasan.h          |   5 +
 tools/linker-tables/include/linux/kernel.h         |   2 +
 tools/linker-tables/include/linux/kprobes.h        |  11 +
 tools/linker-tables/include/linux/module.h         |  14 +
 tools/linker-tables/include/linux/mutex.h          |  17 +
 tools/linker-tables/include/linux/pci.h            |   7 +
 tools/linker-tables/include/linux/printk.h         |  26 +
 tools/linker-tables/include/linux/ps_const.h       |  46 ++
 tools/linker-tables/include/linux/sched.h          |   9 +
 tools/linker-tables/include/linux/spinlock.h       |  13 +
 tools/linker-tables/include/linux/start_kernel.h   |   1 +
 tools/linker-tables/include/linux/types.h          |  13 +
 tools/linker-tables/include/linux/workqueue.h      |  51 ++
 tools/linker-tables/include/xen/xen.h              |   4 +
 tools/linker-tables/kernel/locking/mutex.c         |  28 +
 tools/linker-tables/kernel/locking/spinlock.c      |  26 +
 tools/linker-tables/kernel/main.c                  |  32 +
 tools/linker-tables/kernel/workqueue.c             |  43 ++
 tools/linker-tables/lib/string.c                   |  26 +
 tools/linker-tables/main.c                         |  20 +
 tools/linker-tables/pci-quirks.c                   |  13 +
 tools/linker-tables/pci.c                          |  29 +
 71 files changed, 3232 insertions(+), 5 deletions(-)
 create mode 100644 tools/arch/x86/include/generated/asm/section-core.h
 create mode 100644 tools/arch/x86/include/generated/ranges.h
 create mode 100644 tools/arch/x86/include/generated/tables.h
 create mode 100644 tools/include/asm-generic/ranges.h
 create mode 100644 tools/include/asm-generic/section-core.h
 create mode 100644 tools/include/asm-generic/tables.h
 create mode 100644 tools/include/linux/ranges.h
 create mode 100644 tools/include/linux/sections.h
 create mode 100644 tools/include/linux/tables.h
 create mode 100644 tools/linker-tables/.gitignore
 create mode 100644 tools/linker-tables/Makefile
 create mode 100644 tools/linker-tables/README
 create mode 100644 tools/linker-tables/arch/x86/include/asm/asm.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/boot.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/bootparam.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/kprobes.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ps_const.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ranges.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/section-core.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/setup.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/tables.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
 create mode 100644 tools/linker-tables/arch/x86/kernel/alpha.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/alternative.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/beta.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/head64.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/init.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kasan.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kprobes.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
 create mode 100644 tools/linker-tables/arch/x86/mm/init.c
 create mode 100644 tools/linker-tables/arch/x86/xen/init.c
 create mode 100644 tools/linker-tables/drivers/acme.c
 create mode 100644 tools/linker-tables/drivers/synth/common.c
 create mode 100644 tools/linker-tables/drivers/synth/common.h
 create mode 100644 tools/linker-tables/drivers/synth/main.c
 create mode 100644 tools/linker-tables/drivers/synth/or.S
 create mode 100644 tools/linker-tables/drivers/synth/synth.h
 create mode 100644 tools/linker-tables/drivers/xen-driver.c
 create mode 100644 tools/linker-tables/include/asm-generic/arch_init_fn.h
 create mode 100644 tools/linker-tables/include/asm-generic/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/bitops.h
 create mode 100644 tools/linker-tables/include/linux/init.h
 create mode 100644 tools/linker-tables/include/linux/kasan.h
 create mode 100644 tools/linker-tables/include/linux/kernel.h
 create mode 100644 tools/linker-tables/include/linux/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/module.h
 create mode 100644 tools/linker-tables/include/linux/mutex.h
 create mode 100644 tools/linker-tables/include/linux/pci.h
 create mode 100644 tools/linker-tables/include/linux/printk.h
 create mode 100644 tools/linker-tables/include/linux/ps_const.h
 create mode 100644 tools/linker-tables/include/linux/sched.h
 create mode 100644 tools/linker-tables/include/linux/spinlock.h
 create mode 100644 tools/linker-tables/include/linux/start_kernel.h
 create mode 100644 tools/linker-tables/include/linux/types.h
 create mode 100644 tools/linker-tables/include/linux/workqueue.h
 create mode 100644 tools/linker-tables/include/xen/xen.h
 create mode 100644 tools/linker-tables/kernel/locking/mutex.c
 create mode 100644 tools/linker-tables/kernel/locking/spinlock.c
 create mode 100644 tools/linker-tables/kernel/main.c
 create mode 100644 tools/linker-tables/kernel/workqueue.c
 create mode 100644 tools/linker-tables/lib/string.c
 create mode 100644 tools/linker-tables/main.c
 create mode 100644 tools/linker-tables/pci-quirks.c
 create mode 100644 tools/linker-tables/pci.c

diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index a80f4dd94659..82a71cfe8e59 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -11,11 +11,11 @@ About Linker tables
 .. kernel-doc:: include/linux/tables.h
    :doc: Introduction
 
-Linker table provenance
+Linker table provenance and userspace testing
 ---------------------------------------------
 
 .. kernel-doc:: include/linux/tables.h
-   :doc: Linker table provenance
+   :doc: Linker table provenance and userspace testing
 
 Benefits of using Linker tables
 ===============================
diff --git a/MAINTAINERS b/MAINTAINERS
index c57ba50e2348..2670d55135ed 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5413,6 +5413,7 @@ L:	linux-kernel@vger.kernel.org
 S:	Supported
 F:	include/asm-generic/tables.h
 F:	include/linux/tables.h
+F:	tools/linker-tables/
 F:	Documentation/sections/linker-tables.rst
 
 GENERIC PHY FRAMEWORK
diff --git a/include/linux/tables.h b/include/linux/tables.h
index fdadf794b63e..a1fbbd20fd13 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -35,12 +35,13 @@
  */
 
 /**
- * DOC: Linker table provenance
+ * DOC: Linker table provenance and userspace testing
  *
  * 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].
+ * userspace linker-table tree [1]. Linux has a similar userspace application
+ * in tools/linker-tables/ to help more easily test adding new extensions.
  *
  * Contrary to iPXE's solution which strives to force compilation of
  * everything using linker tables, Linux's solution allows for developers to be
diff --git a/tools/Makefile b/tools/Makefile
index 00caacd3ed92..ecb2e651c930 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -19,6 +19,7 @@ help:
 	@echo '  kvm_stat               - top-like utility for displaying kvm statistics'
 	@echo '  leds                   - LEDs  tools'
 	@echo '  lguest                 - a minimal 32-bit x86 hypervisor'
+	@echo '  linker-tables		- userspace liker table sandbox and related tools'
 	@echo '  net                    - misc networking tools'
 	@echo '  perf                   - Linux performance measurement and analysis tool'
 	@echo '  selftests              - various kernel selftests'
@@ -86,7 +87,7 @@ tmon: FORCE
 freefall: FORCE
 	$(call descend,laptop/$@)
 
-all: acpi cgroup cpupower gpio hv firewire lguest \
+all: acpi cgroup cpupower gpio hv firewire lguest linker-tables \
 		perf selftests turbostat usb \
 		virtio vm net x86_energy_perf_policy \
 		tmon freefall objtool
diff --git a/tools/arch/x86/include/generated/asm/section-core.h b/tools/arch/x86/include/generated/asm/section-core.h
new file mode 100644
index 000000000000..06be2b1c424f
--- /dev/null
+++ b/tools/arch/x86/include/generated/asm/section-core.h
@@ -0,0 +1 @@
+#include <asm-generic/section-core.h>
diff --git a/tools/arch/x86/include/generated/ranges.h b/tools/arch/x86/include/generated/ranges.h
new file mode 100644
index 000000000000..dac1a9a11367
--- /dev/null
+++ b/tools/arch/x86/include/generated/ranges.h
@@ -0,0 +1 @@
+#include <asm-generic/ranges.h>
diff --git a/tools/arch/x86/include/generated/tables.h b/tools/arch/x86/include/generated/tables.h
new file mode 100644
index 000000000000..d437818275c5
--- /dev/null
+++ b/tools/arch/x86/include/generated/tables.h
@@ -0,0 +1 @@
+#include <asm-generic/tables.h>
diff --git a/tools/include/asm-generic/ranges.h b/tools/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..75c196864f45
--- /dev/null
+++ b/tools/include/asm-generic/ranges.h
@@ -0,0 +1,93 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  any, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       any, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   any, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(#section "..rng.name.any")))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using
+ * 	binutils SORT(), the number is sorted as a string, as such be
+ * 	sure to fill with zeroes any empty digits. For instance if you are
+ * 	using 3 levels of digits for order levels, use 001 for the first entry,
+ * 	0002 for the second, 999 for the last entry. You can use however many
+ * 	digits you need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(#section "..rng.name." #level)))
+
+#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/tools/include/asm-generic/section-core.h b/tools/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..65fb076765f8
--- /dev/null
+++ b/tools/include/asm-generic/section-core.h
@@ -0,0 +1,348 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Linux ELF program specific sections
+ *
+ * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and
+ * definition of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
+ * sections. This chaper is dedicated to documenting Linux program specific
+ * sections and helpers available to make use of these easier to implement and
+ * use.
+ *
+ * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
+ */
+
+/**
+ * DOC: Linux linker script
+ *
+ * Linux uses a custom linker script to build the vmlinux binary, it uses it to
+ * strategically place and define Linux ELF sections.  Each architecture needs
+ * to implement its own linker script, it is expected to reside in
+ * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
+ * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
+ * as well as some helpers documented in this chapter.
+ *
+ * In assembly it is common practice to use dots (``.``) in labels to avoid
+ * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
+ * name but not a C symbol. Historically then, two dots are used (``..``)
+ * have been used in linker scripts when adding program specific sections
+ * when there are concerns to avoid clashes with compiler generated sections.
+ */
+
+/**
+ * DOC: Memory protection
+ *
+ * Linux allows architectures which support memory protection features to
+ * take advantage of them by letting architectures define and enable
+ * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.
+ * mark_rodata_ro() can be used for instance to mark specific sections as
+ * read-only or non-executable.
+ *
+ * Linux typically follows a convention to have the .rodata ELF section follow
+ * after the .text ELF section, it does this to help architectures which
+ * support memory protection to mark both .text and .rodata as read-only in
+ * one shot.
+ *
+ * For more details refer to mark_rodata_ro().
+ */
+
+/**
+ * DOC: .rodata
+ *
+ * ELF section used for data which must be protected from write access.
+ */
+
+/**
+ * DOC: .text
+ *
+ * ELF section name used for code (functions) used during regular
+ * kernel run time.
+ */
+
+/**
+ * DOC: .data
+ *
+ * ELF section used for read-write data.
+ */
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: .init.text
+ *
+ * ELF section for code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+
+/**
+ * DOC: .init.data
+ *
+ * ELF section used for data structures used only during boot or driver
+ * initialization.
+ */
+
+/**
+ * DOC: .init.rodata
+ *
+ * ELF section used for read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+
+/**
+ * DOC: .initcall
+ *
+ * ELF section used for subsystem init calls. There are init levels
+ * representing different functionality in the kernel. For more details
+ * refer to __define_initcall().
+ */
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: .exit.text
+ *
+ * ELF section used to for code (functions) used only during module unload.
+ */
+
+/**
+ * DOC: .exit.data
+ *
+ * ELF section used to for data structures used only during module
+ * unload.
+ */
+
+/**
+ * DOC: .exitcall.exit
+ *
+ * ELF section used for exit routines, order is important and maintained by
+ * link order.
+ */
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: .ref.text
+ *
+ * ELF section used to annotate code (functions) which has been vetteed as
+ * valid for its reference or use of other code (functions) or data structures
+ * which are part of the init sections.
+ */
+
+/**
+ * DOC: .ref.data
+ *
+ * ELF section used for data structures which have been vetteed for its
+ * reference or use of other code (functions) or data structures part of the
+ * init sections.
+ */
+
+/**
+ * DOC: .ref.rodata
+ *
+ * ELF section used to annotate const code (functions) const data structures
+ * which has been vetteed for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections alpha numerically. Linux has historically used 'SORT()' in
+ * ``include/asm-generic/vmlinux.lds.h``, its a well established practice. If
+ * 'SORT()' is used on a section one can provide ordering using a postfix on
+ * each section entry added. For instance if a linker script uses::
+ *
+ *    SORT(.foo.*)
+ *
+ * one can then add entries with explicit ordering using numeric postfixes for
+ * each entry, we refer to these as 'order levels'. Since 'SORT()' sorts alpha
+ * numerically a specific series set of digits must be agreed a-priori which
+ * would give also an idea of the max expected number of entries added to a
+ * section. For instance, if you expect a maximum of 999 entries you can use
+ * 3 digits for a section order level. If you wanted an entry to be ordered
+ * first you could use the postfix '000', if you wanted an entry to follow this
+ * you could use '001', and so on. We could for instance have::
+ *
+ *    .foo.000
+ *    .foo.001
+ *    .foo.002
+ *
+ * Often times one may want the option to specify no order is required for
+ * certain elements added to a section which does use 'SORT()' on the linker
+ * script. You can use any arbitrary string value to to specify no order is
+ * used, so long as its used consistantly. For instance, one possibility is to
+ * use the 'any' postfix.  All entries on the section would then have no
+ * specific ordering::
+ *
+ *    .foo.any
+ *    .foo.any
+ *    .foo.any
+ *
+ * To help establish a convention we reserve the special name 'any' for this
+ * purpose. Developers can use and expect the 'any' postfix string on sections
+ * as a helper to annotate section ordering at link time is not relevant
+ * for entries on a section.
+ */
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section..___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section..__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifndef LINKER_SCRIPT
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align=16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/tools/include/asm-generic/tables.h b/tools/include/asm-generic/tables.h
new file mode 100644
index 000000000000..16ef40d145fb
--- /dev/null
+++ b/tools/include/asm-generic/tables.h
@@ -0,0 +1,48 @@
+#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..tbl.name.level
+
+/* Some toolchains are buggy, let them override */
+#ifndef SECTION_TBL_RO
+# define SECTION_TBL_RO	.rodata
+#endif
+
+#define SECTION_TBL_RO_STR __stringify(SECTION_TBL_RO)
+
+#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, 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, any, flags)
+#endif
+
+#endif /* _ASM_GENERIC_TABLES_H_ */
diff --git a/tools/include/linux/ranges.h b/tools/include/linux/ranges.h
new file mode 100644
index 000000000000..1e64674f6d7d
--- /dev/null
+++ b/tools/include/linux/ranges.h
@@ -0,0 +1,183 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * SECTION_RANGE_START - get address of start of section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the start address of the section range.
+ * This should give you the address of the first entry.
+ *
+ */
+#define SECTION_RANGE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * SECTION_RANGE_END - get address of end of the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define SECTION_RANGE_END(name)		LINUX_SECTION_END(name)
+
+/**
+ * SECTION_RANGE_SIZE - get number of entries in the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the number of entries in the section range.
+ * Example usage:
+ *
+ *   unsigned int num_ents = LINKTABLE_SIZE(some_fns);
+ */
+#define SECTION_RANGE_SIZE(name)					\
+	((SECTION_RANGE_END(name)) - (SECTION_RANGE_START(name)))
+
+/**
+ * SECTION_RANGE_EMPTY - check if section range has no entries
+ *
+ * @name: name of the section range
+ *
+ * Returns true if the section range is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(some_fns);
+ */
+#define SECTION_RANGE_EMPTY(name)	(SECTION_RANGE_SIZE(name) == 0)
+
+/**
+ * SECTION_RANGE_ADDR_WITHIN - returns true if address is in the section range
+ *
+ * @name: name of the section range
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_RANGE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) SECTION_RANGE_START(name) &&		\
+          addr < (unsigned long) SECTION_RANGE_END(name))
+
+/**
+ * SECTION_RANGE_ALIGNMENT - get the alignment of the section range
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the section range.
+ */
+#define SECTION_RANGE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.")))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.~")))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) SECTION_RANGE_START(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) SECTION_RANGE_END(name)[0] = {}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
diff --git a/tools/include/linux/sections.h b/tools/include/linux/sections.h
new file mode 100644
index 000000000000..6771c727bcd1
--- /dev/null
+++ b/tools/include/linux/sections.h
@@ -0,0 +1,87 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_CORE(section, core, name, level)			\
+	#section ".." #core "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
diff --git a/tools/include/linux/string.h b/tools/include/linux/string.h
index f436d2420a18..a6b12564bbd9 100644
--- a/tools/include/linux/string.h
+++ b/tools/include/linux/string.h
@@ -3,6 +3,7 @@
 
 
 #include <linux/types.h>	/* for size_t */
+#include <string.h>
 
 void *memdup(const void *src, size_t len);
 
diff --git a/tools/include/linux/tables.h b/tools/include/linux/tables.h
new file mode 100644
index 000000000000..a1fbbd20fd13
--- /dev/null
+++ b/tools/include/linux/tables.h
@@ -0,0 +1,684 @@
+#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 and userspace testing
+ *
+ * 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]. Linux has a similar userspace application
+ * in tools/linker-tables/ to help more easily test adding new extensions.
+ *
+ * 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(.foo..tbl.*))
+ *
+ * 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: The code bit-rot problem
+ *
+ * Linux provides a rich array of features, enabling each feature
+ * however increases the size of the kernel and there are many
+ * features which users often want disabled. The traditional
+ * solution to this problem is for each feature to have its own
+ * Kconfig symbol, followed by a series of #ifdef statements
+ * in C code and header files, allowing the feature to be compiled
+ * only when desirable. As the variability of Linux increases build
+ * tests can and are often done with random kernel configurations,
+ * allyesconfig, and allmodconfig to help find code issues. This
+ * however doesn't catch all errors and as a consequence code that
+ * is typically not enabled often can suffer from bit-rot over time.
+ */
+
+/**
+ * DOC: The build-all selective-link philosophy
+ *
+ * A code architecture philosophy to help avoid code bit-rot consists
+ * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
+ * by instead having each feature implemented it its own C file, and force
+ * compilation for all features. Only features that are enabled get linked in,
+ * the forced compilation therefore has no size impact on the final result of
+ * the kernel. The practice of having each feature implemented in its own C
+ * file is already prevalent in many subsystems, however #ifdefs are still
+ * typically required during feature initialization. For instance in::
+ *
+ *	#ifdef CONFIG_FOO
+ *	foo_init();
+ *	#endif
+ *
+ * We cannot remove the #ifdef and leave foo_init() as we'd either
+ * need to always enable the feature or add a respective #ifdef in a
+ * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem with linker tables
+ *
+ * Linker tables can be used to further help avoid the code bit-rot problem
+ * when embracing the 'build-all selective-link philosophy' by lifting the
+ * requirement to use of #ifdefs during initialization. With linker tables
+ * initialization sequences can be aggregated into a custom ELF section at
+ * link time, during run time the table can be iterated over and each init
+ * sequence enabled can be called. A feature's init routine is only added to a
+ * table when its respective Kconfig symbols has been enabled and therefore
+ * linked in. Linker tables enable subsystems to completely do away with
+ * #ifdefs if one is comfortable in accepting all subsystem's feature's
+ * structural size implications.
+ *
+ * To further help with this the Linux build system supports two special
+ * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
+ * follow the 'build-all selective-link philosophy' can use these targets for a
+ * feature's kconfig symbol. Using these targets will always require
+ * compilation of the kconfig's objects if the kconfig symbol's dependencies
+ * are met but only link the objects into the kernel, and therefore enable the
+ * feature, if and only if the kconfig symbol has been enabled.
+ *
+ * Not all users or build systems may want to opt-in to compile all objects
+ * following the 'build-all selective-link philosophy', as such the targets
+ * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
+ * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
+ * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
+ * ``obj-y`` and ``lib-y`` respectively.
+ *
+ * Example use::
+ *
+ * 	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+ */
+
+/**
+ * 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_START - get address of start of linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the start address of the linker table.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINKTABLE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * LINKTABLE_END - get address of end of the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define LINKTABLE_END(name)	LINUX_SECTION_END(name)
+
+/**
+ * LINKTABLE_SIZE - get number of entries in the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the number of entries in the linker table.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINKTABLE_SIZE(frobnicator_fns);
+ */
+#define LINKTABLE_SIZE(name)					\
+	((LINKTABLE_END(name)) - (LINKTABLE_START(name)))
+
+/**
+ * LINKTABLE_EMPTY - check if linker table has no entries
+ *
+ * @name: name of linker table
+ *
+ * Returns true if the linker table is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(frobnicator_fns);
+ */
+#define LINKTABLE_EMPTY(name)	(LINKTABLE_SIZE(name) == 0)
+
+/**
+ * LINKTABLE_ADDR_WITHIN - returns true if address is in the linker table
+ *
+ * @name: name of the linker table
+ * @addr: address to query for
+ *
+ * Returns true if the address is part of the linker table.
+ */
+#define LINKTABLE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) LINKTABLE_START(name) &&		\
+          addr < (unsigned long) LINKTABLE_END(name))
+
+/**
+ * LINKTABLE_ALIGNMENT - get the alignment of the linker table
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the linker table.
+ */
+#define LINKTABLE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * 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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_TEXT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE_RO(name, ~) LINKTABLE_END(name)[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_RO(type, name);				\
+	LINKTABLE_INIT_WEAK(name,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT_DATA(name, ~) LINKTABLE_END(name)[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 = LINKTABLE_START(tbl);				\
+	     pointer < LINKTABLE_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 < LINKTABLE_SIZE(tbl); i++)			\
+		(LINKTABLE_START(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 < LINKTABLE_SIZE(tbl); i++)		\
+		err = (LINKTABLE_START(tbl)[i]).func (args);		\
+		err;							\
+})
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_LINKER_TABLES_H */
diff --git a/tools/linker-tables/.gitignore b/tools/linker-tables/.gitignore
new file mode 100644
index 000000000000..8275b0c55385
--- /dev/null
+++ b/tools/linker-tables/.gitignore
@@ -0,0 +1,2 @@
+arch/x86/kernel/vmlinux.lds
+demo
diff --git a/tools/linker-tables/Makefile b/tools/linker-tables/Makefile
new file mode 100644
index 000000000000..9d4e6fb0d176
--- /dev/null
+++ b/tools/linker-tables/Makefile
@@ -0,0 +1,184 @@
+include ../scripts/Makefile.include
+
+all:
+
+include ../scripts/utilities.mak
+
+MAKEFLAGS += --no-print-directory
+
+unexport LC_ALL
+LC_COLLATE=C
+LC_NUMERIC=C
+export LC_COLLATE LC_NUMERIC
+
+ifeq ($(srctree),)
+	srctree := $(patsubst %/,%,$(dir $(shell pwd)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Determined 'srctree' to be $(srctree))
+endif
+
+ifneq ($(objtree),)
+#$(info Determined 'objtree' to be $(objtree))
+endif
+
+ifneq ($(OUTPUT),)
+#$(info Determined 'OUTPUT' to be $(OUTPUT))
+# Adding $(OUTPUT) as a directory to look for source files,
+# because use generated output files as sources dependency
+# for flex/bison parsers.
+VPATH += $(OUTPUT)
+export VPATH
+endif
+
+export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK
+include $(srctree)/tools/build/Makefile.include
+
+ifeq ($(V),1)
+	Q=
+	NQ=@true
+else
+	Q=@
+	NQ=@echo
+endif
+
+MAKEFLAGS += -r
+
+define allow-override
+  $(if $(or $(findstring environment,$(origin $(1))),\
+            $(findstring command line,$(origin $(1)))),,\
+    $(eval $(1) = $(2)))
+endef
+
+# Allow setting CC and AR and LD, or setting CROSS_COMPILE as a prefix.
+$(call allow-override,CC,$(CROSS_COMPILE)gcc)
+$(call allow-override,AR,$(CROSS_COMPILE)ar)
+$(call allow-override,LD,$(CROSS_COMPILE)ld)
+
+LD += $(EXTRA_LDFLAGS)
+
+include $(srctree)/tools/scripts/Makefile.arch
+
+# Refer to README to learn how to support your architecture
+SUPPORTED_ARCHS = x86
+
+ifeq ($(filter $(ARCH),$(SUPPORTED_ARCHS)),)
+$(error Unsupported arch: $(ARCH))
+endif
+
+CFLAGS += -O2 -g
+CFLAGS += -std=gnu99 -Wall -Werror
+CFLAGS += -lpthread
+CFLAGS += -DCONFIG_KPROBES
+
+# We confine the includes used below to those we know are safe
+# for this type of hack.
+CFLAGS += -D__KERNEL__
+
+# CFLAGS += -DCONFIG_HAVE_ARCH_PS_CONST
+INCLUDES = \
+	   -I include/ \
+	   -I arch/$(ARCH)/include/ \
+	   -I ../include/ \
+	   -I ../arch/$(ARCH)/include/ \
+	   -I ../arch/$(ARCH)/include/generated/
+
+CFLAGS += $(INCLUDES)
+CFLAGS +=-Wl,-Tarch/$(ARCH)/kernel/vmlinux.lds
+
+HEADERS = \
+	  ../../include/asm-generic/section-core.h \
+	  ../../include/asm-generic/ranges.h \
+	  ../../include/asm-generic/tables.h \
+	  ../../include/linux/sections.h \
+	  ../../include/linux/ranges.h \
+	  ../../include/linux/tables.h
+
+__check_headers: $(HEADERS)
+	@$(foreach h, $(HEADERS), \
+		(test -f $(h) && ( \
+			(diff -B $(subst ../,../,$(h)) $(h) >/dev/null) \
+			|| echo "Warning: $(subst ../../,tools/,$(h)) differs from kernel" >&2 ) || true);)
+
+$(OUTPUT)arch/$(ARCH)/kernel/vmlinux.lds: arch/$(ARCH)/kernel/vmlinux.lds.S
+	$(NQ) '  LD  ' $@
+	$(Q)$(CC) $(CFLAGS) $(INCLUDES) -E -P \
+		-D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
+
+# Note, we use obj-y as a convenience factor, the cmd build
+# stuff doesn't allow this magic, it resolves our depds but
+# we still need to provide a series of targets for our objects.
+# We stick to the convenient shorthand we're used to in the
+# kernel. The final object resolution build stuff is handled
+# by tool_target_obj and its caller below. This also enables
+# OUTPUT=foo-path support so you can build externally.
+obj-y += \
+	arch/$(ARCH)/kernel/head64.o \
+	arch/$(ARCH)/mm/init.o \
+	kernel/locking/mutex.o \
+	kernel/locking/spinlock.o \
+	kernel/workqueue.o \
+	kernel/main.o \
+	pci.o \
+	lib/string.o \
+	pci-quirks.o \
+	drivers/acme.o \
+	drivers/synth/main.o \
+	drivers/synth/common.o \
+	drivers/synth/or.s \
+	main.o
+
+ifeq ($(ARCH),x86)
+obj-y += \
+	arch/$(ARCH)/kernel/alternative.o \
+	arch/$(ARCH)/kernel/init.o \
+	arch/$(ARCH)/kernel/kprobes.o \
+	arch/$(ARCH)/kernel/kasan.o \
+	arch/$(ARCH)/kernel/beta.o \
+	arch/$(ARCH)/kernel/alpha.o \
+	arch/$(ARCH)/xen/init.o	\
+	drivers/xen-driver.o
+endif
+
+obj-y-out = $(patsubst %,$(OUTPUT)%,$(obj-y))
+
+__build-dir = $(subst $(OUTPUT),,$(dir $1))
+build-dir   = $(if $(__build-dir),$(__build-dir),.)
+
+build := -f $(srctree)/tools/build/Makefile.build dir=$(build-dir)
+
+define tool_target_obj
+$(1): $(subst .s,.S,$(subst .o,.c,$(patsubst $(OUTPUT)%,%,$(1))))
+	$(Q)$(MAKE) $(build) obj=$(1)
+endef
+
+$(foreach tool_obj, $(obj-y-out), \
+	$(eval $(call tool_target_obj, $(tool_obj))))
+
+$(OUTPUT)demo: $(obj-y-out)
+	$(NQ) '  CC  ' $@
+	$(Q)$(CC) $(obj-y-out) -o $@ $(CPPFLAGS) $(CFLAGS)
+
+CHECK_HEADERS := __check_headers
+PHONY += $(CHECK_HEADERS)
+
+CMD_TARGETS = $(OUTPUT)arch/$(ARCH)/kernel/vmlinux.lds $(OUTPUT)demo
+TARGETS = $(CMD_TARGETS)
+
+all: $(CHECK_HEADERS) all_cmd
+
+all_cmd: $(CMD_TARGETS)
+
+ifeq ($(OUTPUT),)
+clean_dir = ./
+else
+clean_dir = $(OUTPUT)
+endif
+
+clean::
+	$(NQ)  '  CLEAN deps'
+	$(Q)find $(clean_dir) -name \*.o \
+		-o -name \*.s \
+		-o -name \*.o.d \
+		-o -name \*.o.cmd | xargs rm -f
+	$(NQ)  '  CLEAN targets'
+	$(Q)$(foreach f, $(CMD_TARGETS), rm -f $(f);)
diff --git a/tools/linker-tables/README b/tools/linker-tables/README
new file mode 100644
index 000000000000..729241f9e4c4
--- /dev/null
+++ b/tools/linker-tables/README
@@ -0,0 +1,114 @@
+Linux linker table userspace sandbox
+====================================
+
+This is a userspace sandbox to allow easy experimentation and
+test extensions with linker tables. It tries to mimic the Linux
+kernel development flow as much as possible, it however relies
+on and uses libc and is nothing but a simple stupid userspace
+application demo.
+
+You can use the sandbox to modify the kernel's linker table
+solution or add use it in creative ways without having to run
+qemu with a real kernel or user mode linux. You can simply try
+to extend this sandbox as you would for a regular userspace
+application.
+
+History
+=======
+
+This was hacked on first in an external repository, that tree has
+the full set of history of how this work came about. Refer to that
+tree for more details if you are interested in the logic used for
+a lot of decisions made for linker tables:
+
+https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linker-tables.git/
+
+This tree is discontinued now in favor of an upstream solution which
+is kept in sync with the kernel.
+
+Compile
+=======
+
+Run:
+	make
+
+Clean:
+	make clean
+
+If you need to get object files outside of the source tree:
+
+	make OUTPUT=/tmp/path/
+	make OUTPUT=/tmp/path/ clean
+
+Supported architectures
+=======================
+
+x86_64
+
+Currently only x86_64 is supported for the demo. It should be
+relatively easy to add more. To add a new architecture you need
+a toolchain available with libc. You then need to generate a
+respective base template custom linker script for userspace
+as is provided on x86 in arch/x86/kernel/vmlinux.lds.S.
+
+A respective architecture tools/arch/$(ARCH)/include/* file for
+each section-core.h, ranges.h, tables.h will need to be provided
+as well. If your architecture's file is generated copy the generated
+file over.
+
+x86 Simulated boots
+===================
+
+This programs simulates boot on both bare metal and with the
+Xen PV entry on x86.
+
+Emulate bare metal boot:
+
+./demo
+
+Emulate Xen boot (x86):
+
+./demo -x
+
+Testing new features
+====================
+
+A copy of each kernel header file is maintained in tools/include/,
+as well as a respective generated asm file for each sandbox supported
+architecture. This sandbox has a built in checker for when these files
+get out of sync.
+
+If testing new extensions on the files:
+
+  o section-core
+  o ranges.h
+  o tables.h
+
+You'll want to copy them into tools as well. If you are working on
+using these files you can work within the current directory's namespace,
+including its own set of header files, so tools/linker-tables/include/ and
+each respective tools/linker-tables/arch/$(ARCH)/include/asm/.
+
+Features evaluation
+===================
+
+This lists features currently being evaluated in the sandbox, not yet
+present upstream. These make use of the existing set of header files
+without modification.
+
+ o Demo use of initialization on for x86, refer to arch/x86/kernel/init.c
+
+ o Demo use of porting the kernel's init call levels to linker tables, refer
+   to the init_calls linker table use on kernel/main.c
+
+ o Demo use of an asm-generic architecture init family, which could potentially
+   be used to help share initialization sequences on simple architectures.
+   Refer to include/asm-generic/arch_init_fn.h
+
+ o Building synthetic routines with the option to provide enhancements
+   per architecture in asm, refer to drivers/synth/or.S and its use on
+   synth_init_or().
+
+ o User of linker tables for alternatives with consts - refer to
+   use of the ps_set_const_table linker table and its use in
+   arch/x86/kernel/alternative.c
diff --git a/tools/linker-tables/arch/x86/include/asm/asm.h b/tools/linker-tables/arch/x86/include/asm/asm.h
new file mode 100644
index 000000000000..155a52920dfb
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/asm.h
@@ -0,0 +1,17 @@
+#ifndef _ASM_X86_ASM_H
+
+#ifdef __ASSEMBLY__
+# define __ASM_FORM(x)	x
+# define __ASM_FORM_RAW(x)     x
+# define __ASM_FORM_COMMA(x) x,
+#else
+# define __ASM_FORM(x)	" " #x " "
+# define __ASM_FORM_RAW(x)     #x
+# define __ASM_FORM_COMMA(x) " " #x ","
+#endif
+
+# define __ASM_SEL(a,b) __ASM_FORM(b)
+# define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(b)
+#define _ASM_PTR	__ASM_SEL(.long, .quad)
+
+#endif /* _ASM_X86_ASM_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/boot.h b/tools/linker-tables/arch/x86/include/asm/boot.h
new file mode 100644
index 000000000000..af91b94ad5a6
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/boot.h
@@ -0,0 +1 @@
+extern struct boot_params boot_params;
diff --git a/tools/linker-tables/arch/x86/include/asm/bootparam.h b/tools/linker-tables/arch/x86/include/asm/bootparam.h
new file mode 100644
index 000000000000..a7ef34216f7f
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/bootparam.h
@@ -0,0 +1,32 @@
+#ifndef __BOOTPARAM_H
+#define __BOOTPARAM_H
+
+#include <linux/types.h>
+
+struct setup_header {
+	__u32 hardware_subarch;
+} __attribute__((packed));
+
+struct boot_params {
+	struct setup_header hdr;
+} __attribute__((packed));
+
+enum {
+	X86_SUBARCH_PC = 0,
+	X86_SUBARCH_LGUEST,
+	X86_SUBARCH_XEN,
+	X86_SUBARCH_INTEL_MID,
+	X86_SUBARCH_CE4100,
+	X86_NR_SUBARCHS,
+};
+
+#define X86_SUBARCH_ALL_SUBARCHS 	\
+	(				\
+	BIT(X86_SUBARCH_PC) |		\
+	BIT(X86_SUBARCH_LGUEST) |	\
+	BIT(X86_SUBARCH_XEN) |		\
+	BIT(X86_SUBARCH_INTEL_MID) |	\
+	BIT(X86_SUBARCH_CE4100)		\
+	)
+
+#endif /* __BOOTPARAM_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/kprobes.h b/tools/linker-tables/arch/x86/include/asm/kprobes.h
new file mode 100644
index 000000000000..f702fc359efe
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/kprobes.h
@@ -0,0 +1,7 @@
+#ifndef _SANDBOX_ASM_X86_KPROBES_H
+#define _SANDBOX_ASM_X86_KPROBES_H
+
+/* This is all we need for the demo */
+#include <asm-generic/kprobes.h>
+
+#endif /* _SANDBOX_ASM_X86_KPROBES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/ps_const.h b/tools/linker-tables/arch/x86/include/asm/ps_const.h
new file mode 100644
index 000000000000..3847f03fca92
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/ps_const.h
@@ -0,0 +1,23 @@
+#ifndef __X86_PS_CONST
+#define __X86_PS_CONST
+
+#include <linux/stringify.h>
+#include <linux/tables.h>
+#include <asm/asm.h>
+
+#define ps_shr(in, _func)						\
+({									\
+	 __typeof__(in) _count;						\
+									\
+	asm volatile(							\
+		"shr %P[_in],%[_count]\n"				\
+		"1:\n"							\
+		push_section_tbl(.init.data, ps_set_const_table, 01,)	\
+		_ASM_PTR "1b-1, %P2, %P3\n"				\
+		".popsection\n"						\
+		: [_count] "=g" (_count)				\
+		: [_in] "i" (in), "i" (SET_CONST_U8), "i" (_func));	\
+	(_count);							\
+})
+
+#endif /* __X86_PS_CONST */
diff --git a/tools/linker-tables/arch/x86/include/asm/ranges.h b/tools/linker-tables/arch/x86/include/asm/ranges.h
new file mode 100644
index 000000000000..823789d2b010
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/ranges.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_RANGES_H
+#define _ASM_X86_RANGES_H
+
+#include <asm-generic/ranges.h>
+
+#endif  /* _ASM_X86_RANGES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/section-core.h b/tools/linker-tables/arch/x86/include/asm/section-core.h
new file mode 100644
index 000000000000..06be2b1c424f
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/section-core.h
@@ -0,0 +1 @@
+#include <asm-generic/section-core.h>
diff --git a/tools/linker-tables/arch/x86/include/asm/setup.h b/tools/linker-tables/arch/x86/include/asm/setup.h
new file mode 100644
index 000000000000..366c36bd2910
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/setup.h
@@ -0,0 +1,6 @@
+#ifndef __LINUX_X86_USER_SETUP_H
+#define __LINUX_X86_USER_SETUP_H
+
+/* I'm lazy */
+
+#endif /* __LINUX_X86_USER_SETUP_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/tables.h b/tools/linker-tables/arch/x86/include/asm/tables.h
new file mode 100644
index 000000000000..797df3407ee1
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/tables.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_TABLES_H
+#define _ASM_X86_TABLES_H
+
+#include <asm-generic/tables.h>
+
+#endif  /* _ASM_X86_RANGES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/x86.h b/tools/linker-tables/arch/x86/include/asm/x86.h
new file mode 100644
index 000000000000..680c1141e0de
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/x86.h
@@ -0,0 +1,4 @@
+int startup_64(void);
+int x86_64_start_reservations(void);
+void setup_arch(void);
+void late_init(void);
diff --git a/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h b/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
new file mode 100644
index 000000000000..afece8ce6dd4
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
@@ -0,0 +1,169 @@
+#ifndef __X86_INIT_TABLES_H
+#define __X86_INIT_TABLES_H
+
+#include <linux/types.h>
+#include <linux/tables.h>
+
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <asm/bootparam.h>
+
+/**
+ * struct x86_init_fn - x86 generic kernel init call
+ *
+ * Linux x86 features vary in complexity, features may require work done at
+ * different levels of the full x86 init sequence. Today there are also two
+ * different possible entry points for Linux on x86, one for bare metal, KVM
+ * and Xen HVM, and another for Xen PV guests / dom0.  Assuming a bootloader
+ * has set up 64-bit mode, roughly the x86 init sequence follows this path:
+ *
+ * Bare metal, KVM, Xen HVM                      Xen PV / dom0
+ *       startup_64()                             startup_xen()
+ *              \                                     /
+ *      x86_64_start_kernel()                 xen_start_kernel()
+ *                           \               /
+ *                      x86_64_start_reservations()
+ *                                   |
+ *                              start_kernel()
+ *                              [   ...        ]
+ *                              [ setup_arch() ]
+ *                              [   ...        ]
+ *                                  init
+ *
+ * x86_64_start_kernel() and xen_start_kernel() are the respective first C code
+ * entry starting points. The different entry points exist to enable Xen to
+ * skip a lot of hardware setup already done and managed on behalf of the
+ * hypervisor, we refer to this as "paravirtualization yielding". The different
+ * levels of init calls on the x86 init sequence exist to account for these
+ * slight differences and requirements. These different entry points also share
+ * a common entry x86 specific path, x86_64_start_reservations().
+ *
+ * A generic x86 feature can have different initialization calls, one on each
+ * of the different main x86 init sequences, but must also address both entry
+ * points in order to work properly across the board on all supported x86
+ * subarchitectures. Since x86 features can also have dependencies on other
+ * setup code or features, x86 features can at times be subordinate to other
+ * x86 features, or conditions. struct x86_init_fn enables feature developers
+ * to annotate dependency relationships to ensure subsequent init calls only
+ * run once a subordinate's dependencies have run. When needed custom
+ * dependency requirements can also be spelled out through a custom dependency
+ * checker. In order to account for the dual entry point nature of x86-64 Linux
+ * for "paravirtualization yielding" and to make annotations for support for
+ * these explicit each struct x86_init_fn must specify supported
+ * subarchitectures. The earliest x86-64 code can read the subarchitecture
+ * though is after load_idt(), as such the earliest we can currently rely on
+ * subarchitecture for semantics and a common init sequences is on the shared
+ * common x86_64_start_reservations().  Each struct x86_init_fn is associated
+ * with a specific special link order number which has been careflly thought
+ * out by x86 maintainers. You should pick a link order level associated with
+ * the specific directory your code lies in, a respective macro is used to
+ * build association to a link oder with a routine, you should use one of the
+ * provided x86_init_*() macros. You should not use __x86_init() directly.
+ *
+ * x86_init_fn enables strong semantics and dependencies to be defined and
+ * implemented on the full x86 initialization sequence.
+ *
+ * @supp_hardware_subarch: must be set, it represents the bitmask of supported
+ *	subarchitectures.  We require each struct x86_init_fn to have this set
+ *	to require developer considerations for each supported x86
+ *	subarchitecture and to build strong annotations of different possible
+ *	run time states particularly in consideration for the two main
+ *	different entry points for x86 Linux, to account for paravirtualization
+ *	yielding.
+ *
+ *	The subarchitecture is read by the kernel at early boot from the
+ *	struct boot_params hardware_subarch. Support for the subarchitecture
+ *	exists as of x86 boot protocol 2.07. The bootloader would have set up
+ *	the respective hardware_subarch on the boot sector as per
+ *	Documentation/x86/boot.txt.
+ *
+ *	What x86 entry point is used is determined at run time by the
+ *	bootloader. Linux pv_ops was designed to help enable to build one Linux
+ *	binary to support bare metal and different hypervisors.  pv_ops setup
+ *	code however is limited in that all pv_ops setup code is run late in
+ *	the x86 init sequence, during setup_arch(). In fact cpu_has_hypervisor
+ *	only works after early_cpu_init() during setup_arch(). If an x86
+ *	feature requires an earlier determination of what hypervisor was used,
+ *	or if it needs to annotate only support for certain hypervisors, the
+ *	x86 hardware_subarch should be set by the bootloader and
+ *	@supp_hardware_subarch set by the x86 feature. Using hardware_subarch
+ *	enables x86 features to fill the semantic gap between the Linux x86
+ *	entry point used and what pv_ops has to offer through a hypervisor
+ *	agnostic mechanism.
+ *
+ *	Each supported subarchitecture is set using the respective
+ *	X86_SUBARCH_* as a bit in the bitmask. For instance if a feature
+ *	is supported on PC and Xen subarchitectures only you would set this
+ *	bitmask to:
+ *
+ *		BIT(X86_SUBARCH_PC) |
+ *		BIT(X86_SUBARCH_XEN);
+ *
+ * @early_init: required, routine which will run in x86_64_start_reservations()
+ *	after we ensure boot_params.hdr.hardware_subarch is accessible and
+ *	properly set. Memory is not yet available. This the earliest we can
+ *	currently define a common shared callback since all callbacks need to
+ *	check for boot_params.hdr.hardware_subarch and this becomes accessible
+ *	on x86-64 until after load_idt().
+ */
+struct x86_init_fn {
+	__u32 supp_hardware_subarch;
+	void (*early_init)(void);
+};
+
+DECLARE_LINKTABLE(struct x86_init_fn, x86_init_fns);
+
+/* Init order levels, we can start at 0000 but reserve 0000-0999 for now */
+
+/*
+ * X86_INIT_ORDER_EARLY - early kernel init code
+ *
+ * This consists of the first parts of the Linux kernel executed.
+ */
+#define X86_INIT_ORDER_EARLY	1000
+
+/* X86_INIT_ORDER_PLATFORM - platform kernel code
+ *
+ * Code the kernel needs to initialize under arch/x86/platform/
+ * early in boot.
+ */
+#define X86_INIT_ORDER_PLATFORM	3000
+
+#define __x86_init(__level,						\
+		   __supp_hardware_subarch,				\
+		   __early_init)					\
+	static LINKTABLE_INIT_DATA(x86_init_fns, __level)		\
+	__x86_init_fn_##__early_init = {				\
+		.supp_hardware_subarch = __supp_hardware_subarch,	\
+		.early_init = __early_init,				\
+	};
+
+#define x86_init_early(__supp_hardware_subarch,				\
+		       __early_init)					\
+	__x86_init(X86_INIT_ORDER_EARLY, __supp_hardware_subarch,	\
+		   __early_init);
+
+#define x86_init_platform(__supp_hardware_subarch,			\
+		       __early_init)					\
+	__x86_init(__name, X86_INIT_ORDER_PLATFORM, __supp_hardware_subarch,\
+		   __early_init);
+
+#define x86_init_early_all(__early_init)				\
+	x86_init_early(X86_SUBARCH_ALL_SUBARCHS,			\
+		       __early_init);
+
+#define x86_init_early_pc(__early_init)					\
+	x86_init_early(BIT(X86_SUBARCH_PC),				\
+		       __early_init);
+
+#define x86_init_early_xen(__early_init)				\
+	x86_init_early(BIT(X86_SUBARCH_XEN),				\
+		       __early_init);
+/**
+ * x86_init_fn_early_init: call all early_init() callbacks
+ *
+ * This calls all early_init() callbacks on the x86_init_fns linker table.
+ */
+void x86_init_fn_early_init(void);
+
+#endif /* __X86_INIT_TABLES_H */
diff --git a/tools/linker-tables/arch/x86/kernel/alpha.c b/tools/linker-tables/arch/x86/kernel/alpha.c
new file mode 100644
index 000000000000..0f9d45734c33
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/alpha.c
@@ -0,0 +1,9 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_alpha(void) {
+	pr_info("Initializing alpha ...\n");
+	pr_info("Completed initializing alpha !\n");
+}
+
+x86_init_early_pc(early_init_alpha);
diff --git a/tools/linker-tables/arch/x86/kernel/alternative.c b/tools/linker-tables/arch/x86/kernel/alternative.c
new file mode 100644
index 000000000000..ea67562d36a9
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/alternative.c
@@ -0,0 +1,31 @@
+#include <asm/x86_init_fn.h>
+
+#include <linux/kernel.h>
+#include <linux/ps_const.h>
+
+void apply_alternatives_linker_tables(void)
+{
+	unsigned int num_consts = LINKTABLE_SIZE(ps_set_const_table);
+	struct ps_set_const *ps_const;
+
+	if (!num_consts)
+		return;
+
+	pr_debug("Number of init entries: %d\n", num_consts);
+
+	LINKTABLE_FOR_EACH(ps_const, ps_set_const_table) {
+		switch(ps_const->type) {
+		case SET_CONST_U8:
+			*ps_const->count = (__u8) ps_const->func();
+			break;
+		case SET_CONST_U16:
+			*ps_const->count = (__u16) ps_const->func();
+			break;
+		case SET_CONST_U32:
+			*ps_const->count = (__u16) ps_const->func();
+			break;
+		}
+	}
+}
+
+x86_init_early_pc(apply_alternatives_linker_tables);
diff --git a/tools/linker-tables/arch/x86/kernel/beta.c b/tools/linker-tables/arch/x86/kernel/beta.c
new file mode 100644
index 000000000000..2bdbf49d4731
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/beta.c
@@ -0,0 +1,9 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_beta(void) {
+	pr_info("Initializing beta ...\n");
+	pr_info("Completed initializing beta !\n");
+}
+
+x86_init_early_pc(early_init_beta);
diff --git a/tools/linker-tables/arch/x86/kernel/head64.c b/tools/linker-tables/arch/x86/kernel/head64.c
new file mode 100644
index 000000000000..d14dcdfd0ea9
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/head64.c
@@ -0,0 +1,58 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+
+#include <asm/x86_init_fn.h>
+#include <asm/boot.h>
+#include <asm/bootparam.h>
+
+#include <linux/start_kernel.h>
+#include <linux/kasan.h>
+
+void x86_64_start_reservations(void)
+{
+	switch (boot_params.hdr.hardware_subarch) {
+	case X86_SUBARCH_PC:
+		pr_info("Booting bare metal\n");
+		break;
+	case X86_SUBARCH_LGUEST:
+		pr_info("Booting lguest not supported\n");
+		BUG();
+	case X86_SUBARCH_XEN:
+		pr_info("Booting a Xen guest\n");
+		break;
+	case X86_SUBARCH_INTEL_MID:
+		pr_info("Booting Intel MID not supported\n");
+		BUG();
+	case X86_SUBARCH_CE4100:
+		pr_info("Booting Intel CE4100 not supported\n");
+		BUG();
+	default:
+		pr_info("Booting sunsupported x86 hardware subarch\n");
+		BUG();
+	}
+
+	start_kernel();
+}
+
+static void x86_64_start_kernel(void)
+{
+	x86_init_fn_early_init();
+
+	x86_64_start_reservations();
+}
+
+void startup_64(void)
+{
+	pr_info("Initializing x86 bare metal world\n");
+	x86_64_start_kernel();
+}
+
+void setup_arch(void)
+{
+	/* TODO: x86_init_fn_setup_arch(); */
+}
+
+void late_init(void)
+{
+	/* TODO: x86_init_fn_late_init(); */
+}
diff --git a/tools/linker-tables/arch/x86/kernel/init.c b/tools/linker-tables/arch/x86/kernel/init.c
new file mode 100644
index 000000000000..3de4e506425c
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/init.c
@@ -0,0 +1,42 @@
+#define pr_fmt(fmt) "x86-init: " fmt
+
+#include <linux/bug.h>
+#include <linux/kernel.h>
+
+#include <asm/x86_init_fn.h>
+#include <asm/bootparam.h>
+#include <asm/boot.h>
+#include <asm/setup.h>
+
+DEFINE_LINKTABLE_INIT_DATA(struct x86_init_fn, x86_init_fns);
+
+static bool x86_init_fn_supports_subarch(struct x86_init_fn *fn)
+{
+	if (!fn->supp_hardware_subarch) {
+		//pr_err("Init sequence fails to declares any supported subarchs: %pF\n", fn->early_init);
+		WARN_ON(1);
+	}
+	if (BIT(boot_params.hdr.hardware_subarch) & fn->supp_hardware_subarch)
+		return true;
+	return false;
+}
+
+void __ref x86_init_fn_early_init(void)
+{
+	struct x86_init_fn *init_fn;
+	unsigned int num_inits = LINKTABLE_SIZE(x86_init_fns);
+
+	if (!num_inits)
+		return;
+
+	pr_debug("Number of init entries: %d\n", num_inits);
+
+	LINKTABLE_FOR_EACH(init_fn, x86_init_fns) {
+		if (!x86_init_fn_supports_subarch(init_fn))
+			continue;
+
+		//pr_debug("Running early init %pF ...\n", init_fn->early_init);
+		init_fn->early_init();
+		//pr_debug("Completed early init %pF\n", init_fn->early_init);
+	}
+}
diff --git a/tools/linker-tables/arch/x86/kernel/kasan.c b/tools/linker-tables/arch/x86/kernel/kasan.c
new file mode 100644
index 000000000000..c0120676eb9c
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/kasan.c
@@ -0,0 +1,10 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+void kasan_early_init(void) {
+	pr_info("Initializing kasan ...\n");
+	pr_info("Early init for Kasan...\n");
+	pr_info("Completed initializing kasan !\n");
+}
+
+x86_init_early_pc(kasan_early_init);
diff --git a/tools/linker-tables/arch/x86/kernel/kprobes.c b/tools/linker-tables/arch/x86/kernel/kprobes.c
new file mode 100644
index 000000000000..c4e42beae55b
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/kprobes.c
@@ -0,0 +1,51 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <linux/ranges.h>
+#include <linux/kprobes.h>
+
+DEFINE_SECTION_RANGE(kprobes, .text);
+
+void __kprobes test_kprobe_0001(void)
+{
+	pr_info("test_kprobe\n");
+}
+
+void test_kprobe_0002(void)
+{
+	pr_info("test_kprobe\n");
+}
+
+void test_kprobe_addr(const char *test, unsigned long addr, bool should_match)
+{
+	if (SECTION_RANGE_ADDR_WITHIN(kprobes, addr))
+		if (should_match)
+			pr_info("== OK: %s within range!\n", test);
+		else
+			pr_info("== FAIL: %s should not be in range...\n",
+				test);
+	else
+		if (should_match)
+			pr_info("== FAIL: %s should be in range...\n", test);
+		else
+			pr_info("== OK: %s not in range as expected!\n", test);
+}
+
+void early_init_kprobes(void)
+{
+	unsigned long addr;
+
+	pr_info("Initializing kprobes ...\n");
+
+	addr = (unsigned long) &test_kprobe_0001;
+
+	test_kprobe_addr("test_kprobe_0001", addr, true);
+
+	addr = (unsigned long) &test_kprobe_0002;
+
+	test_kprobe_addr("test_kprobe_0002", addr, false);
+
+	pr_info("Completed initializing kprobes !\n");
+}
+
+x86_init_early_all(early_init_kprobes);
diff --git a/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S b/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
new file mode 100644
index 000000000000..783735fb897a
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
@@ -0,0 +1,277 @@
+/* Script for -z combreloc: combine and sort reloc sections */
+/* Copyright (C) 2014 Free Software Foundation, Inc.
+   Copying and distribution of this script, with or without modification,
+   are permitted in any medium without royalty provided the copyright
+   notice and this notice are preserved.  */
+
+#include <asm/section-core.h>
+#include <asm/ranges.h>
+#include <asm/tables.h>
+
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
+	      "elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(_start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
+  .interp         : { *(.interp) }
+  .note.gnu.build-id : { *(.note.gnu.build-id) }
+  .hash           : { *(.hash) }
+  .gnu.hash       : { *(.gnu.hash) }
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+  .rela.dyn       :
+    {
+      *(.rela.init)
+      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+      *(.rela.fini)
+      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+      *(.rela.ctors)
+      *(.rela.dtors)
+      *(.rela.got)
+      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+      *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
+      *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
+      *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
+      *(.rela.ifunc)
+    }
+  .rela.plt       :
+    {
+      *(.rela.plt)
+      PROVIDE_HIDDEN (__rela_iplt_start = .);
+      *(.rela.iplt)
+      PROVIDE_HIDDEN (__rela_iplt_end = .);
+    }
+  .init           :
+  {
+    KEEP (*(SORT_NONE(.init)))
+  }
+  .plt            : { *(.plt) *(.iplt) }
+  .plt.bnd        : { *(.plt.bnd) }
+  .text           :
+  {
+    *(.text.unlikely .text.*_unlikely .text.unlikely.*)
+    *(.text.exit .text.exit.*)
+    *(.text.startup .text.startup.*)
+    *(.text.hot .text.hot.*)
+
+    *(SORT(.text..rng.*))
+    *(SORT(.text..tbl.*))
+
+    *(SORT(.init.text..rng.*))
+    *(SORT(.init.text..tbl.*))
+
+    *(SORT(.initcall..rng.*))
+    *(SORT(.initcall..tbl.*))
+
+    *(SORT(.exit.text..rng.*))
+    *(SORT(.exit.text..tbl.*))
+
+    *(SORT(.exitcall.exit..rng.*))
+    *(SORT(.exitcall.exit..tbl.*))
+
+    *(.text .stub .text.* .gnu.linkonce.t.*)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  }
+  .fini           :
+  {
+    KEEP (*(SORT_NONE(.fini)))
+  }
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+  .rodata         :
+  {
+	*(.rodata)
+
+	*(SORT(.rodata.*))
+
+	*(SORT(.rodata..rng.*))
+	*(SORT(.rodata..tbl.*))
+
+	*(SORT(.init.rodata..rng.*))
+	*(SORT(.init.rodata..tbl.*))
+
+	*(SORT(.ref.rodata..rng.*))
+	*(SORT(.ref.rodata..tbl.*))
+
+	*(.gnu.linkonce.r.*)
+  }
+  .rodata1        : { *(.rodata1) }
+  .eh_frame_hdr : { *(.eh_frame_hdr) }
+  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table
+  .gcc_except_table.*) }
+  /* These sections are generated by the Sun/Oracle C++ compiler.  */
+  .exception_ranges   : ONLY_IF_RO { *(.exception_ranges
+  .exception_ranges*) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  */
+  . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+  /* Exception handling  */
+  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
+  .exception_ranges   : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
+  /* Thread Local Storage sections  */
+  .tdata	  : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+  .preinit_array     :
+  {
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP (*(.preinit_array))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+  }
+  .init_array     :
+  {
+    PROVIDE_HIDDEN (__init_array_start = .);
+    KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
+    KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
+    PROVIDE_HIDDEN (__init_array_end = .);
+  }
+  .fini_array     :
+  {
+    PROVIDE_HIDDEN (__fini_array_start = .);
+    KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
+    KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
+    PROVIDE_HIDDEN (__fini_array_end = .);
+  }
+  .ctors          :
+  {
+    /* gcc uses crtbegin.o to find the start of
+       the constructors, so we make sure it is
+       first.  Because this is a wildcard, it
+       doesn't matter if the user does not
+       actually link against crtbegin.o; the
+       linker won't look for a file to match a
+       wildcard.  The wildcard also means that it
+       doesn't matter which directory crtbegin.o
+       is in.  */
+    KEEP (*crtbegin.o(.ctors))
+    KEEP (*crtbegin?.o(.ctors))
+    /* We don't want to include the .ctor section from
+       the crtend.o file until after the sorted ctors.
+       The .ctor section from the crtend file contains the
+       end of ctors marker and it must be last */
+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+  .dtors          :
+  {
+    KEEP (*crtbegin.o(.dtors))
+    KEEP (*crtbegin?.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  .jcr            : { KEEP (*(.jcr)) }
+  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
+  .dynamic        : { *(.dynamic) }
+  .got            : { *(.got) *(.igot) }
+  . = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
+  .got.plt        : { *(.got.plt)  *(.igot.plt) }
+  .data           :
+  {
+    *(.data .data.* .gnu.linkonce.d.*)
+
+    *(SORT(.data..rng.*))
+    *(SORT(.data..tbl.*))
+
+    *(SORT(.init.data..rng.*))
+    *(SORT(.init.data..tbl.*))
+
+    *(SORT(.ref.rodata..rng.*))
+    *(SORT(.ref.rodata..tbl.*))
+
+    *(SORT(.exit.data..rng.*))
+    *(SORT(.exit.data..tbl.*))
+
+    SORT(CONSTRUCTORS)
+  }
+  .data1          : { *(.data1) }
+  _edata = .; PROVIDE (edata = .);
+  . = .;
+
+  __bss_start = .;
+  .bss            :
+  {
+   *(.dynbss)
+   *(.bss .bss.* .gnu.linkonce.b.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.
+      FIXME: Why do we need it? When there is no .bss section, we don't
+      pad the .data section.  */
+   . = ALIGN(. != 0 ? 64 / 8 : 1);
+  }
+  .lbss   :
+  {
+    *(.dynlbss)
+    *(.lbss .lbss.* .gnu.linkonce.lb.*)
+    *(LARGE_COMMON)
+  }
+  . = ALIGN(64 / 8);
+  . = SEGMENT_START("ldata-segment", .);
+  .lrodata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+  {
+    *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
+  }
+  .ldata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+  {
+    *(.ldata .ldata.* .gnu.linkonce.l.*)
+    . = ALIGN(. != 0 ? 64 / 8 : 1);
+  }
+  . = ALIGN(64 / 8);
+  _end = .; PROVIDE (end = .);
+  . = DATA_SEGMENT_END (.);
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line .debug_line.* .debug_line_end ) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  /* DWARF 3 */
+  .debug_pubtypes 0 : { *(.debug_pubtypes) }
+  .debug_ranges   0 : { *(.debug_ranges) }
+  /* DWARF Extension.  */
+  .debug_macro    0 : { *(.debug_macro) }
+  .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
+}
diff --git a/tools/linker-tables/arch/x86/mm/init.c b/tools/linker-tables/arch/x86/mm/init.c
new file mode 100644
index 000000000000..dbf1a85a4043
--- /dev/null
+++ b/tools/linker-tables/arch/x86/mm/init.c
@@ -0,0 +1,10 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_memory(void) {
+	pr_info("Initializing memory ...\n");
+	sleep(1);
+	pr_info("Completed initializing memory !\n");
+}
+
+x86_init_early_all(early_init_memory);
diff --git a/tools/linker-tables/arch/x86/xen/init.c b/tools/linker-tables/arch/x86/xen/init.c
new file mode 100644
index 000000000000..40ad493daee8
--- /dev/null
+++ b/tools/linker-tables/arch/x86/xen/init.c
@@ -0,0 +1,13 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <asm/x86.h>
+
+void startup_xen(void)
+{
+	pr_info("Initializing Xen guest\n");
+
+	x86_init_fn_early_init();
+
+	x86_64_start_reservations();
+}
diff --git a/tools/linker-tables/drivers/acme.c b/tools/linker-tables/drivers/acme.c
new file mode 100644
index 000000000000..dd321686dd49
--- /dev/null
+++ b/tools/linker-tables/drivers/acme.c
@@ -0,0 +1,32 @@
+#define pr_fmt(fmt) "ACME: " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/workqueue.h>
+
+void *acme_todo(void *arg);
+static DECLARE_WORK(acme_work, acme_todo);
+
+void *acme_todo(void *arg)
+{
+	pr_info("Running scheduled work\n");
+	pthread_exit(NULL);
+}
+
+static int acme_init_driver(void) {
+	pr_info("Initializing ...\n");
+	sleep(2);
+	pr_info("Finished init ... !\n");
+
+	init_work(&acme_work);
+	schedule_work(&acme_work);
+
+	return 0;
+}
+module_init(acme_init_driver);
+
+static void acme_exit(void)
+{
+	cancel_work_sync(&acme_work);
+};
+module_exit(acme_exit);
diff --git a/tools/linker-tables/drivers/synth/common.c b/tools/linker-tables/drivers/synth/common.c
new file mode 100644
index 000000000000..b44d9fcc7a9b
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/common.c
@@ -0,0 +1,16 @@
+int demo_or_1(int arg)
+{
+	switch (arg) {
+	case 1:
+		return 0xDEA00000;
+	case 2:
+		return 0X000D0000;
+	default:
+		return arg * 2;
+	}
+}
+
+int demo_or_2(void)
+{
+	return 0x0000BEEF;
+}
diff --git a/tools/linker-tables/drivers/synth/common.h b/tools/linker-tables/drivers/synth/common.h
new file mode 100644
index 000000000000..92827004f532
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/common.h
@@ -0,0 +1,2 @@
+int demo_or_1(int arg);
+int demo_or_2(void);
diff --git a/tools/linker-tables/drivers/synth/main.c b/tools/linker-tables/drivers/synth/main.c
new file mode 100644
index 000000000000..555cf97a5cbb
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/main.c
@@ -0,0 +1,35 @@
+#define pr_fmt(fmt) "Synthetics: " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ps_const.h>
+
+#include "common.h"
+#include "synth.h"
+
+DEFINE_LINKTABLE_INIT_DATA(struct ps_set_const, ps_set_const_table);
+
+unsigned int get_demo_shr(void)
+{
+	return 16;
+}
+
+static int synth_init(void)
+{
+	int synth_or;
+	int val = 2;
+	const unsigned int reg =  ps_shr(0xDEADBEEF, get_demo_shr);
+
+	synth_or = synth_init_or(val);
+	pr_info("synth_init_or(%d) returns: 0x%08X\n", val, synth_or);
+
+	pr_info("ps_shr(0x%08X, get_demo_shr) returns: 0x%08X\n", 0xDEADBEEF, reg);
+
+	return 0;
+}
+module_init(synth_init);
+
+static void synth_exit(void)
+{
+}
+module_exit(synth_exit);
diff --git a/tools/linker-tables/drivers/synth/or.S b/tools/linker-tables/drivers/synth/or.S
new file mode 100644
index 000000000000..deb963fdae33
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/or.S
@@ -0,0 +1,39 @@
+#include <asm/ranges.h>
+
+	DEFINE_SECTION_RANGE(.text, synth_init_or)
+
+	push_section_rng_level(.text, synth_init_or, "01", )
+	/* err = 0; */
+	pushq %rbp
+	movq %rsp,%rbp
+	pushq %rbx
+	xorq %rbx,%rbx
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "99", )
+	/* return err; */
+	movq %rbx,%rax
+	popq %rbx
+	popq %rbp
+	retq
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "50", )
+	/* err |= demo_or_1(1); */
+	movl $1,%edi
+	call demo_or_1
+	orq %rax,%rbx
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "50", )
+	/* err |= demo_or_1(2); */
+	movl $2,%edi
+	call demo_or_1
+	orq %rax,%rbx
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "50", )
+	/* err |= demo_or_2(); */
+	call demo_or_2
+	orq %rax,%rbx
+	.popsection
diff --git a/tools/linker-tables/drivers/synth/synth.h b/tools/linker-tables/drivers/synth/synth.h
new file mode 100644
index 000000000000..abbb9afac374
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/synth.h
@@ -0,0 +1,2 @@
+/* Synthetic demos go here */
+int synth_init_or(int arg);
diff --git a/tools/linker-tables/drivers/xen-driver.c b/tools/linker-tables/drivers/xen-driver.c
new file mode 100644
index 000000000000..79d229f72818
--- /dev/null
+++ b/tools/linker-tables/drivers/xen-driver.c
@@ -0,0 +1,11 @@
+#include <asm/x86_init_fn.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <xen/xen.h>
+
+static void early_xen_init_driver(void) {
+	pr_info("Initializing xen driver\n");
+	sleep(2);
+}
+
+x86_init_early_xen(early_xen_init_driver);
diff --git a/tools/linker-tables/include/asm-generic/arch_init_fn.h b/tools/linker-tables/include/asm-generic/arch_init_fn.h
new file mode 100644
index 000000000000..61a04a50b453
--- /dev/null
+++ b/tools/linker-tables/include/asm-generic/arch_init_fn.h
@@ -0,0 +1,50 @@
+#ifndef __ARCH_INIT_TABLES_H
+#define __ARCH_INIT_TABLES_H
+
+#include <linux/types.h>
+#include <linux/tables.h>
+#include <linux/init.h>
+
+/**
+ * struct arch_init_fn - architecture-generic kernel init call
+ *
+ * Architectures must initialize a series of things prior to handing off
+ * control to the kernel. This structure can be used if the architecture is
+ * simple and it just needs a basic set of calls on its way up.
+ *
+ * @early_init: required, routine which will run in startup_64(). Memory is
+ * 	not yet available.
+ */
+struct arch_init_fn {
+	void (*early_init)(void);
+};
+
+DECLARE_LINKTABLE(struct arch_init_fn, arch_init_fns);
+
+/* Init order levels, we can start at 0000 but reserve 0000-0999 for now */
+
+/*
+ * ARCH_INIT_ORDER_EARLY - early kernel init code
+ *
+ * This consists of the first parts of the Linux kernel executed.
+ */
+#define ARCH_INIT_ORDER_EARLY	1000
+
+#define __arch_init(__level,						\
+		    __early_init)					\
+	static LINKTABLE_INIT_DATA(arch_init_fns, __level)		\
+	__arch_init_fn_##__early_init = {				\
+		.early_init = __early_init,				\
+	}
+
+#define arch_init_early(__early_init)					\
+	__arch_init(ARCH_INIT_ORDER_EARLY, __early_init)
+
+/**
+ * arch_init_fn_early_init: call all early_init() callbacks
+ *
+ * This calls all early_init() callbacks on the arch_init_fns linker table.
+ */
+void arch_init_fn_early_init(void);
+
+#endif /* __ARCH_INIT_TABLES_H */
diff --git a/tools/linker-tables/include/asm-generic/kprobes.h b/tools/linker-tables/include/asm-generic/kprobes.h
new file mode 100644
index 000000000000..839d2eb464d3
--- /dev/null
+++ b/tools/linker-tables/include/asm-generic/kprobes.h
@@ -0,0 +1,26 @@
+#ifndef _SANDBOX_ASM_GENERIC_KPROBES_H
+#define _SANDBOX_ASM_GENERIC_KPROBES_H
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#ifdef CONFIG_KPROBES
+#include <linux/tables.h>
+#include <asm/ranges.h>
+/*
+ * Blacklist ganerating macro. Specify functions which is not probed
+ * by using this macro.
+ */
+# define __NOKPROBE_SYMBOL(fname)				\
+static LINKTABLE_INIT_DATA(_kprobe_blacklist, all)		\
+	_kbl_addr_##fname = (unsigned long)fname;
+# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
+/* Use this to forbid a kprobes attach on very low level functions */
+# define __kprobes	__LINUX_RANGE(.text, kprobes)
+# define nokprobe_inline	__always_inline
+#else
+# define NOKPROBE_SYMBOL(fname)
+# define __kprobes
+# define nokprobe_inline	inline
+#endif
+#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
+
+#endif /* _SANDBOX_ASM_GENERIC_KPROBES_H */
diff --git a/tools/linker-tables/include/linux/bitops.h b/tools/linker-tables/include/linux/bitops.h
new file mode 100644
index 000000000000..2960e8089ebc
--- /dev/null
+++ b/tools/linker-tables/include/linux/bitops.h
@@ -0,0 +1,6 @@
+#ifndef _LINUX_BITOPS_H
+#define _LINUX_BITOPS_H
+
+#define BIT(nr)		(1UL << (nr))
+
+#endif /* _LINUX_BITOPS_H */
diff --git a/tools/linker-tables/include/linux/init.h b/tools/linker-tables/include/linux/init.h
new file mode 100644
index 000000000000..2691c3697f48
--- /dev/null
+++ b/tools/linker-tables/include/linux/init.h
@@ -0,0 +1,40 @@
+#ifndef _SANDBOX_LINUX_INIT_H
+#define _SANDBOX_LINUX_INIT_H
+
+#include_next <linux/init.h>
+#include <linux/types.h>
+#include <linux/sections.h>
+
+#define __init	__section(.init.text)
+#define __exit	__section(.exit.text)
+
+#ifndef __ASSEMBLY__
+#include <linux/tables.h>
+typedef int (*initcall_t)(void);
+typedef void (*exitcall_t)(void);
+
+DECLARE_LINKTABLE(initcall_t, init_calls);
+DECLARE_LINKTABLE(exitcall_t, exit_calls);
+
+#define __define_initcall(fn, id)					\
+	static LINKTABLE_INIT_DATA(init_calls, id)			\
+	__initcall_##fn##id = fn
+
+#define pure_initcall(fn)			__define_initcall(fn, 0)
+#define core_initcall(fn)			__define_initcall(fn, 1)
+#define postcore_initcall(fn)			__define_initcall(fn, 2)
+#define arch_initcall(fn)			__define_initcall(fn, 3)
+#define subsys_initcall(fn)			__define_initcall(fn, 4)
+#define fs_initcall(fn)				__define_initcall(fn, 5)
+#define device_initcall(fn)			__define_initcall(fn, 6)
+#define late_initcall(fn)			__define_initcall(fn, 7)
+
+#define __initcall(fn)				device_initcall(fn)
+
+#define __exitcall(fn)							\
+	static LINKTABLE_INIT_DATA(exit_calls, any)			\
+	__exitcall_##fn = fn;
+
+#endif
+
+#endif /* _SANDBOX_LINUX_INIT_H */
diff --git a/tools/linker-tables/include/linux/kasan.h b/tools/linker-tables/include/linux/kasan.h
new file mode 100644
index 000000000000..41791187854e
--- /dev/null
+++ b/tools/linker-tables/include/linux/kasan.h
@@ -0,0 +1,5 @@
+#include <linux/types.h>
+
+void kasan_early_init(void);
+int kasan_init(void);
+bool is_kasan_setup(void);
diff --git a/tools/linker-tables/include/linux/kernel.h b/tools/linker-tables/include/linux/kernel.h
new file mode 100644
index 000000000000..e2857c0b5b11
--- /dev/null
+++ b/tools/linker-tables/include/linux/kernel.h
@@ -0,0 +1,2 @@
+#include_next <linux/kernel.h>
+#include <linux/printk.h>
diff --git a/tools/linker-tables/include/linux/kprobes.h b/tools/linker-tables/include/linux/kprobes.h
new file mode 100644
index 000000000000..ecd5a0a69ae6
--- /dev/null
+++ b/tools/linker-tables/include/linux/kprobes.h
@@ -0,0 +1,11 @@
+#ifndef _SANDBOX_LINUX_KPROBES_H
+#define _SANDBOX_LINUX_KPROBES_H
+
+#include <asm/kprobes.h>
+#include <linux/ranges.h>
+
+#ifdef CONFIG_KPROBES
+DECLARE_SECTION_RANGE(kprobes);
+#endif
+
+#endif /* _SANDBOX_LINUX_KPROBES_H */
diff --git a/tools/linker-tables/include/linux/module.h b/tools/linker-tables/include/linux/module.h
new file mode 100644
index 000000000000..b59e55f3f04e
--- /dev/null
+++ b/tools/linker-tables/include/linux/module.h
@@ -0,0 +1,14 @@
+#ifndef _LINUX_MODULE_H
+#define _LINUX_MODULE_H
+
+#include <linux/init.h>
+
+#define module_init(x)  __initcall(x);
+#define module_exit(x)  __exitcall(x);
+
+struct module {
+	int (*init)(void);
+	void (*exit)(void);
+};
+
+#endif /* _LINUX_MODULE_H */
diff --git a/tools/linker-tables/include/linux/mutex.h b/tools/linker-tables/include/linux/mutex.h
new file mode 100644
index 000000000000..a74f951ceb42
--- /dev/null
+++ b/tools/linker-tables/include/linux/mutex.h
@@ -0,0 +1,17 @@
+#ifndef __LINUX_MUTEX_H
+#define __LINUX_MUTEX_H
+
+#include <sys/types.h>
+#include <linux/sched.h>
+#include <pthread.h>
+
+struct mutex {
+	pthread_mutex_t lock;
+};
+
+void mutex_init(struct mutex *lock);
+void mutex_destroy(struct mutex *lock);
+void mutex_lock(struct mutex *lock);
+void mutex_unlock(struct mutex *lock);
+
+#endif /* __LINUX_MUTEX_H */
diff --git a/tools/linker-tables/include/linux/pci.h b/tools/linker-tables/include/linux/pci.h
new file mode 100644
index 000000000000..8518c46631f7
--- /dev/null
+++ b/tools/linker-tables/include/linux/pci.h
@@ -0,0 +1,7 @@
+#include <linux/types.h>
+
+struct pci_fixup {
+	void (*hook)(void);
+};
+
+bool detect_pci(void);
diff --git a/tools/linker-tables/include/linux/printk.h b/tools/linker-tables/include/linux/printk.h
new file mode 100644
index 000000000000..dc137d3421e8
--- /dev/null
+++ b/tools/linker-tables/include/linux/printk.h
@@ -0,0 +1,26 @@
+#ifndef _SANDBOX_KERNEL_PRINTK
+#define _SANDBOX_KERNEL_PRINTK
+
+#ifdef __KERNEL__
+
+#include <stdio.h>
+
+#ifndef pr_fmt
+#define pr_fmt(fmt)	fmt
+#endif
+
+#ifndef pr_info
+#define pr_info(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
+#ifndef pr_err
+#define pr_err(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
+#ifndef pr_debug
+#define pr_debug(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* _SANDBOX_KERNEL_PRINTK */
diff --git a/tools/linker-tables/include/linux/ps_const.h b/tools/linker-tables/include/linux/ps_const.h
new file mode 100644
index 000000000000..5eab3a124e00
--- /dev/null
+++ b/tools/linker-tables/include/linux/ps_const.h
@@ -0,0 +1,46 @@
+#ifndef __PS_CONST
+#define __PS_CONST
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/tables.h>
+
+/* Helpers for partially static settings */
+
+enum ps_static_type {
+	SET_CONST_U8 = 0,
+	SET_CONST_U16,
+	SET_CONST_U32,
+};
+
+struct ps_set_const {
+	unsigned int *count;
+	enum ps_static_type type;
+	unsigned int (*func)(void);
+};
+
+DECLARE_LINKTABLE(struct ps_set_const, ps_set_const_table);
+
+#ifdef CONFIG_HAVE_ARCH_PS_CONST
+#include <asm/ps_const.h>
+#endif
+
+/*
+ * ps_ stands for "partially static", so we "partialloy static shift right"
+ * You can optimize this for your architecture.
+ *
+ * ps_shr(unsigned int in, unsigned char (*func)(void))
+ */
+#ifndef ps_shr
+#define ps_shr(_in, _func)						\
+({									\
+	static unsigned int _count;					\
+	static LINKTABLE_INIT_DATA(ps_set_const_table, 01)		\
+		__ps_shr##__func =					\
+		{ &_count, SET_CONST_U8, (_func) };			\
+									\
+	(_in) >> _count;						\
+})
+#endif /* ps_shr */
+
+#endif /* __PS_CONST */
diff --git a/tools/linker-tables/include/linux/sched.h b/tools/linker-tables/include/linux/sched.h
new file mode 100644
index 000000000000..0fe3526e88bf
--- /dev/null
+++ b/tools/linker-tables/include/linux/sched.h
@@ -0,0 +1,9 @@
+#ifndef _LINUX_SCHED_H
+#define _LINUX_SCHED_H
+
+#include <linux/ranges.h>
+
+DECLARE_SECTION_RANGE(sched_text);
+#define __sched		__LINUX_RANGE(.text, sched_text)
+
+#endif /* _LINUX_SCHED_H */
diff --git a/tools/linker-tables/include/linux/spinlock.h b/tools/linker-tables/include/linux/spinlock.h
new file mode 100644
index 000000000000..e62bc3bc5e6a
--- /dev/null
+++ b/tools/linker-tables/include/linux/spinlock.h
@@ -0,0 +1,13 @@
+#ifndef __LINUX_SPINLOCK_H
+#define __LINUX_SPINLOCK_H
+
+#include <pthread.h>
+
+#define spinlock_t pthread_spinlock_t
+
+void spin_lock_init(spinlock_t *lock);
+void spin_lock_destroy(spinlock_t *lock);
+void spin_lock(spinlock_t *lock);
+void spin_unlock(spinlock_t *lock);
+
+#endif /* __LINUX_SPINLOCK_H */
diff --git a/tools/linker-tables/include/linux/start_kernel.h b/tools/linker-tables/include/linux/start_kernel.h
new file mode 100644
index 000000000000..5c2cb9a5cb0c
--- /dev/null
+++ b/tools/linker-tables/include/linux/start_kernel.h
@@ -0,0 +1 @@
+int start_kernel(void);
diff --git a/tools/linker-tables/include/linux/types.h b/tools/linker-tables/include/linux/types.h
new file mode 100644
index 000000000000..3fc87b2c84e2
--- /dev/null
+++ b/tools/linker-tables/include/linux/types.h
@@ -0,0 +1,13 @@
+#ifndef __LINUX_USER_TYPES_H
+#define __LINUX_USER_TYPES_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+typedef unsigned char __u8;
+typedef unsigned short __u16;
+typedef unsigned int __u32;
+
+#endif /* __LINUX_USER_TYPES_H */
diff --git a/tools/linker-tables/include/linux/workqueue.h b/tools/linker-tables/include/linux/workqueue.h
new file mode 100644
index 000000000000..69e1c6de5051
--- /dev/null
+++ b/tools/linker-tables/include/linux/workqueue.h
@@ -0,0 +1,51 @@
+#ifndef _LINUX_WORKQUEUE_H
+#define _LINUX_WORKQUEUE_H
+
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <pthread.h>
+
+struct work {
+	bool ready;
+
+	pthread_t thread;
+	struct mutex mutex;
+	pthread_cond_t cond;
+
+	void *arg;
+	void *(*work_cb)(void *arg);
+};
+
+#define DECLARE_WORK(_w, _w_cb) \
+struct work _w = { \
+	.work_cb = _w_cb, \
+	.arg = NULL, \
+};
+
+extern void *run_work(void *arg);
+
+static inline void init_work(struct work *w)
+{
+	w->ready = false;
+
+	mutex_init(&w->mutex);
+	pthread_cond_init(&w->cond, NULL);
+
+	pthread_create(&w->thread, NULL, run_work, (void *) w);
+
+	while (1) {
+		mutex_lock(&w->mutex);
+		if (w->ready) {
+			pthread_mutex_unlock(&w->mutex.lock);
+			break;
+		}
+		mutex_unlock(&w->mutex);
+	}
+}
+
+void schedule_work(struct work *w);
+void cancel_work_sync(struct work *w);
+void init_work(struct work *w);
+
+#endif /* _LINUX_WORKQUEUE_H */
diff --git a/tools/linker-tables/include/xen/xen.h b/tools/linker-tables/include/xen/xen.h
new file mode 100644
index 000000000000..782c799a0064
--- /dev/null
+++ b/tools/linker-tables/include/xen/xen.h
@@ -0,0 +1,4 @@
+#include <linux/types.h>
+
+bool booting_xen(void);
+int startup_xen(void);
diff --git a/tools/linker-tables/kernel/locking/mutex.c b/tools/linker-tables/kernel/locking/mutex.c
new file mode 100644
index 000000000000..950e4a18461e
--- /dev/null
+++ b/tools/linker-tables/kernel/locking/mutex.c
@@ -0,0 +1,28 @@
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+
+DEFINE_SECTION_RANGE(sched_text, .text);
+
+void __sched mutex_init(struct mutex *lock)
+{
+	int r;
+
+	r = pthread_mutex_init(&lock->lock, NULL);
+	if (r)
+		BUG_ON(r);
+}
+
+void __sched mutex_destroy(struct mutex *lock)
+{
+	pthread_mutex_destroy(&lock->lock);
+}
+
+void __sched mutex_lock(struct mutex *lock)
+{
+	pthread_mutex_lock(&lock->lock);
+}
+
+void __sched mutex_unlock(struct mutex *lock)
+{
+	pthread_mutex_unlock(&lock->lock);
+}
diff --git a/tools/linker-tables/kernel/locking/spinlock.c b/tools/linker-tables/kernel/locking/spinlock.c
new file mode 100644
index 000000000000..5be2bc7cdece
--- /dev/null
+++ b/tools/linker-tables/kernel/locking/spinlock.c
@@ -0,0 +1,26 @@
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+
+void spin_lock_init(spinlock_t *lock)
+{
+	int r;
+
+	r = pthread_spin_init(lock, PTHREAD_PROCESS_SHARED);
+	if (r)
+		BUG_ON(r);
+}
+
+void spin_lock_destroy(spinlock_t *lock)
+{
+	pthread_spin_destroy(lock);
+}
+
+void spin_lock(spinlock_t *lock)
+{
+	pthread_spin_lock(lock);
+}
+
+void spin_unlock(spinlock_t *lock)
+{
+	pthread_spin_unlock(lock);
+}
diff --git a/tools/linker-tables/kernel/main.c b/tools/linker-tables/kernel/main.c
new file mode 100644
index 000000000000..f3826cdb2ca8
--- /dev/null
+++ b/tools/linker-tables/kernel/main.c
@@ -0,0 +1,32 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/x86_init_fn.h>
+#include <asm/x86.h>
+
+DEFINE_LINKTABLE_INIT_DATA(initcall_t, init_calls);
+
+int do_one_initcall(initcall_t fn)
+{
+	int ret;
+
+	ret = fn();
+
+	return ret;
+}
+
+static void do_initcalls(void)
+{
+	initcall_t *fn;
+
+	 LINKTABLE_FOR_EACH(fn, init_calls)
+		 do_one_initcall(*fn);
+}
+
+void start_kernel(void)
+{
+	pr_info("Calling start_kernel()...\n");
+
+	setup_arch();
+	late_init();
+	do_initcalls();
+}
diff --git a/tools/linker-tables/kernel/workqueue.c b/tools/linker-tables/kernel/workqueue.c
new file mode 100644
index 000000000000..5ba73c7e7c8b
--- /dev/null
+++ b/tools/linker-tables/kernel/workqueue.c
@@ -0,0 +1,43 @@
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <linux/workqueue.h>
+#include <linux/kernel.h>
+
+void schedule_work(struct work *w)
+{
+	mutex_lock(&w->mutex);
+	pthread_cond_signal(&w->cond);
+	mutex_unlock(&w->mutex);
+}
+
+void cancel_work_sync(struct work *w)
+{
+	pthread_exit(NULL);
+}
+
+void *run_work(void *arg)
+{
+	struct work *w;
+	int r;
+
+	w = (struct work *) arg;
+
+	mutex_lock(&w->mutex);
+
+	while (true) {
+		if (!w->ready)
+			w->ready = true;
+		r = pthread_cond_wait(&w->cond, &w->mutex.lock);
+		if (r != 0) {
+			printf("(%s)\n", strerror(r));
+			BUG_ON(r);
+		}
+		w->work_cb(w->arg);
+	}
+
+	mutex_unlock(&w->mutex);
+
+	pthread_exit(NULL);
+}
diff --git a/tools/linker-tables/lib/string.c b/tools/linker-tables/lib/string.c
new file mode 100644
index 000000000000..95631c742f1d
--- /dev/null
+++ b/tools/linker-tables/lib/string.c
@@ -0,0 +1,26 @@
+/*
+ *  linux/lib/string.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  Licensed under GPLv2 - taken from linux-next next-20160803
+ */
+
+#include <linux/kernel.h>
+
+/**
+ * memset - Fill a region of memory with the given value
+ * @s: Pointer to the start of the area.
+ * @c: The byte to fill the area with
+ * @count: The size of the area.
+ *
+ * Do not use memset() to access IO space, use memset_io() instead.
+ */
+void *memset(void *s, int c, size_t count)
+{
+	char *xs = s;
+
+	while (count--)
+		*xs++ = c;
+	return s;
+}
diff --git a/tools/linker-tables/main.c b/tools/linker-tables/main.c
new file mode 100644
index 000000000000..c0b1f4c95112
--- /dev/null
+++ b/tools/linker-tables/main.c
@@ -0,0 +1,20 @@
+#include <linux/string.h>
+#include <xen/xen.h>
+#include <asm/x86.h>
+#include <asm/bootparam.h>
+
+struct boot_params boot_params __attribute__((aligned(16)));
+
+int main(int arg, char *argc[])
+{
+	memset(&boot_params, 0, sizeof(struct boot_params));
+
+	if (arg <= 1)
+		startup_64();
+	else {
+		boot_params.hdr.hardware_subarch = X86_SUBARCH_XEN;
+		startup_xen();
+	}
+
+	return 0;
+}
diff --git a/tools/linker-tables/pci-quirks.c b/tools/linker-tables/pci-quirks.c
new file mode 100644
index 000000000000..2cd1116dd0fc
--- /dev/null
+++ b/tools/linker-tables/pci-quirks.c
@@ -0,0 +1,13 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <linux/pci.h>
+
+DEFINE_LINKTABLE_RO(struct pci_fixup, pci_fixup_early);
+
+static void foo_fixup(void) {
+	pr_info("foo_fixup\n");
+};
+
+LINKTABLE_RO(pci_fixup_early, 50) quirk_foo = {
+	.hook = foo_fixup,
+};
diff --git a/tools/linker-tables/pci.c b/tools/linker-tables/pci.c
new file mode 100644
index 000000000000..131b98e1170e
--- /dev/null
+++ b/tools/linker-tables/pci.c
@@ -0,0 +1,29 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <asm/bootparam.h>
+#include <linux/pci.h>
+
+DECLARE_LINKTABLE(struct pci_fixup, pci_fixup_early);
+
+void early_init_pci(void) {
+
+	const struct pci_fixup *fixup;
+	unsigned int tbl_size = LINKTABLE_SIZE(pci_fixup_early);
+
+	pr_info("Initializing pci ...\n");
+
+	pr_info("PCI fixup size: %d\n", tbl_size);
+
+	sleep(1);
+	pr_info("Demo: Using LINKTABLE_FOR_EACH\n");
+	LINKTABLE_FOR_EACH(fixup, pci_fixup_early)
+		fixup->hook();
+
+	pr_info("Demo: Using LINKTABLE_RUN_ALL\n");
+	LINKTABLE_RUN_ALL(pci_fixup_early, hook,);
+
+	pr_info("Completed initializing pci !\n");
+}
+
+x86_init_early_all(early_init_pci);
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v2 6/6] tools: add userspace linker table sandbox
@ 2016-12-22  2:39         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2016-12-22  2:39 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Add a userspace sandbox to allow easy experimentation and
test extensions with linker tables, section ranges and the
new section core definitions.

The userspace sandbox tries to mimic the Linux kernel development
flow as much as possible, it however relies on and uses libc. Support
is currently only provided to x86_64.

Demo run:

cd tools/linker-tables
make clean; make;
./demo
Initializing x86 bare metal world
x86-init: Number of init entries: 8
Initializing memory ...
Completed initializing memory !
Initializing pci ...
PCI fixup size: 1
Demo: Using LINKTABLE_FOR_EACH
foo_fixup
Demo: Using LINKTABLE_RUN_ALL
foo_fixup
Completed initializing pci !
Number of init entries: 1
Initializing kprobes ...
= OK: test_kprobe_0001 within range!
= OK: test_kprobe_0002 not in range as expected!
Completed initializing kprobes !
Initializing kasan ...
Early init for Kasan...
Completed initializing kasan !
Initializing beta ...
Completed initializing beta !
Initializing alpha ...
Completed initializing alpha !
Booting bare metal
Calling start_kernel()...
ACME: Initializing ...
ACME: Finished init ... !
Synthetics: synth_init_or(2) returns: 0xDEADBEEF
Synthetics: ps_shr(0xDEADBEEF, get_demo_shr) returns: 0x0000DEAD

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clashes with compiler generated
  sections.

o moves tools/include/linux/printk.h to tools
  linker-table/include/linux/printk.h -- we cannot generalize this
  just yet, more work is needed in terms of providing a namespace for
  headers for types of ports of kernel functionality to userspace.

o Adjust code according to the latest discussions for the linker
  tables API (section name macros are now gone).

o Give CONFIG_HAVE_ARCH_PS_CONST for x86 another good 'ol college try,
  still fails, but this is just a demo anyway. We can amend and fix
  make this more optimized for x86 later. Thanks Boris!

v4: this patch is new in this series -- added to the kenrel as
    suggested by Boris, as otherwise it'd be really hard to keep
    an external userspace repository in sync.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/linker-tables.rst           |   4 +-
 MAINTAINERS                                        |   1 +
 include/linux/tables.h                             |   5 +-
 tools/Makefile                                     |   3 +-
 .../arch/x86/include/generated/asm/section-core.h  |   1 +
 tools/arch/x86/include/generated/ranges.h          |   1 +
 tools/arch/x86/include/generated/tables.h          |   1 +
 tools/include/asm-generic/ranges.h                 |  93 +++
 tools/include/asm-generic/section-core.h           | 348 +++++++++++
 tools/include/asm-generic/tables.h                 |  48 ++
 tools/include/linux/ranges.h                       | 183 ++++++
 tools/include/linux/sections.h                     |  87 +++
 tools/include/linux/string.h                       |   1 +
 tools/include/linux/tables.h                       | 684 +++++++++++++++++++++
 tools/linker-tables/.gitignore                     |   2 +
 tools/linker-tables/Makefile                       | 184 ++++++
 tools/linker-tables/README                         | 114 ++++
 tools/linker-tables/arch/x86/include/asm/asm.h     |  17 +
 tools/linker-tables/arch/x86/include/asm/boot.h    |   1 +
 .../linker-tables/arch/x86/include/asm/bootparam.h |  32 +
 tools/linker-tables/arch/x86/include/asm/kprobes.h |   7 +
 .../linker-tables/arch/x86/include/asm/ps_const.h  |  23 +
 tools/linker-tables/arch/x86/include/asm/ranges.h  |   6 +
 .../arch/x86/include/asm/section-core.h            |   1 +
 tools/linker-tables/arch/x86/include/asm/setup.h   |   6 +
 tools/linker-tables/arch/x86/include/asm/tables.h  |   6 +
 tools/linker-tables/arch/x86/include/asm/x86.h     |   4 +
 .../arch/x86/include/asm/x86_init_fn.h             | 169 +++++
 tools/linker-tables/arch/x86/kernel/alpha.c        |   9 +
 tools/linker-tables/arch/x86/kernel/alternative.c  |  31 +
 tools/linker-tables/arch/x86/kernel/beta.c         |   9 +
 tools/linker-tables/arch/x86/kernel/head64.c       |  58 ++
 tools/linker-tables/arch/x86/kernel/init.c         |  42 ++
 tools/linker-tables/arch/x86/kernel/kasan.c        |  10 +
 tools/linker-tables/arch/x86/kernel/kprobes.c      |  51 ++
 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S  | 277 +++++++++
 tools/linker-tables/arch/x86/mm/init.c             |  10 +
 tools/linker-tables/arch/x86/xen/init.c            |  13 +
 tools/linker-tables/drivers/acme.c                 |  32 +
 tools/linker-tables/drivers/synth/common.c         |  16 +
 tools/linker-tables/drivers/synth/common.h         |   2 +
 tools/linker-tables/drivers/synth/main.c           |  35 ++
 tools/linker-tables/drivers/synth/or.S             |  39 ++
 tools/linker-tables/drivers/synth/synth.h          |   2 +
 tools/linker-tables/drivers/xen-driver.c           |  11 +
 .../include/asm-generic/arch_init_fn.h             |  50 ++
 tools/linker-tables/include/asm-generic/kprobes.h  |  26 +
 tools/linker-tables/include/linux/bitops.h         |   6 +
 tools/linker-tables/include/linux/init.h           |  40 ++
 tools/linker-tables/include/linux/kasan.h          |   5 +
 tools/linker-tables/include/linux/kernel.h         |   2 +
 tools/linker-tables/include/linux/kprobes.h        |  11 +
 tools/linker-tables/include/linux/module.h         |  14 +
 tools/linker-tables/include/linux/mutex.h          |  17 +
 tools/linker-tables/include/linux/pci.h            |   7 +
 tools/linker-tables/include/linux/printk.h         |  26 +
 tools/linker-tables/include/linux/ps_const.h       |  46 ++
 tools/linker-tables/include/linux/sched.h          |   9 +
 tools/linker-tables/include/linux/spinlock.h       |  13 +
 tools/linker-tables/include/linux/start_kernel.h   |   1 +
 tools/linker-tables/include/linux/types.h          |  13 +
 tools/linker-tables/include/linux/workqueue.h      |  51 ++
 tools/linker-tables/include/xen/xen.h              |   4 +
 tools/linker-tables/kernel/locking/mutex.c         |  28 +
 tools/linker-tables/kernel/locking/spinlock.c      |  26 +
 tools/linker-tables/kernel/main.c                  |  32 +
 tools/linker-tables/kernel/workqueue.c             |  43 ++
 tools/linker-tables/lib/string.c                   |  26 +
 tools/linker-tables/main.c                         |  20 +
 tools/linker-tables/pci-quirks.c                   |  13 +
 tools/linker-tables/pci.c                          |  29 +
 71 files changed, 3232 insertions(+), 5 deletions(-)
 create mode 100644 tools/arch/x86/include/generated/asm/section-core.h
 create mode 100644 tools/arch/x86/include/generated/ranges.h
 create mode 100644 tools/arch/x86/include/generated/tables.h
 create mode 100644 tools/include/asm-generic/ranges.h
 create mode 100644 tools/include/asm-generic/section-core.h
 create mode 100644 tools/include/asm-generic/tables.h
 create mode 100644 tools/include/linux/ranges.h
 create mode 100644 tools/include/linux/sections.h
 create mode 100644 tools/include/linux/tables.h
 create mode 100644 tools/linker-tables/.gitignore
 create mode 100644 tools/linker-tables/Makefile
 create mode 100644 tools/linker-tables/README
 create mode 100644 tools/linker-tables/arch/x86/include/asm/asm.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/boot.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/bootparam.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/kprobes.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ps_const.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ranges.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/section-core.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/setup.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/tables.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
 create mode 100644 tools/linker-tables/arch/x86/kernel/alpha.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/alternative.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/beta.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/head64.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/init.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kasan.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kprobes.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
 create mode 100644 tools/linker-tables/arch/x86/mm/init.c
 create mode 100644 tools/linker-tables/arch/x86/xen/init.c
 create mode 100644 tools/linker-tables/drivers/acme.c
 create mode 100644 tools/linker-tables/drivers/synth/common.c
 create mode 100644 tools/linker-tables/drivers/synth/common.h
 create mode 100644 tools/linker-tables/drivers/synth/main.c
 create mode 100644 tools/linker-tables/drivers/synth/or.S
 create mode 100644 tools/linker-tables/drivers/synth/synth.h
 create mode 100644 tools/linker-tables/drivers/xen-driver.c
 create mode 100644 tools/linker-tables/include/asm-generic/arch_init_fn.h
 create mode 100644 tools/linker-tables/include/asm-generic/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/bitops.h
 create mode 100644 tools/linker-tables/include/linux/init.h
 create mode 100644 tools/linker-tables/include/linux/kasan.h
 create mode 100644 tools/linker-tables/include/linux/kernel.h
 create mode 100644 tools/linker-tables/include/linux/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/module.h
 create mode 100644 tools/linker-tables/include/linux/mutex.h
 create mode 100644 tools/linker-tables/include/linux/pci.h
 create mode 100644 tools/linker-tables/include/linux/printk.h
 create mode 100644 tools/linker-tables/include/linux/ps_const.h
 create mode 100644 tools/linker-tables/include/linux/sched.h
 create mode 100644 tools/linker-tables/include/linux/spinlock.h
 create mode 100644 tools/linker-tables/include/linux/start_kernel.h
 create mode 100644 tools/linker-tables/include/linux/types.h
 create mode 100644 tools/linker-tables/include/linux/workqueue.h
 create mode 100644 tools/linker-tables/include/xen/xen.h
 create mode 100644 tools/linker-tables/kernel/locking/mutex.c
 create mode 100644 tools/linker-tables/kernel/locking/spinlock.c
 create mode 100644 tools/linker-tables/kernel/main.c
 create mode 100644 tools/linker-tables/kernel/workqueue.c
 create mode 100644 tools/linker-tables/lib/string.c
 create mode 100644 tools/linker-tables/main.c
 create mode 100644 tools/linker-tables/pci-quirks.c
 create mode 100644 tools/linker-tables/pci.c

diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index a80f4dd94659..82a71cfe8e59 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -11,11 +11,11 @@ About Linker tables
 .. kernel-doc:: include/linux/tables.h
    :doc: Introduction
 
-Linker table provenance
+Linker table provenance and userspace testing
 ---------------------------------------------
 
 .. kernel-doc:: include/linux/tables.h
-   :doc: Linker table provenance
+   :doc: Linker table provenance and userspace testing
 
 Benefits of using Linker tables
 ===============diff --git a/MAINTAINERS b/MAINTAINERS
index c57ba50e2348..2670d55135ed 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5413,6 +5413,7 @@ L:	linux-kernel@vger.kernel.org
 S:	Supported
 F:	include/asm-generic/tables.h
 F:	include/linux/tables.h
+F:	tools/linker-tables/
 F:	Documentation/sections/linker-tables.rst
 
 GENERIC PHY FRAMEWORK
diff --git a/include/linux/tables.h b/include/linux/tables.h
index fdadf794b63e..a1fbbd20fd13 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -35,12 +35,13 @@
  */
 
 /**
- * DOC: Linker table provenance
+ * DOC: Linker table provenance and userspace testing
  *
  * 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].
+ * userspace linker-table tree [1]. Linux has a similar userspace application
+ * in tools/linker-tables/ to help more easily test adding new extensions.
  *
  * Contrary to iPXE's solution which strives to force compilation of
  * everything using linker tables, Linux's solution allows for developers to be
diff --git a/tools/Makefile b/tools/Makefile
index 00caacd3ed92..ecb2e651c930 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -19,6 +19,7 @@ help:
 	@echo '  kvm_stat               - top-like utility for displaying kvm statistics'
 	@echo '  leds                   - LEDs  tools'
 	@echo '  lguest                 - a minimal 32-bit x86 hypervisor'
+	@echo '  linker-tables		- userspace liker table sandbox and related tools'
 	@echo '  net                    - misc networking tools'
 	@echo '  perf                   - Linux performance measurement and analysis tool'
 	@echo '  selftests              - various kernel selftests'
@@ -86,7 +87,7 @@ tmon: FORCE
 freefall: FORCE
 	$(call descend,laptop/$@)
 
-all: acpi cgroup cpupower gpio hv firewire lguest \
+all: acpi cgroup cpupower gpio hv firewire lguest linker-tables \
 		perf selftests turbostat usb \
 		virtio vm net x86_energy_perf_policy \
 		tmon freefall objtool
diff --git a/tools/arch/x86/include/generated/asm/section-core.h b/tools/arch/x86/include/generated/asm/section-core.h
new file mode 100644
index 000000000000..06be2b1c424f
--- /dev/null
+++ b/tools/arch/x86/include/generated/asm/section-core.h
@@ -0,0 +1 @@
+#include <asm-generic/section-core.h>
diff --git a/tools/arch/x86/include/generated/ranges.h b/tools/arch/x86/include/generated/ranges.h
new file mode 100644
index 000000000000..dac1a9a11367
--- /dev/null
+++ b/tools/arch/x86/include/generated/ranges.h
@@ -0,0 +1 @@
+#include <asm-generic/ranges.h>
diff --git a/tools/arch/x86/include/generated/tables.h b/tools/arch/x86/include/generated/tables.h
new file mode 100644
index 000000000000..d437818275c5
--- /dev/null
+++ b/tools/arch/x86/include/generated/tables.h
@@ -0,0 +1 @@
+#include <asm-generic/tables.h>
diff --git a/tools/include/asm-generic/ranges.h b/tools/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..75c196864f45
--- /dev/null
+++ b/tools/include/asm-generic/ranges.h
@@ -0,0 +1,93 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  any, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       any, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   any, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(#section "..rng.name.any")))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using
+ * 	binutils SORT(), the number is sorted as a string, as such be
+ * 	sure to fill with zeroes any empty digits. For instance if you are
+ * 	using 3 levels of digits for order levels, use 001 for the first entry,
+ * 	0002 for the second, 999 for the last entry. You can use however many
+ * 	digits you need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(#section "..rng.name." #level)))
+
+#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/tools/include/asm-generic/section-core.h b/tools/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..65fb076765f8
--- /dev/null
+++ b/tools/include/asm-generic/section-core.h
@@ -0,0 +1,348 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Linux ELF program specific sections
+ *
+ * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and
+ * definition of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
+ * sections. This chaper is dedicated to documenting Linux program specific
+ * sections and helpers available to make use of these easier to implement and
+ * use.
+ *
+ * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
+ */
+
+/**
+ * DOC: Linux linker script
+ *
+ * Linux uses a custom linker script to build the vmlinux binary, it uses it to
+ * strategically place and define Linux ELF sections.  Each architecture needs
+ * to implement its own linker script, it is expected to reside in
+ * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
+ * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
+ * as well as some helpers documented in this chapter.
+ *
+ * In assembly it is common practice to use dots (``.``) in labels to avoid
+ * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
+ * name but not a C symbol. Historically then, two dots are used (``..``)
+ * have been used in linker scripts when adding program specific sections
+ * when there are concerns to avoid clashes with compiler generated sections.
+ */
+
+/**
+ * DOC: Memory protection
+ *
+ * Linux allows architectures which support memory protection features to
+ * take advantage of them by letting architectures define and enable
+ * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.
+ * mark_rodata_ro() can be used for instance to mark specific sections as
+ * read-only or non-executable.
+ *
+ * Linux typically follows a convention to have the .rodata ELF section follow
+ * after the .text ELF section, it does this to help architectures which
+ * support memory protection to mark both .text and .rodata as read-only in
+ * one shot.
+ *
+ * For more details refer to mark_rodata_ro().
+ */
+
+/**
+ * DOC: .rodata
+ *
+ * ELF section used for data which must be protected from write access.
+ */
+
+/**
+ * DOC: .text
+ *
+ * ELF section name used for code (functions) used during regular
+ * kernel run time.
+ */
+
+/**
+ * DOC: .data
+ *
+ * ELF section used for read-write data.
+ */
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: .init.text
+ *
+ * ELF section for code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+
+/**
+ * DOC: .init.data
+ *
+ * ELF section used for data structures used only during boot or driver
+ * initialization.
+ */
+
+/**
+ * DOC: .init.rodata
+ *
+ * ELF section used for read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+
+/**
+ * DOC: .initcall
+ *
+ * ELF section used for subsystem init calls. There are init levels
+ * representing different functionality in the kernel. For more details
+ * refer to __define_initcall().
+ */
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: .exit.text
+ *
+ * ELF section used to for code (functions) used only during module unload.
+ */
+
+/**
+ * DOC: .exit.data
+ *
+ * ELF section used to for data structures used only during module
+ * unload.
+ */
+
+/**
+ * DOC: .exitcall.exit
+ *
+ * ELF section used for exit routines, order is important and maintained by
+ * link order.
+ */
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: .ref.text
+ *
+ * ELF section used to annotate code (functions) which has been vetteed as
+ * valid for its reference or use of other code (functions) or data structures
+ * which are part of the init sections.
+ */
+
+/**
+ * DOC: .ref.data
+ *
+ * ELF section used for data structures which have been vetteed for its
+ * reference or use of other code (functions) or data structures part of the
+ * init sections.
+ */
+
+/**
+ * DOC: .ref.rodata
+ *
+ * ELF section used to annotate const code (functions) const data structures
+ * which has been vetteed for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections alpha numerically. Linux has historically used 'SORT()' in
+ * ``include/asm-generic/vmlinux.lds.h``, its a well established practice. If
+ * 'SORT()' is used on a section one can provide ordering using a postfix on
+ * each section entry added. For instance if a linker script uses::
+ *
+ *    SORT(.foo.*)
+ *
+ * one can then add entries with explicit ordering using numeric postfixes for
+ * each entry, we refer to these as 'order levels'. Since 'SORT()' sorts alpha
+ * numerically a specific series set of digits must be agreed a-priori which
+ * would give also an idea of the max expected number of entries added to a
+ * section. For instance, if you expect a maximum of 999 entries you can use
+ * 3 digits for a section order level. If you wanted an entry to be ordered
+ * first you could use the postfix '000', if you wanted an entry to follow this
+ * you could use '001', and so on. We could for instance have::
+ *
+ *    .foo.000
+ *    .foo.001
+ *    .foo.002
+ *
+ * Often times one may want the option to specify no order is required for
+ * certain elements added to a section which does use 'SORT()' on the linker
+ * script. You can use any arbitrary string value to to specify no order is
+ * used, so long as its used consistantly. For instance, one possibility is to
+ * use the 'any' postfix.  All entries on the section would then have no
+ * specific ordering::
+ *
+ *    .foo.any
+ *    .foo.any
+ *    .foo.any
+ *
+ * To help establish a convention we reserve the special name 'any' for this
+ * purpose. Developers can use and expect the 'any' postfix string on sections
+ * as a helper to annotate section ordering at link time is not relevant
+ * for entries on a section.
+ */
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section..___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section..__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifndef LINKER_SCRIPT
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align\x16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/tools/include/asm-generic/tables.h b/tools/include/asm-generic/tables.h
new file mode 100644
index 000000000000..16ef40d145fb
--- /dev/null
+++ b/tools/include/asm-generic/tables.h
@@ -0,0 +1,48 @@
+#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..tbl.name.level
+
+/* Some toolchains are buggy, let them override */
+#ifndef SECTION_TBL_RO
+# define SECTION_TBL_RO	.rodata
+#endif
+
+#define SECTION_TBL_RO_STR __stringify(SECTION_TBL_RO)
+
+#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, 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, any, flags)
+#endif
+
+#endif /* _ASM_GENERIC_TABLES_H_ */
diff --git a/tools/include/linux/ranges.h b/tools/include/linux/ranges.h
new file mode 100644
index 000000000000..1e64674f6d7d
--- /dev/null
+++ b/tools/include/linux/ranges.h
@@ -0,0 +1,183 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * SECTION_RANGE_START - get address of start of section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the start address of the section range.
+ * This should give you the address of the first entry.
+ *
+ */
+#define SECTION_RANGE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * SECTION_RANGE_END - get address of end of the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define SECTION_RANGE_END(name)		LINUX_SECTION_END(name)
+
+/**
+ * SECTION_RANGE_SIZE - get number of entries in the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the number of entries in the section range.
+ * Example usage:
+ *
+ *   unsigned int num_ents = LINKTABLE_SIZE(some_fns);
+ */
+#define SECTION_RANGE_SIZE(name)					\
+	((SECTION_RANGE_END(name)) - (SECTION_RANGE_START(name)))
+
+/**
+ * SECTION_RANGE_EMPTY - check if section range has no entries
+ *
+ * @name: name of the section range
+ *
+ * Returns true if the section range is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(some_fns);
+ */
+#define SECTION_RANGE_EMPTY(name)	(SECTION_RANGE_SIZE(name) = 0)
+
+/**
+ * SECTION_RANGE_ADDR_WITHIN - returns true if address is in the section range
+ *
+ * @name: name of the section range
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_RANGE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) SECTION_RANGE_START(name) &&		\
+          addr < (unsigned long) SECTION_RANGE_END(name))
+
+/**
+ * SECTION_RANGE_ALIGNMENT - get the alignment of the section range
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the section range.
+ */
+#define SECTION_RANGE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.")))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.~")))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) SECTION_RANGE_START(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) SECTION_RANGE_END(name)[0] = {}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
diff --git a/tools/include/linux/sections.h b/tools/include/linux/sections.h
new file mode 100644
index 000000000000..6771c727bcd1
--- /dev/null
+++ b/tools/include/linux/sections.h
@@ -0,0 +1,87 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_CORE(section, core, name, level)			\
+	#section ".." #core "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
diff --git a/tools/include/linux/string.h b/tools/include/linux/string.h
index f436d2420a18..a6b12564bbd9 100644
--- a/tools/include/linux/string.h
+++ b/tools/include/linux/string.h
@@ -3,6 +3,7 @@
 
 
 #include <linux/types.h>	/* for size_t */
+#include <string.h>
 
 void *memdup(const void *src, size_t len);
 
diff --git a/tools/include/linux/tables.h b/tools/include/linux/tables.h
new file mode 100644
index 000000000000..a1fbbd20fd13
--- /dev/null
+++ b/tools/include/linux/tables.h
@@ -0,0 +1,684 @@
+#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 and userspace testing
+ *
+ * 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]. Linux has a similar userspace application
+ * in tools/linker-tables/ to help more easily test adding new extensions.
+ *
+ * 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(.foo..tbl.*))
+ *
+ * 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: The code bit-rot problem
+ *
+ * Linux provides a rich array of features, enabling each feature
+ * however increases the size of the kernel and there are many
+ * features which users often want disabled. The traditional
+ * solution to this problem is for each feature to have its own
+ * Kconfig symbol, followed by a series of #ifdef statements
+ * in C code and header files, allowing the feature to be compiled
+ * only when desirable. As the variability of Linux increases build
+ * tests can and are often done with random kernel configurations,
+ * allyesconfig, and allmodconfig to help find code issues. This
+ * however doesn't catch all errors and as a consequence code that
+ * is typically not enabled often can suffer from bit-rot over time.
+ */
+
+/**
+ * DOC: The build-all selective-link philosophy
+ *
+ * A code architecture philosophy to help avoid code bit-rot consists
+ * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
+ * by instead having each feature implemented it its own C file, and force
+ * compilation for all features. Only features that are enabled get linked in,
+ * the forced compilation therefore has no size impact on the final result of
+ * the kernel. The practice of having each feature implemented in its own C
+ * file is already prevalent in many subsystems, however #ifdefs are still
+ * typically required during feature initialization. For instance in::
+ *
+ *	#ifdef CONFIG_FOO
+ *	foo_init();
+ *	#endif
+ *
+ * We cannot remove the #ifdef and leave foo_init() as we'd either
+ * need to always enable the feature or add a respective #ifdef in a
+ * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem with linker tables
+ *
+ * Linker tables can be used to further help avoid the code bit-rot problem
+ * when embracing the 'build-all selective-link philosophy' by lifting the
+ * requirement to use of #ifdefs during initialization. With linker tables
+ * initialization sequences can be aggregated into a custom ELF section at
+ * link time, during run time the table can be iterated over and each init
+ * sequence enabled can be called. A feature's init routine is only added to a
+ * table when its respective Kconfig symbols has been enabled and therefore
+ * linked in. Linker tables enable subsystems to completely do away with
+ * #ifdefs if one is comfortable in accepting all subsystem's feature's
+ * structural size implications.
+ *
+ * To further help with this the Linux build system supports two special
+ * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
+ * follow the 'build-all selective-link philosophy' can use these targets for a
+ * feature's kconfig symbol. Using these targets will always require
+ * compilation of the kconfig's objects if the kconfig symbol's dependencies
+ * are met but only link the objects into the kernel, and therefore enable the
+ * feature, if and only if the kconfig symbol has been enabled.
+ *
+ * Not all users or build systems may want to opt-in to compile all objects
+ * following the 'build-all selective-link philosophy', as such the targets
+ * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
+ * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
+ * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
+ * ``obj-y`` and ``lib-y`` respectively.
+ *
+ * Example use::
+ *
+ * 	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+ */
+
+/**
+ * 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_START - get address of start of linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the start address of the linker table.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINKTABLE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * LINKTABLE_END - get address of end of the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define LINKTABLE_END(name)	LINUX_SECTION_END(name)
+
+/**
+ * LINKTABLE_SIZE - get number of entries in the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the number of entries in the linker table.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINKTABLE_SIZE(frobnicator_fns);
+ */
+#define LINKTABLE_SIZE(name)					\
+	((LINKTABLE_END(name)) - (LINKTABLE_START(name)))
+
+/**
+ * LINKTABLE_EMPTY - check if linker table has no entries
+ *
+ * @name: name of linker table
+ *
+ * Returns true if the linker table is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(frobnicator_fns);
+ */
+#define LINKTABLE_EMPTY(name)	(LINKTABLE_SIZE(name) = 0)
+
+/**
+ * LINKTABLE_ADDR_WITHIN - returns true if address is in the linker table
+ *
+ * @name: name of the linker table
+ * @addr: address to query for
+ *
+ * Returns true if the address is part of the linker table.
+ */
+#define LINKTABLE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) LINKTABLE_START(name) &&		\
+          addr < (unsigned long) LINKTABLE_END(name))
+
+/**
+ * LINKTABLE_ALIGNMENT - get the alignment of the linker table
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the linker table.
+ */
+#define LINKTABLE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * 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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_TEXT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE_RO(name, ~) LINKTABLE_END(name)[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_RO(type, name);				\
+	LINKTABLE_INIT_WEAK(name,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT_DATA(name, ~) LINKTABLE_END(name)[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 = LINKTABLE_START(tbl);				\
+	     pointer < LINKTABLE_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 < LINKTABLE_SIZE(tbl); i++)			\
+		(LINKTABLE_START(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 < LINKTABLE_SIZE(tbl); i++)		\
+		err = (LINKTABLE_START(tbl)[i]).func (args);		\
+		err;							\
+})
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_LINKER_TABLES_H */
diff --git a/tools/linker-tables/.gitignore b/tools/linker-tables/.gitignore
new file mode 100644
index 000000000000..8275b0c55385
--- /dev/null
+++ b/tools/linker-tables/.gitignore
@@ -0,0 +1,2 @@
+arch/x86/kernel/vmlinux.lds
+demo
diff --git a/tools/linker-tables/Makefile b/tools/linker-tables/Makefile
new file mode 100644
index 000000000000..9d4e6fb0d176
--- /dev/null
+++ b/tools/linker-tables/Makefile
@@ -0,0 +1,184 @@
+include ../scripts/Makefile.include
+
+all:
+
+include ../scripts/utilities.mak
+
+MAKEFLAGS += --no-print-directory
+
+unexport LC_ALL
+LC_COLLATE=C
+LC_NUMERIC=C
+export LC_COLLATE LC_NUMERIC
+
+ifeq ($(srctree),)
+	srctree := $(patsubst %/,%,$(dir $(shell pwd)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Determined 'srctree' to be $(srctree))
+endif
+
+ifneq ($(objtree),)
+#$(info Determined 'objtree' to be $(objtree))
+endif
+
+ifneq ($(OUTPUT),)
+#$(info Determined 'OUTPUT' to be $(OUTPUT))
+# Adding $(OUTPUT) as a directory to look for source files,
+# because use generated output files as sources dependency
+# for flex/bison parsers.
+VPATH += $(OUTPUT)
+export VPATH
+endif
+
+export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK
+include $(srctree)/tools/build/Makefile.include
+
+ifeq ($(V),1)
+	Q+	NQ=@true
+else
+	Q=@
+	NQ=@echo
+endif
+
+MAKEFLAGS += -r
+
+define allow-override
+  $(if $(or $(findstring environment,$(origin $(1))),\
+            $(findstring command line,$(origin $(1)))),,\
+    $(eval $(1) = $(2)))
+endef
+
+# Allow setting CC and AR and LD, or setting CROSS_COMPILE as a prefix.
+$(call allow-override,CC,$(CROSS_COMPILE)gcc)
+$(call allow-override,AR,$(CROSS_COMPILE)ar)
+$(call allow-override,LD,$(CROSS_COMPILE)ld)
+
+LD += $(EXTRA_LDFLAGS)
+
+include $(srctree)/tools/scripts/Makefile.arch
+
+# Refer to README to learn how to support your architecture
+SUPPORTED_ARCHS = x86
+
+ifeq ($(filter $(ARCH),$(SUPPORTED_ARCHS)),)
+$(error Unsupported arch: $(ARCH))
+endif
+
+CFLAGS += -O2 -g
+CFLAGS += -std=gnu99 -Wall -Werror
+CFLAGS += -lpthread
+CFLAGS += -DCONFIG_KPROBES
+
+# We confine the includes used below to those we know are safe
+# for this type of hack.
+CFLAGS += -D__KERNEL__
+
+# CFLAGS += -DCONFIG_HAVE_ARCH_PS_CONST
+INCLUDES = \
+	   -I include/ \
+	   -I arch/$(ARCH)/include/ \
+	   -I ../include/ \
+	   -I ../arch/$(ARCH)/include/ \
+	   -I ../arch/$(ARCH)/include/generated/
+
+CFLAGS += $(INCLUDES)
+CFLAGS +=-Wl,-Tarch/$(ARCH)/kernel/vmlinux.lds
+
+HEADERS = \
+	  ../../include/asm-generic/section-core.h \
+	  ../../include/asm-generic/ranges.h \
+	  ../../include/asm-generic/tables.h \
+	  ../../include/linux/sections.h \
+	  ../../include/linux/ranges.h \
+	  ../../include/linux/tables.h
+
+__check_headers: $(HEADERS)
+	@$(foreach h, $(HEADERS), \
+		(test -f $(h) && ( \
+			(diff -B $(subst ../,../,$(h)) $(h) >/dev/null) \
+			|| echo "Warning: $(subst ../../,tools/,$(h)) differs from kernel" >&2 ) || true);)
+
+$(OUTPUT)arch/$(ARCH)/kernel/vmlinux.lds: arch/$(ARCH)/kernel/vmlinux.lds.S
+	$(NQ) '  LD  ' $@
+	$(Q)$(CC) $(CFLAGS) $(INCLUDES) -E -P \
+		-D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
+
+# Note, we use obj-y as a convenience factor, the cmd build
+# stuff doesn't allow this magic, it resolves our depds but
+# we still need to provide a series of targets for our objects.
+# We stick to the convenient shorthand we're used to in the
+# kernel. The final object resolution build stuff is handled
+# by tool_target_obj and its caller below. This also enables
+# OUTPUT=foo-path support so you can build externally.
+obj-y += \
+	arch/$(ARCH)/kernel/head64.o \
+	arch/$(ARCH)/mm/init.o \
+	kernel/locking/mutex.o \
+	kernel/locking/spinlock.o \
+	kernel/workqueue.o \
+	kernel/main.o \
+	pci.o \
+	lib/string.o \
+	pci-quirks.o \
+	drivers/acme.o \
+	drivers/synth/main.o \
+	drivers/synth/common.o \
+	drivers/synth/or.s \
+	main.o
+
+ifeq ($(ARCH),x86)
+obj-y += \
+	arch/$(ARCH)/kernel/alternative.o \
+	arch/$(ARCH)/kernel/init.o \
+	arch/$(ARCH)/kernel/kprobes.o \
+	arch/$(ARCH)/kernel/kasan.o \
+	arch/$(ARCH)/kernel/beta.o \
+	arch/$(ARCH)/kernel/alpha.o \
+	arch/$(ARCH)/xen/init.o	\
+	drivers/xen-driver.o
+endif
+
+obj-y-out = $(patsubst %,$(OUTPUT)%,$(obj-y))
+
+__build-dir = $(subst $(OUTPUT),,$(dir $1))
+build-dir   = $(if $(__build-dir),$(__build-dir),.)
+
+build := -f $(srctree)/tools/build/Makefile.build dir=$(build-dir)
+
+define tool_target_obj
+$(1): $(subst .s,.S,$(subst .o,.c,$(patsubst $(OUTPUT)%,%,$(1))))
+	$(Q)$(MAKE) $(build) obj=$(1)
+endef
+
+$(foreach tool_obj, $(obj-y-out), \
+	$(eval $(call tool_target_obj, $(tool_obj))))
+
+$(OUTPUT)demo: $(obj-y-out)
+	$(NQ) '  CC  ' $@
+	$(Q)$(CC) $(obj-y-out) -o $@ $(CPPFLAGS) $(CFLAGS)
+
+CHECK_HEADERS := __check_headers
+PHONY += $(CHECK_HEADERS)
+
+CMD_TARGETS = $(OUTPUT)arch/$(ARCH)/kernel/vmlinux.lds $(OUTPUT)demo
+TARGETS = $(CMD_TARGETS)
+
+all: $(CHECK_HEADERS) all_cmd
+
+all_cmd: $(CMD_TARGETS)
+
+ifeq ($(OUTPUT),)
+clean_dir = ./
+else
+clean_dir = $(OUTPUT)
+endif
+
+clean::
+	$(NQ)  '  CLEAN deps'
+	$(Q)find $(clean_dir) -name \*.o \
+		-o -name \*.s \
+		-o -name \*.o.d \
+		-o -name \*.o.cmd | xargs rm -f
+	$(NQ)  '  CLEAN targets'
+	$(Q)$(foreach f, $(CMD_TARGETS), rm -f $(f);)
diff --git a/tools/linker-tables/README b/tools/linker-tables/README
new file mode 100644
index 000000000000..729241f9e4c4
--- /dev/null
+++ b/tools/linker-tables/README
@@ -0,0 +1,114 @@
+Linux linker table userspace sandbox
+==================
+
+This is a userspace sandbox to allow easy experimentation and
+test extensions with linker tables. It tries to mimic the Linux
+kernel development flow as much as possible, it however relies
+on and uses libc and is nothing but a simple stupid userspace
+application demo.
+
+You can use the sandbox to modify the kernel's linker table
+solution or add use it in creative ways without having to run
+qemu with a real kernel or user mode linux. You can simply try
+to extend this sandbox as you would for a regular userspace
+application.
+
+History
+===+
+This was hacked on first in an external repository, that tree has
+the full set of history of how this work came about. Refer to that
+tree for more details if you are interested in the logic used for
+a lot of decisions made for linker tables:
+
+https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linker-tables.git/
+
+This tree is discontinued now in favor of an upstream solution which
+is kept in sync with the kernel.
+
+Compile
+===+
+Run:
+	make
+
+Clean:
+	make clean
+
+If you need to get object files outside of the source tree:
+
+	make OUTPUT=/tmp/path/
+	make OUTPUT=/tmp/path/ clean
+
+Supported architectures
+===========+
+x86_64
+
+Currently only x86_64 is supported for the demo. It should be
+relatively easy to add more. To add a new architecture you need
+a toolchain available with libc. You then need to generate a
+respective base template custom linker script for userspace
+as is provided on x86 in arch/x86/kernel/vmlinux.lds.S.
+
+A respective architecture tools/arch/$(ARCH)/include/* file for
+each section-core.h, ranges.h, tables.h will need to be provided
+as well. If your architecture's file is generated copy the generated
+file over.
+
+x86 Simulated boots
+=========+
+This programs simulates boot on both bare metal and with the
+Xen PV entry on x86.
+
+Emulate bare metal boot:
+
+./demo
+
+Emulate Xen boot (x86):
+
+./demo -x
+
+Testing new features
+==========
+
+A copy of each kernel header file is maintained in tools/include/,
+as well as a respective generated asm file for each sandbox supported
+architecture. This sandbox has a built in checker for when these files
+get out of sync.
+
+If testing new extensions on the files:
+
+  o section-core
+  o ranges.h
+  o tables.h
+
+You'll want to copy them into tools as well. If you are working on
+using these files you can work within the current directory's namespace,
+including its own set of header files, so tools/linker-tables/include/ and
+each respective tools/linker-tables/arch/$(ARCH)/include/asm/.
+
+Features evaluation
+=========+
+This lists features currently being evaluated in the sandbox, not yet
+present upstream. These make use of the existing set of header files
+without modification.
+
+ o Demo use of initialization on for x86, refer to arch/x86/kernel/init.c
+
+ o Demo use of porting the kernel's init call levels to linker tables, refer
+   to the init_calls linker table use on kernel/main.c
+
+ o Demo use of an asm-generic architecture init family, which could potentially
+   be used to help share initialization sequences on simple architectures.
+   Refer to include/asm-generic/arch_init_fn.h
+
+ o Building synthetic routines with the option to provide enhancements
+   per architecture in asm, refer to drivers/synth/or.S and its use on
+   synth_init_or().
+
+ o User of linker tables for alternatives with consts - refer to
+   use of the ps_set_const_table linker table and its use in
+   arch/x86/kernel/alternative.c
diff --git a/tools/linker-tables/arch/x86/include/asm/asm.h b/tools/linker-tables/arch/x86/include/asm/asm.h
new file mode 100644
index 000000000000..155a52920dfb
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/asm.h
@@ -0,0 +1,17 @@
+#ifndef _ASM_X86_ASM_H
+
+#ifdef __ASSEMBLY__
+# define __ASM_FORM(x)	x
+# define __ASM_FORM_RAW(x)     x
+# define __ASM_FORM_COMMA(x) x,
+#else
+# define __ASM_FORM(x)	" " #x " "
+# define __ASM_FORM_RAW(x)     #x
+# define __ASM_FORM_COMMA(x) " " #x ","
+#endif
+
+# define __ASM_SEL(a,b) __ASM_FORM(b)
+# define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(b)
+#define _ASM_PTR	__ASM_SEL(.long, .quad)
+
+#endif /* _ASM_X86_ASM_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/boot.h b/tools/linker-tables/arch/x86/include/asm/boot.h
new file mode 100644
index 000000000000..af91b94ad5a6
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/boot.h
@@ -0,0 +1 @@
+extern struct boot_params boot_params;
diff --git a/tools/linker-tables/arch/x86/include/asm/bootparam.h b/tools/linker-tables/arch/x86/include/asm/bootparam.h
new file mode 100644
index 000000000000..a7ef34216f7f
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/bootparam.h
@@ -0,0 +1,32 @@
+#ifndef __BOOTPARAM_H
+#define __BOOTPARAM_H
+
+#include <linux/types.h>
+
+struct setup_header {
+	__u32 hardware_subarch;
+} __attribute__((packed));
+
+struct boot_params {
+	struct setup_header hdr;
+} __attribute__((packed));
+
+enum {
+	X86_SUBARCH_PC = 0,
+	X86_SUBARCH_LGUEST,
+	X86_SUBARCH_XEN,
+	X86_SUBARCH_INTEL_MID,
+	X86_SUBARCH_CE4100,
+	X86_NR_SUBARCHS,
+};
+
+#define X86_SUBARCH_ALL_SUBARCHS 	\
+	(				\
+	BIT(X86_SUBARCH_PC) |		\
+	BIT(X86_SUBARCH_LGUEST) |	\
+	BIT(X86_SUBARCH_XEN) |		\
+	BIT(X86_SUBARCH_INTEL_MID) |	\
+	BIT(X86_SUBARCH_CE4100)		\
+	)
+
+#endif /* __BOOTPARAM_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/kprobes.h b/tools/linker-tables/arch/x86/include/asm/kprobes.h
new file mode 100644
index 000000000000..f702fc359efe
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/kprobes.h
@@ -0,0 +1,7 @@
+#ifndef _SANDBOX_ASM_X86_KPROBES_H
+#define _SANDBOX_ASM_X86_KPROBES_H
+
+/* This is all we need for the demo */
+#include <asm-generic/kprobes.h>
+
+#endif /* _SANDBOX_ASM_X86_KPROBES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/ps_const.h b/tools/linker-tables/arch/x86/include/asm/ps_const.h
new file mode 100644
index 000000000000..3847f03fca92
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/ps_const.h
@@ -0,0 +1,23 @@
+#ifndef __X86_PS_CONST
+#define __X86_PS_CONST
+
+#include <linux/stringify.h>
+#include <linux/tables.h>
+#include <asm/asm.h>
+
+#define ps_shr(in, _func)						\
+({									\
+	 __typeof__(in) _count;						\
+									\
+	asm volatile(							\
+		"shr %P[_in],%[_count]\n"				\
+		"1:\n"							\
+		push_section_tbl(.init.data, ps_set_const_table, 01,)	\
+		_ASM_PTR "1b-1, %P2, %P3\n"				\
+		".popsection\n"						\
+		: [_count] "=g" (_count)				\
+		: [_in] "i" (in), "i" (SET_CONST_U8), "i" (_func));	\
+	(_count);							\
+})
+
+#endif /* __X86_PS_CONST */
diff --git a/tools/linker-tables/arch/x86/include/asm/ranges.h b/tools/linker-tables/arch/x86/include/asm/ranges.h
new file mode 100644
index 000000000000..823789d2b010
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/ranges.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_RANGES_H
+#define _ASM_X86_RANGES_H
+
+#include <asm-generic/ranges.h>
+
+#endif  /* _ASM_X86_RANGES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/section-core.h b/tools/linker-tables/arch/x86/include/asm/section-core.h
new file mode 100644
index 000000000000..06be2b1c424f
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/section-core.h
@@ -0,0 +1 @@
+#include <asm-generic/section-core.h>
diff --git a/tools/linker-tables/arch/x86/include/asm/setup.h b/tools/linker-tables/arch/x86/include/asm/setup.h
new file mode 100644
index 000000000000..366c36bd2910
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/setup.h
@@ -0,0 +1,6 @@
+#ifndef __LINUX_X86_USER_SETUP_H
+#define __LINUX_X86_USER_SETUP_H
+
+/* I'm lazy */
+
+#endif /* __LINUX_X86_USER_SETUP_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/tables.h b/tools/linker-tables/arch/x86/include/asm/tables.h
new file mode 100644
index 000000000000..797df3407ee1
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/tables.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_TABLES_H
+#define _ASM_X86_TABLES_H
+
+#include <asm-generic/tables.h>
+
+#endif  /* _ASM_X86_RANGES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/x86.h b/tools/linker-tables/arch/x86/include/asm/x86.h
new file mode 100644
index 000000000000..680c1141e0de
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/x86.h
@@ -0,0 +1,4 @@
+int startup_64(void);
+int x86_64_start_reservations(void);
+void setup_arch(void);
+void late_init(void);
diff --git a/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h b/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
new file mode 100644
index 000000000000..afece8ce6dd4
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
@@ -0,0 +1,169 @@
+#ifndef __X86_INIT_TABLES_H
+#define __X86_INIT_TABLES_H
+
+#include <linux/types.h>
+#include <linux/tables.h>
+
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <asm/bootparam.h>
+
+/**
+ * struct x86_init_fn - x86 generic kernel init call
+ *
+ * Linux x86 features vary in complexity, features may require work done at
+ * different levels of the full x86 init sequence. Today there are also two
+ * different possible entry points for Linux on x86, one for bare metal, KVM
+ * and Xen HVM, and another for Xen PV guests / dom0.  Assuming a bootloader
+ * has set up 64-bit mode, roughly the x86 init sequence follows this path:
+ *
+ * Bare metal, KVM, Xen HVM                      Xen PV / dom0
+ *       startup_64()                             startup_xen()
+ *              \                                     /
+ *      x86_64_start_kernel()                 xen_start_kernel()
+ *                           \               /
+ *                      x86_64_start_reservations()
+ *                                   |
+ *                              start_kernel()
+ *                              [   ...        ]
+ *                              [ setup_arch() ]
+ *                              [   ...        ]
+ *                                  init
+ *
+ * x86_64_start_kernel() and xen_start_kernel() are the respective first C code
+ * entry starting points. The different entry points exist to enable Xen to
+ * skip a lot of hardware setup already done and managed on behalf of the
+ * hypervisor, we refer to this as "paravirtualization yielding". The different
+ * levels of init calls on the x86 init sequence exist to account for these
+ * slight differences and requirements. These different entry points also share
+ * a common entry x86 specific path, x86_64_start_reservations().
+ *
+ * A generic x86 feature can have different initialization calls, one on each
+ * of the different main x86 init sequences, but must also address both entry
+ * points in order to work properly across the board on all supported x86
+ * subarchitectures. Since x86 features can also have dependencies on other
+ * setup code or features, x86 features can at times be subordinate to other
+ * x86 features, or conditions. struct x86_init_fn enables feature developers
+ * to annotate dependency relationships to ensure subsequent init calls only
+ * run once a subordinate's dependencies have run. When needed custom
+ * dependency requirements can also be spelled out through a custom dependency
+ * checker. In order to account for the dual entry point nature of x86-64 Linux
+ * for "paravirtualization yielding" and to make annotations for support for
+ * these explicit each struct x86_init_fn must specify supported
+ * subarchitectures. The earliest x86-64 code can read the subarchitecture
+ * though is after load_idt(), as such the earliest we can currently rely on
+ * subarchitecture for semantics and a common init sequences is on the shared
+ * common x86_64_start_reservations().  Each struct x86_init_fn is associated
+ * with a specific special link order number which has been careflly thought
+ * out by x86 maintainers. You should pick a link order level associated with
+ * the specific directory your code lies in, a respective macro is used to
+ * build association to a link oder with a routine, you should use one of the
+ * provided x86_init_*() macros. You should not use __x86_init() directly.
+ *
+ * x86_init_fn enables strong semantics and dependencies to be defined and
+ * implemented on the full x86 initialization sequence.
+ *
+ * @supp_hardware_subarch: must be set, it represents the bitmask of supported
+ *	subarchitectures.  We require each struct x86_init_fn to have this set
+ *	to require developer considerations for each supported x86
+ *	subarchitecture and to build strong annotations of different possible
+ *	run time states particularly in consideration for the two main
+ *	different entry points for x86 Linux, to account for paravirtualization
+ *	yielding.
+ *
+ *	The subarchitecture is read by the kernel at early boot from the
+ *	struct boot_params hardware_subarch. Support for the subarchitecture
+ *	exists as of x86 boot protocol 2.07. The bootloader would have set up
+ *	the respective hardware_subarch on the boot sector as per
+ *	Documentation/x86/boot.txt.
+ *
+ *	What x86 entry point is used is determined at run time by the
+ *	bootloader. Linux pv_ops was designed to help enable to build one Linux
+ *	binary to support bare metal and different hypervisors.  pv_ops setup
+ *	code however is limited in that all pv_ops setup code is run late in
+ *	the x86 init sequence, during setup_arch(). In fact cpu_has_hypervisor
+ *	only works after early_cpu_init() during setup_arch(). If an x86
+ *	feature requires an earlier determination of what hypervisor was used,
+ *	or if it needs to annotate only support for certain hypervisors, the
+ *	x86 hardware_subarch should be set by the bootloader and
+ *	@supp_hardware_subarch set by the x86 feature. Using hardware_subarch
+ *	enables x86 features to fill the semantic gap between the Linux x86
+ *	entry point used and what pv_ops has to offer through a hypervisor
+ *	agnostic mechanism.
+ *
+ *	Each supported subarchitecture is set using the respective
+ *	X86_SUBARCH_* as a bit in the bitmask. For instance if a feature
+ *	is supported on PC and Xen subarchitectures only you would set this
+ *	bitmask to:
+ *
+ *		BIT(X86_SUBARCH_PC) |
+ *		BIT(X86_SUBARCH_XEN);
+ *
+ * @early_init: required, routine which will run in x86_64_start_reservations()
+ *	after we ensure boot_params.hdr.hardware_subarch is accessible and
+ *	properly set. Memory is not yet available. This the earliest we can
+ *	currently define a common shared callback since all callbacks need to
+ *	check for boot_params.hdr.hardware_subarch and this becomes accessible
+ *	on x86-64 until after load_idt().
+ */
+struct x86_init_fn {
+	__u32 supp_hardware_subarch;
+	void (*early_init)(void);
+};
+
+DECLARE_LINKTABLE(struct x86_init_fn, x86_init_fns);
+
+/* Init order levels, we can start at 0000 but reserve 0000-0999 for now */
+
+/*
+ * X86_INIT_ORDER_EARLY - early kernel init code
+ *
+ * This consists of the first parts of the Linux kernel executed.
+ */
+#define X86_INIT_ORDER_EARLY	1000
+
+/* X86_INIT_ORDER_PLATFORM - platform kernel code
+ *
+ * Code the kernel needs to initialize under arch/x86/platform/
+ * early in boot.
+ */
+#define X86_INIT_ORDER_PLATFORM	3000
+
+#define __x86_init(__level,						\
+		   __supp_hardware_subarch,				\
+		   __early_init)					\
+	static LINKTABLE_INIT_DATA(x86_init_fns, __level)		\
+	__x86_init_fn_##__early_init = {				\
+		.supp_hardware_subarch = __supp_hardware_subarch,	\
+		.early_init = __early_init,				\
+	};
+
+#define x86_init_early(__supp_hardware_subarch,				\
+		       __early_init)					\
+	__x86_init(X86_INIT_ORDER_EARLY, __supp_hardware_subarch,	\
+		   __early_init);
+
+#define x86_init_platform(__supp_hardware_subarch,			\
+		       __early_init)					\
+	__x86_init(__name, X86_INIT_ORDER_PLATFORM, __supp_hardware_subarch,\
+		   __early_init);
+
+#define x86_init_early_all(__early_init)				\
+	x86_init_early(X86_SUBARCH_ALL_SUBARCHS,			\
+		       __early_init);
+
+#define x86_init_early_pc(__early_init)					\
+	x86_init_early(BIT(X86_SUBARCH_PC),				\
+		       __early_init);
+
+#define x86_init_early_xen(__early_init)				\
+	x86_init_early(BIT(X86_SUBARCH_XEN),				\
+		       __early_init);
+/**
+ * x86_init_fn_early_init: call all early_init() callbacks
+ *
+ * This calls all early_init() callbacks on the x86_init_fns linker table.
+ */
+void x86_init_fn_early_init(void);
+
+#endif /* __X86_INIT_TABLES_H */
diff --git a/tools/linker-tables/arch/x86/kernel/alpha.c b/tools/linker-tables/arch/x86/kernel/alpha.c
new file mode 100644
index 000000000000..0f9d45734c33
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/alpha.c
@@ -0,0 +1,9 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_alpha(void) {
+	pr_info("Initializing alpha ...\n");
+	pr_info("Completed initializing alpha !\n");
+}
+
+x86_init_early_pc(early_init_alpha);
diff --git a/tools/linker-tables/arch/x86/kernel/alternative.c b/tools/linker-tables/arch/x86/kernel/alternative.c
new file mode 100644
index 000000000000..ea67562d36a9
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/alternative.c
@@ -0,0 +1,31 @@
+#include <asm/x86_init_fn.h>
+
+#include <linux/kernel.h>
+#include <linux/ps_const.h>
+
+void apply_alternatives_linker_tables(void)
+{
+	unsigned int num_consts = LINKTABLE_SIZE(ps_set_const_table);
+	struct ps_set_const *ps_const;
+
+	if (!num_consts)
+		return;
+
+	pr_debug("Number of init entries: %d\n", num_consts);
+
+	LINKTABLE_FOR_EACH(ps_const, ps_set_const_table) {
+		switch(ps_const->type) {
+		case SET_CONST_U8:
+			*ps_const->count = (__u8) ps_const->func();
+			break;
+		case SET_CONST_U16:
+			*ps_const->count = (__u16) ps_const->func();
+			break;
+		case SET_CONST_U32:
+			*ps_const->count = (__u16) ps_const->func();
+			break;
+		}
+	}
+}
+
+x86_init_early_pc(apply_alternatives_linker_tables);
diff --git a/tools/linker-tables/arch/x86/kernel/beta.c b/tools/linker-tables/arch/x86/kernel/beta.c
new file mode 100644
index 000000000000..2bdbf49d4731
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/beta.c
@@ -0,0 +1,9 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_beta(void) {
+	pr_info("Initializing beta ...\n");
+	pr_info("Completed initializing beta !\n");
+}
+
+x86_init_early_pc(early_init_beta);
diff --git a/tools/linker-tables/arch/x86/kernel/head64.c b/tools/linker-tables/arch/x86/kernel/head64.c
new file mode 100644
index 000000000000..d14dcdfd0ea9
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/head64.c
@@ -0,0 +1,58 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+
+#include <asm/x86_init_fn.h>
+#include <asm/boot.h>
+#include <asm/bootparam.h>
+
+#include <linux/start_kernel.h>
+#include <linux/kasan.h>
+
+void x86_64_start_reservations(void)
+{
+	switch (boot_params.hdr.hardware_subarch) {
+	case X86_SUBARCH_PC:
+		pr_info("Booting bare metal\n");
+		break;
+	case X86_SUBARCH_LGUEST:
+		pr_info("Booting lguest not supported\n");
+		BUG();
+	case X86_SUBARCH_XEN:
+		pr_info("Booting a Xen guest\n");
+		break;
+	case X86_SUBARCH_INTEL_MID:
+		pr_info("Booting Intel MID not supported\n");
+		BUG();
+	case X86_SUBARCH_CE4100:
+		pr_info("Booting Intel CE4100 not supported\n");
+		BUG();
+	default:
+		pr_info("Booting sunsupported x86 hardware subarch\n");
+		BUG();
+	}
+
+	start_kernel();
+}
+
+static void x86_64_start_kernel(void)
+{
+	x86_init_fn_early_init();
+
+	x86_64_start_reservations();
+}
+
+void startup_64(void)
+{
+	pr_info("Initializing x86 bare metal world\n");
+	x86_64_start_kernel();
+}
+
+void setup_arch(void)
+{
+	/* TODO: x86_init_fn_setup_arch(); */
+}
+
+void late_init(void)
+{
+	/* TODO: x86_init_fn_late_init(); */
+}
diff --git a/tools/linker-tables/arch/x86/kernel/init.c b/tools/linker-tables/arch/x86/kernel/init.c
new file mode 100644
index 000000000000..3de4e506425c
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/init.c
@@ -0,0 +1,42 @@
+#define pr_fmt(fmt) "x86-init: " fmt
+
+#include <linux/bug.h>
+#include <linux/kernel.h>
+
+#include <asm/x86_init_fn.h>
+#include <asm/bootparam.h>
+#include <asm/boot.h>
+#include <asm/setup.h>
+
+DEFINE_LINKTABLE_INIT_DATA(struct x86_init_fn, x86_init_fns);
+
+static bool x86_init_fn_supports_subarch(struct x86_init_fn *fn)
+{
+	if (!fn->supp_hardware_subarch) {
+		//pr_err("Init sequence fails to declares any supported subarchs: %pF\n", fn->early_init);
+		WARN_ON(1);
+	}
+	if (BIT(boot_params.hdr.hardware_subarch) & fn->supp_hardware_subarch)
+		return true;
+	return false;
+}
+
+void __ref x86_init_fn_early_init(void)
+{
+	struct x86_init_fn *init_fn;
+	unsigned int num_inits = LINKTABLE_SIZE(x86_init_fns);
+
+	if (!num_inits)
+		return;
+
+	pr_debug("Number of init entries: %d\n", num_inits);
+
+	LINKTABLE_FOR_EACH(init_fn, x86_init_fns) {
+		if (!x86_init_fn_supports_subarch(init_fn))
+			continue;
+
+		//pr_debug("Running early init %pF ...\n", init_fn->early_init);
+		init_fn->early_init();
+		//pr_debug("Completed early init %pF\n", init_fn->early_init);
+	}
+}
diff --git a/tools/linker-tables/arch/x86/kernel/kasan.c b/tools/linker-tables/arch/x86/kernel/kasan.c
new file mode 100644
index 000000000000..c0120676eb9c
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/kasan.c
@@ -0,0 +1,10 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+void kasan_early_init(void) {
+	pr_info("Initializing kasan ...\n");
+	pr_info("Early init for Kasan...\n");
+	pr_info("Completed initializing kasan !\n");
+}
+
+x86_init_early_pc(kasan_early_init);
diff --git a/tools/linker-tables/arch/x86/kernel/kprobes.c b/tools/linker-tables/arch/x86/kernel/kprobes.c
new file mode 100644
index 000000000000..c4e42beae55b
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/kprobes.c
@@ -0,0 +1,51 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <linux/ranges.h>
+#include <linux/kprobes.h>
+
+DEFINE_SECTION_RANGE(kprobes, .text);
+
+void __kprobes test_kprobe_0001(void)
+{
+	pr_info("test_kprobe\n");
+}
+
+void test_kprobe_0002(void)
+{
+	pr_info("test_kprobe\n");
+}
+
+void test_kprobe_addr(const char *test, unsigned long addr, bool should_match)
+{
+	if (SECTION_RANGE_ADDR_WITHIN(kprobes, addr))
+		if (should_match)
+			pr_info("= OK: %s within range!\n", test);
+		else
+			pr_info("= FAIL: %s should not be in range...\n",
+				test);
+	else
+		if (should_match)
+			pr_info("= FAIL: %s should be in range...\n", test);
+		else
+			pr_info("= OK: %s not in range as expected!\n", test);
+}
+
+void early_init_kprobes(void)
+{
+	unsigned long addr;
+
+	pr_info("Initializing kprobes ...\n");
+
+	addr = (unsigned long) &test_kprobe_0001;
+
+	test_kprobe_addr("test_kprobe_0001", addr, true);
+
+	addr = (unsigned long) &test_kprobe_0002;
+
+	test_kprobe_addr("test_kprobe_0002", addr, false);
+
+	pr_info("Completed initializing kprobes !\n");
+}
+
+x86_init_early_all(early_init_kprobes);
diff --git a/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S b/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
new file mode 100644
index 000000000000..783735fb897a
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
@@ -0,0 +1,277 @@
+/* Script for -z combreloc: combine and sort reloc sections */
+/* Copyright (C) 2014 Free Software Foundation, Inc.
+   Copying and distribution of this script, with or without modification,
+   are permitted in any medium without royalty provided the copyright
+   notice and this notice are preserved.  */
+
+#include <asm/section-core.h>
+#include <asm/ranges.h>
+#include <asm/tables.h>
+
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
+	      "elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(_start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
+  .interp         : { *(.interp) }
+  .note.gnu.build-id : { *(.note.gnu.build-id) }
+  .hash           : { *(.hash) }
+  .gnu.hash       : { *(.gnu.hash) }
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+  .rela.dyn       :
+    {
+      *(.rela.init)
+      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+      *(.rela.fini)
+      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+      *(.rela.ctors)
+      *(.rela.dtors)
+      *(.rela.got)
+      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+      *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
+      *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
+      *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
+      *(.rela.ifunc)
+    }
+  .rela.plt       :
+    {
+      *(.rela.plt)
+      PROVIDE_HIDDEN (__rela_iplt_start = .);
+      *(.rela.iplt)
+      PROVIDE_HIDDEN (__rela_iplt_end = .);
+    }
+  .init           :
+  {
+    KEEP (*(SORT_NONE(.init)))
+  }
+  .plt            : { *(.plt) *(.iplt) }
+  .plt.bnd        : { *(.plt.bnd) }
+  .text           :
+  {
+    *(.text.unlikely .text.*_unlikely .text.unlikely.*)
+    *(.text.exit .text.exit.*)
+    *(.text.startup .text.startup.*)
+    *(.text.hot .text.hot.*)
+
+    *(SORT(.text..rng.*))
+    *(SORT(.text..tbl.*))
+
+    *(SORT(.init.text..rng.*))
+    *(SORT(.init.text..tbl.*))
+
+    *(SORT(.initcall..rng.*))
+    *(SORT(.initcall..tbl.*))
+
+    *(SORT(.exit.text..rng.*))
+    *(SORT(.exit.text..tbl.*))
+
+    *(SORT(.exitcall.exit..rng.*))
+    *(SORT(.exitcall.exit..tbl.*))
+
+    *(.text .stub .text.* .gnu.linkonce.t.*)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  }
+  .fini           :
+  {
+    KEEP (*(SORT_NONE(.fini)))
+  }
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+  .rodata         :
+  {
+	*(.rodata)
+
+	*(SORT(.rodata.*))
+
+	*(SORT(.rodata..rng.*))
+	*(SORT(.rodata..tbl.*))
+
+	*(SORT(.init.rodata..rng.*))
+	*(SORT(.init.rodata..tbl.*))
+
+	*(SORT(.ref.rodata..rng.*))
+	*(SORT(.ref.rodata..tbl.*))
+
+	*(.gnu.linkonce.r.*)
+  }
+  .rodata1        : { *(.rodata1) }
+  .eh_frame_hdr : { *(.eh_frame_hdr) }
+  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table
+  .gcc_except_table.*) }
+  /* These sections are generated by the Sun/Oracle C++ compiler.  */
+  .exception_ranges   : ONLY_IF_RO { *(.exception_ranges
+  .exception_ranges*) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  */
+  . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+  /* Exception handling  */
+  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
+  .exception_ranges   : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
+  /* Thread Local Storage sections  */
+  .tdata	  : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+  .preinit_array     :
+  {
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP (*(.preinit_array))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+  }
+  .init_array     :
+  {
+    PROVIDE_HIDDEN (__init_array_start = .);
+    KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
+    KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
+    PROVIDE_HIDDEN (__init_array_end = .);
+  }
+  .fini_array     :
+  {
+    PROVIDE_HIDDEN (__fini_array_start = .);
+    KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
+    KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
+    PROVIDE_HIDDEN (__fini_array_end = .);
+  }
+  .ctors          :
+  {
+    /* gcc uses crtbegin.o to find the start of
+       the constructors, so we make sure it is
+       first.  Because this is a wildcard, it
+       doesn't matter if the user does not
+       actually link against crtbegin.o; the
+       linker won't look for a file to match a
+       wildcard.  The wildcard also means that it
+       doesn't matter which directory crtbegin.o
+       is in.  */
+    KEEP (*crtbegin.o(.ctors))
+    KEEP (*crtbegin?.o(.ctors))
+    /* We don't want to include the .ctor section from
+       the crtend.o file until after the sorted ctors.
+       The .ctor section from the crtend file contains the
+       end of ctors marker and it must be last */
+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+  .dtors          :
+  {
+    KEEP (*crtbegin.o(.dtors))
+    KEEP (*crtbegin?.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  .jcr            : { KEEP (*(.jcr)) }
+  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
+  .dynamic        : { *(.dynamic) }
+  .got            : { *(.got) *(.igot) }
+  . = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
+  .got.plt        : { *(.got.plt)  *(.igot.plt) }
+  .data           :
+  {
+    *(.data .data.* .gnu.linkonce.d.*)
+
+    *(SORT(.data..rng.*))
+    *(SORT(.data..tbl.*))
+
+    *(SORT(.init.data..rng.*))
+    *(SORT(.init.data..tbl.*))
+
+    *(SORT(.ref.rodata..rng.*))
+    *(SORT(.ref.rodata..tbl.*))
+
+    *(SORT(.exit.data..rng.*))
+    *(SORT(.exit.data..tbl.*))
+
+    SORT(CONSTRUCTORS)
+  }
+  .data1          : { *(.data1) }
+  _edata = .; PROVIDE (edata = .);
+  . = .;
+
+  __bss_start = .;
+  .bss            :
+  {
+   *(.dynbss)
+   *(.bss .bss.* .gnu.linkonce.b.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.
+      FIXME: Why do we need it? When there is no .bss section, we don't
+      pad the .data section.  */
+   . = ALIGN(. != 0 ? 64 / 8 : 1);
+  }
+  .lbss   :
+  {
+    *(.dynlbss)
+    *(.lbss .lbss.* .gnu.linkonce.lb.*)
+    *(LARGE_COMMON)
+  }
+  . = ALIGN(64 / 8);
+  . = SEGMENT_START("ldata-segment", .);
+  .lrodata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+  {
+    *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
+  }
+  .ldata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+  {
+    *(.ldata .ldata.* .gnu.linkonce.l.*)
+    . = ALIGN(. != 0 ? 64 / 8 : 1);
+  }
+  . = ALIGN(64 / 8);
+  _end = .; PROVIDE (end = .);
+  . = DATA_SEGMENT_END (.);
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line .debug_line.* .debug_line_end ) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  /* DWARF 3 */
+  .debug_pubtypes 0 : { *(.debug_pubtypes) }
+  .debug_ranges   0 : { *(.debug_ranges) }
+  /* DWARF Extension.  */
+  .debug_macro    0 : { *(.debug_macro) }
+  .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
+}
diff --git a/tools/linker-tables/arch/x86/mm/init.c b/tools/linker-tables/arch/x86/mm/init.c
new file mode 100644
index 000000000000..dbf1a85a4043
--- /dev/null
+++ b/tools/linker-tables/arch/x86/mm/init.c
@@ -0,0 +1,10 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_memory(void) {
+	pr_info("Initializing memory ...\n");
+	sleep(1);
+	pr_info("Completed initializing memory !\n");
+}
+
+x86_init_early_all(early_init_memory);
diff --git a/tools/linker-tables/arch/x86/xen/init.c b/tools/linker-tables/arch/x86/xen/init.c
new file mode 100644
index 000000000000..40ad493daee8
--- /dev/null
+++ b/tools/linker-tables/arch/x86/xen/init.c
@@ -0,0 +1,13 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <asm/x86.h>
+
+void startup_xen(void)
+{
+	pr_info("Initializing Xen guest\n");
+
+	x86_init_fn_early_init();
+
+	x86_64_start_reservations();
+}
diff --git a/tools/linker-tables/drivers/acme.c b/tools/linker-tables/drivers/acme.c
new file mode 100644
index 000000000000..dd321686dd49
--- /dev/null
+++ b/tools/linker-tables/drivers/acme.c
@@ -0,0 +1,32 @@
+#define pr_fmt(fmt) "ACME: " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/workqueue.h>
+
+void *acme_todo(void *arg);
+static DECLARE_WORK(acme_work, acme_todo);
+
+void *acme_todo(void *arg)
+{
+	pr_info("Running scheduled work\n");
+	pthread_exit(NULL);
+}
+
+static int acme_init_driver(void) {
+	pr_info("Initializing ...\n");
+	sleep(2);
+	pr_info("Finished init ... !\n");
+
+	init_work(&acme_work);
+	schedule_work(&acme_work);
+
+	return 0;
+}
+module_init(acme_init_driver);
+
+static void acme_exit(void)
+{
+	cancel_work_sync(&acme_work);
+};
+module_exit(acme_exit);
diff --git a/tools/linker-tables/drivers/synth/common.c b/tools/linker-tables/drivers/synth/common.c
new file mode 100644
index 000000000000..b44d9fcc7a9b
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/common.c
@@ -0,0 +1,16 @@
+int demo_or_1(int arg)
+{
+	switch (arg) {
+	case 1:
+		return 0xDEA00000;
+	case 2:
+		return 0X000D0000;
+	default:
+		return arg * 2;
+	}
+}
+
+int demo_or_2(void)
+{
+	return 0x0000BEEF;
+}
diff --git a/tools/linker-tables/drivers/synth/common.h b/tools/linker-tables/drivers/synth/common.h
new file mode 100644
index 000000000000..92827004f532
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/common.h
@@ -0,0 +1,2 @@
+int demo_or_1(int arg);
+int demo_or_2(void);
diff --git a/tools/linker-tables/drivers/synth/main.c b/tools/linker-tables/drivers/synth/main.c
new file mode 100644
index 000000000000..555cf97a5cbb
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/main.c
@@ -0,0 +1,35 @@
+#define pr_fmt(fmt) "Synthetics: " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ps_const.h>
+
+#include "common.h"
+#include "synth.h"
+
+DEFINE_LINKTABLE_INIT_DATA(struct ps_set_const, ps_set_const_table);
+
+unsigned int get_demo_shr(void)
+{
+	return 16;
+}
+
+static int synth_init(void)
+{
+	int synth_or;
+	int val = 2;
+	const unsigned int reg =  ps_shr(0xDEADBEEF, get_demo_shr);
+
+	synth_or = synth_init_or(val);
+	pr_info("synth_init_or(%d) returns: 0x%08X\n", val, synth_or);
+
+	pr_info("ps_shr(0x%08X, get_demo_shr) returns: 0x%08X\n", 0xDEADBEEF, reg);
+
+	return 0;
+}
+module_init(synth_init);
+
+static void synth_exit(void)
+{
+}
+module_exit(synth_exit);
diff --git a/tools/linker-tables/drivers/synth/or.S b/tools/linker-tables/drivers/synth/or.S
new file mode 100644
index 000000000000..deb963fdae33
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/or.S
@@ -0,0 +1,39 @@
+#include <asm/ranges.h>
+
+	DEFINE_SECTION_RANGE(.text, synth_init_or)
+
+	push_section_rng_level(.text, synth_init_or, "01", )
+	/* err = 0; */
+	pushq %rbp
+	movq %rsp,%rbp
+	pushq %rbx
+	xorq %rbx,%rbx
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "99", )
+	/* return err; */
+	movq %rbx,%rax
+	popq %rbx
+	popq %rbp
+	retq
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "50", )
+	/* err |= demo_or_1(1); */
+	movl $1,%edi
+	call demo_or_1
+	orq %rax,%rbx
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "50", )
+	/* err |= demo_or_1(2); */
+	movl $2,%edi
+	call demo_or_1
+	orq %rax,%rbx
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "50", )
+	/* err |= demo_or_2(); */
+	call demo_or_2
+	orq %rax,%rbx
+	.popsection
diff --git a/tools/linker-tables/drivers/synth/synth.h b/tools/linker-tables/drivers/synth/synth.h
new file mode 100644
index 000000000000..abbb9afac374
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/synth.h
@@ -0,0 +1,2 @@
+/* Synthetic demos go here */
+int synth_init_or(int arg);
diff --git a/tools/linker-tables/drivers/xen-driver.c b/tools/linker-tables/drivers/xen-driver.c
new file mode 100644
index 000000000000..79d229f72818
--- /dev/null
+++ b/tools/linker-tables/drivers/xen-driver.c
@@ -0,0 +1,11 @@
+#include <asm/x86_init_fn.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <xen/xen.h>
+
+static void early_xen_init_driver(void) {
+	pr_info("Initializing xen driver\n");
+	sleep(2);
+}
+
+x86_init_early_xen(early_xen_init_driver);
diff --git a/tools/linker-tables/include/asm-generic/arch_init_fn.h b/tools/linker-tables/include/asm-generic/arch_init_fn.h
new file mode 100644
index 000000000000..61a04a50b453
--- /dev/null
+++ b/tools/linker-tables/include/asm-generic/arch_init_fn.h
@@ -0,0 +1,50 @@
+#ifndef __ARCH_INIT_TABLES_H
+#define __ARCH_INIT_TABLES_H
+
+#include <linux/types.h>
+#include <linux/tables.h>
+#include <linux/init.h>
+
+/**
+ * struct arch_init_fn - architecture-generic kernel init call
+ *
+ * Architectures must initialize a series of things prior to handing off
+ * control to the kernel. This structure can be used if the architecture is
+ * simple and it just needs a basic set of calls on its way up.
+ *
+ * @early_init: required, routine which will run in startup_64(). Memory is
+ * 	not yet available.
+ */
+struct arch_init_fn {
+	void (*early_init)(void);
+};
+
+DECLARE_LINKTABLE(struct arch_init_fn, arch_init_fns);
+
+/* Init order levels, we can start at 0000 but reserve 0000-0999 for now */
+
+/*
+ * ARCH_INIT_ORDER_EARLY - early kernel init code
+ *
+ * This consists of the first parts of the Linux kernel executed.
+ */
+#define ARCH_INIT_ORDER_EARLY	1000
+
+#define __arch_init(__level,						\
+		    __early_init)					\
+	static LINKTABLE_INIT_DATA(arch_init_fns, __level)		\
+	__arch_init_fn_##__early_init = {				\
+		.early_init = __early_init,				\
+	}
+
+#define arch_init_early(__early_init)					\
+	__arch_init(ARCH_INIT_ORDER_EARLY, __early_init)
+
+/**
+ * arch_init_fn_early_init: call all early_init() callbacks
+ *
+ * This calls all early_init() callbacks on the arch_init_fns linker table.
+ */
+void arch_init_fn_early_init(void);
+
+#endif /* __ARCH_INIT_TABLES_H */
diff --git a/tools/linker-tables/include/asm-generic/kprobes.h b/tools/linker-tables/include/asm-generic/kprobes.h
new file mode 100644
index 000000000000..839d2eb464d3
--- /dev/null
+++ b/tools/linker-tables/include/asm-generic/kprobes.h
@@ -0,0 +1,26 @@
+#ifndef _SANDBOX_ASM_GENERIC_KPROBES_H
+#define _SANDBOX_ASM_GENERIC_KPROBES_H
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#ifdef CONFIG_KPROBES
+#include <linux/tables.h>
+#include <asm/ranges.h>
+/*
+ * Blacklist ganerating macro. Specify functions which is not probed
+ * by using this macro.
+ */
+# define __NOKPROBE_SYMBOL(fname)				\
+static LINKTABLE_INIT_DATA(_kprobe_blacklist, all)		\
+	_kbl_addr_##fname = (unsigned long)fname;
+# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
+/* Use this to forbid a kprobes attach on very low level functions */
+# define __kprobes	__LINUX_RANGE(.text, kprobes)
+# define nokprobe_inline	__always_inline
+#else
+# define NOKPROBE_SYMBOL(fname)
+# define __kprobes
+# define nokprobe_inline	inline
+#endif
+#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
+
+#endif /* _SANDBOX_ASM_GENERIC_KPROBES_H */
diff --git a/tools/linker-tables/include/linux/bitops.h b/tools/linker-tables/include/linux/bitops.h
new file mode 100644
index 000000000000..2960e8089ebc
--- /dev/null
+++ b/tools/linker-tables/include/linux/bitops.h
@@ -0,0 +1,6 @@
+#ifndef _LINUX_BITOPS_H
+#define _LINUX_BITOPS_H
+
+#define BIT(nr)		(1UL << (nr))
+
+#endif /* _LINUX_BITOPS_H */
diff --git a/tools/linker-tables/include/linux/init.h b/tools/linker-tables/include/linux/init.h
new file mode 100644
index 000000000000..2691c3697f48
--- /dev/null
+++ b/tools/linker-tables/include/linux/init.h
@@ -0,0 +1,40 @@
+#ifndef _SANDBOX_LINUX_INIT_H
+#define _SANDBOX_LINUX_INIT_H
+
+#include_next <linux/init.h>
+#include <linux/types.h>
+#include <linux/sections.h>
+
+#define __init	__section(.init.text)
+#define __exit	__section(.exit.text)
+
+#ifndef __ASSEMBLY__
+#include <linux/tables.h>
+typedef int (*initcall_t)(void);
+typedef void (*exitcall_t)(void);
+
+DECLARE_LINKTABLE(initcall_t, init_calls);
+DECLARE_LINKTABLE(exitcall_t, exit_calls);
+
+#define __define_initcall(fn, id)					\
+	static LINKTABLE_INIT_DATA(init_calls, id)			\
+	__initcall_##fn##id = fn
+
+#define pure_initcall(fn)			__define_initcall(fn, 0)
+#define core_initcall(fn)			__define_initcall(fn, 1)
+#define postcore_initcall(fn)			__define_initcall(fn, 2)
+#define arch_initcall(fn)			__define_initcall(fn, 3)
+#define subsys_initcall(fn)			__define_initcall(fn, 4)
+#define fs_initcall(fn)				__define_initcall(fn, 5)
+#define device_initcall(fn)			__define_initcall(fn, 6)
+#define late_initcall(fn)			__define_initcall(fn, 7)
+
+#define __initcall(fn)				device_initcall(fn)
+
+#define __exitcall(fn)							\
+	static LINKTABLE_INIT_DATA(exit_calls, any)			\
+	__exitcall_##fn = fn;
+
+#endif
+
+#endif /* _SANDBOX_LINUX_INIT_H */
diff --git a/tools/linker-tables/include/linux/kasan.h b/tools/linker-tables/include/linux/kasan.h
new file mode 100644
index 000000000000..41791187854e
--- /dev/null
+++ b/tools/linker-tables/include/linux/kasan.h
@@ -0,0 +1,5 @@
+#include <linux/types.h>
+
+void kasan_early_init(void);
+int kasan_init(void);
+bool is_kasan_setup(void);
diff --git a/tools/linker-tables/include/linux/kernel.h b/tools/linker-tables/include/linux/kernel.h
new file mode 100644
index 000000000000..e2857c0b5b11
--- /dev/null
+++ b/tools/linker-tables/include/linux/kernel.h
@@ -0,0 +1,2 @@
+#include_next <linux/kernel.h>
+#include <linux/printk.h>
diff --git a/tools/linker-tables/include/linux/kprobes.h b/tools/linker-tables/include/linux/kprobes.h
new file mode 100644
index 000000000000..ecd5a0a69ae6
--- /dev/null
+++ b/tools/linker-tables/include/linux/kprobes.h
@@ -0,0 +1,11 @@
+#ifndef _SANDBOX_LINUX_KPROBES_H
+#define _SANDBOX_LINUX_KPROBES_H
+
+#include <asm/kprobes.h>
+#include <linux/ranges.h>
+
+#ifdef CONFIG_KPROBES
+DECLARE_SECTION_RANGE(kprobes);
+#endif
+
+#endif /* _SANDBOX_LINUX_KPROBES_H */
diff --git a/tools/linker-tables/include/linux/module.h b/tools/linker-tables/include/linux/module.h
new file mode 100644
index 000000000000..b59e55f3f04e
--- /dev/null
+++ b/tools/linker-tables/include/linux/module.h
@@ -0,0 +1,14 @@
+#ifndef _LINUX_MODULE_H
+#define _LINUX_MODULE_H
+
+#include <linux/init.h>
+
+#define module_init(x)  __initcall(x);
+#define module_exit(x)  __exitcall(x);
+
+struct module {
+	int (*init)(void);
+	void (*exit)(void);
+};
+
+#endif /* _LINUX_MODULE_H */
diff --git a/tools/linker-tables/include/linux/mutex.h b/tools/linker-tables/include/linux/mutex.h
new file mode 100644
index 000000000000..a74f951ceb42
--- /dev/null
+++ b/tools/linker-tables/include/linux/mutex.h
@@ -0,0 +1,17 @@
+#ifndef __LINUX_MUTEX_H
+#define __LINUX_MUTEX_H
+
+#include <sys/types.h>
+#include <linux/sched.h>
+#include <pthread.h>
+
+struct mutex {
+	pthread_mutex_t lock;
+};
+
+void mutex_init(struct mutex *lock);
+void mutex_destroy(struct mutex *lock);
+void mutex_lock(struct mutex *lock);
+void mutex_unlock(struct mutex *lock);
+
+#endif /* __LINUX_MUTEX_H */
diff --git a/tools/linker-tables/include/linux/pci.h b/tools/linker-tables/include/linux/pci.h
new file mode 100644
index 000000000000..8518c46631f7
--- /dev/null
+++ b/tools/linker-tables/include/linux/pci.h
@@ -0,0 +1,7 @@
+#include <linux/types.h>
+
+struct pci_fixup {
+	void (*hook)(void);
+};
+
+bool detect_pci(void);
diff --git a/tools/linker-tables/include/linux/printk.h b/tools/linker-tables/include/linux/printk.h
new file mode 100644
index 000000000000..dc137d3421e8
--- /dev/null
+++ b/tools/linker-tables/include/linux/printk.h
@@ -0,0 +1,26 @@
+#ifndef _SANDBOX_KERNEL_PRINTK
+#define _SANDBOX_KERNEL_PRINTK
+
+#ifdef __KERNEL__
+
+#include <stdio.h>
+
+#ifndef pr_fmt
+#define pr_fmt(fmt)	fmt
+#endif
+
+#ifndef pr_info
+#define pr_info(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
+#ifndef pr_err
+#define pr_err(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
+#ifndef pr_debug
+#define pr_debug(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* _SANDBOX_KERNEL_PRINTK */
diff --git a/tools/linker-tables/include/linux/ps_const.h b/tools/linker-tables/include/linux/ps_const.h
new file mode 100644
index 000000000000..5eab3a124e00
--- /dev/null
+++ b/tools/linker-tables/include/linux/ps_const.h
@@ -0,0 +1,46 @@
+#ifndef __PS_CONST
+#define __PS_CONST
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/tables.h>
+
+/* Helpers for partially static settings */
+
+enum ps_static_type {
+	SET_CONST_U8 = 0,
+	SET_CONST_U16,
+	SET_CONST_U32,
+};
+
+struct ps_set_const {
+	unsigned int *count;
+	enum ps_static_type type;
+	unsigned int (*func)(void);
+};
+
+DECLARE_LINKTABLE(struct ps_set_const, ps_set_const_table);
+
+#ifdef CONFIG_HAVE_ARCH_PS_CONST
+#include <asm/ps_const.h>
+#endif
+
+/*
+ * ps_ stands for "partially static", so we "partialloy static shift right"
+ * You can optimize this for your architecture.
+ *
+ * ps_shr(unsigned int in, unsigned char (*func)(void))
+ */
+#ifndef ps_shr
+#define ps_shr(_in, _func)						\
+({									\
+	static unsigned int _count;					\
+	static LINKTABLE_INIT_DATA(ps_set_const_table, 01)		\
+		__ps_shr##__func =					\
+		{ &_count, SET_CONST_U8, (_func) };			\
+									\
+	(_in) >> _count;						\
+})
+#endif /* ps_shr */
+
+#endif /* __PS_CONST */
diff --git a/tools/linker-tables/include/linux/sched.h b/tools/linker-tables/include/linux/sched.h
new file mode 100644
index 000000000000..0fe3526e88bf
--- /dev/null
+++ b/tools/linker-tables/include/linux/sched.h
@@ -0,0 +1,9 @@
+#ifndef _LINUX_SCHED_H
+#define _LINUX_SCHED_H
+
+#include <linux/ranges.h>
+
+DECLARE_SECTION_RANGE(sched_text);
+#define __sched		__LINUX_RANGE(.text, sched_text)
+
+#endif /* _LINUX_SCHED_H */
diff --git a/tools/linker-tables/include/linux/spinlock.h b/tools/linker-tables/include/linux/spinlock.h
new file mode 100644
index 000000000000..e62bc3bc5e6a
--- /dev/null
+++ b/tools/linker-tables/include/linux/spinlock.h
@@ -0,0 +1,13 @@
+#ifndef __LINUX_SPINLOCK_H
+#define __LINUX_SPINLOCK_H
+
+#include <pthread.h>
+
+#define spinlock_t pthread_spinlock_t
+
+void spin_lock_init(spinlock_t *lock);
+void spin_lock_destroy(spinlock_t *lock);
+void spin_lock(spinlock_t *lock);
+void spin_unlock(spinlock_t *lock);
+
+#endif /* __LINUX_SPINLOCK_H */
diff --git a/tools/linker-tables/include/linux/start_kernel.h b/tools/linker-tables/include/linux/start_kernel.h
new file mode 100644
index 000000000000..5c2cb9a5cb0c
--- /dev/null
+++ b/tools/linker-tables/include/linux/start_kernel.h
@@ -0,0 +1 @@
+int start_kernel(void);
diff --git a/tools/linker-tables/include/linux/types.h b/tools/linker-tables/include/linux/types.h
new file mode 100644
index 000000000000..3fc87b2c84e2
--- /dev/null
+++ b/tools/linker-tables/include/linux/types.h
@@ -0,0 +1,13 @@
+#ifndef __LINUX_USER_TYPES_H
+#define __LINUX_USER_TYPES_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+typedef unsigned char __u8;
+typedef unsigned short __u16;
+typedef unsigned int __u32;
+
+#endif /* __LINUX_USER_TYPES_H */
diff --git a/tools/linker-tables/include/linux/workqueue.h b/tools/linker-tables/include/linux/workqueue.h
new file mode 100644
index 000000000000..69e1c6de5051
--- /dev/null
+++ b/tools/linker-tables/include/linux/workqueue.h
@@ -0,0 +1,51 @@
+#ifndef _LINUX_WORKQUEUE_H
+#define _LINUX_WORKQUEUE_H
+
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <pthread.h>
+
+struct work {
+	bool ready;
+
+	pthread_t thread;
+	struct mutex mutex;
+	pthread_cond_t cond;
+
+	void *arg;
+	void *(*work_cb)(void *arg);
+};
+
+#define DECLARE_WORK(_w, _w_cb) \
+struct work _w = { \
+	.work_cb = _w_cb, \
+	.arg = NULL, \
+};
+
+extern void *run_work(void *arg);
+
+static inline void init_work(struct work *w)
+{
+	w->ready = false;
+
+	mutex_init(&w->mutex);
+	pthread_cond_init(&w->cond, NULL);
+
+	pthread_create(&w->thread, NULL, run_work, (void *) w);
+
+	while (1) {
+		mutex_lock(&w->mutex);
+		if (w->ready) {
+			pthread_mutex_unlock(&w->mutex.lock);
+			break;
+		}
+		mutex_unlock(&w->mutex);
+	}
+}
+
+void schedule_work(struct work *w);
+void cancel_work_sync(struct work *w);
+void init_work(struct work *w);
+
+#endif /* _LINUX_WORKQUEUE_H */
diff --git a/tools/linker-tables/include/xen/xen.h b/tools/linker-tables/include/xen/xen.h
new file mode 100644
index 000000000000..782c799a0064
--- /dev/null
+++ b/tools/linker-tables/include/xen/xen.h
@@ -0,0 +1,4 @@
+#include <linux/types.h>
+
+bool booting_xen(void);
+int startup_xen(void);
diff --git a/tools/linker-tables/kernel/locking/mutex.c b/tools/linker-tables/kernel/locking/mutex.c
new file mode 100644
index 000000000000..950e4a18461e
--- /dev/null
+++ b/tools/linker-tables/kernel/locking/mutex.c
@@ -0,0 +1,28 @@
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+
+DEFINE_SECTION_RANGE(sched_text, .text);
+
+void __sched mutex_init(struct mutex *lock)
+{
+	int r;
+
+	r = pthread_mutex_init(&lock->lock, NULL);
+	if (r)
+		BUG_ON(r);
+}
+
+void __sched mutex_destroy(struct mutex *lock)
+{
+	pthread_mutex_destroy(&lock->lock);
+}
+
+void __sched mutex_lock(struct mutex *lock)
+{
+	pthread_mutex_lock(&lock->lock);
+}
+
+void __sched mutex_unlock(struct mutex *lock)
+{
+	pthread_mutex_unlock(&lock->lock);
+}
diff --git a/tools/linker-tables/kernel/locking/spinlock.c b/tools/linker-tables/kernel/locking/spinlock.c
new file mode 100644
index 000000000000..5be2bc7cdece
--- /dev/null
+++ b/tools/linker-tables/kernel/locking/spinlock.c
@@ -0,0 +1,26 @@
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+
+void spin_lock_init(spinlock_t *lock)
+{
+	int r;
+
+	r = pthread_spin_init(lock, PTHREAD_PROCESS_SHARED);
+	if (r)
+		BUG_ON(r);
+}
+
+void spin_lock_destroy(spinlock_t *lock)
+{
+	pthread_spin_destroy(lock);
+}
+
+void spin_lock(spinlock_t *lock)
+{
+	pthread_spin_lock(lock);
+}
+
+void spin_unlock(spinlock_t *lock)
+{
+	pthread_spin_unlock(lock);
+}
diff --git a/tools/linker-tables/kernel/main.c b/tools/linker-tables/kernel/main.c
new file mode 100644
index 000000000000..f3826cdb2ca8
--- /dev/null
+++ b/tools/linker-tables/kernel/main.c
@@ -0,0 +1,32 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/x86_init_fn.h>
+#include <asm/x86.h>
+
+DEFINE_LINKTABLE_INIT_DATA(initcall_t, init_calls);
+
+int do_one_initcall(initcall_t fn)
+{
+	int ret;
+
+	ret = fn();
+
+	return ret;
+}
+
+static void do_initcalls(void)
+{
+	initcall_t *fn;
+
+	 LINKTABLE_FOR_EACH(fn, init_calls)
+		 do_one_initcall(*fn);
+}
+
+void start_kernel(void)
+{
+	pr_info("Calling start_kernel()...\n");
+
+	setup_arch();
+	late_init();
+	do_initcalls();
+}
diff --git a/tools/linker-tables/kernel/workqueue.c b/tools/linker-tables/kernel/workqueue.c
new file mode 100644
index 000000000000..5ba73c7e7c8b
--- /dev/null
+++ b/tools/linker-tables/kernel/workqueue.c
@@ -0,0 +1,43 @@
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <linux/workqueue.h>
+#include <linux/kernel.h>
+
+void schedule_work(struct work *w)
+{
+	mutex_lock(&w->mutex);
+	pthread_cond_signal(&w->cond);
+	mutex_unlock(&w->mutex);
+}
+
+void cancel_work_sync(struct work *w)
+{
+	pthread_exit(NULL);
+}
+
+void *run_work(void *arg)
+{
+	struct work *w;
+	int r;
+
+	w = (struct work *) arg;
+
+	mutex_lock(&w->mutex);
+
+	while (true) {
+		if (!w->ready)
+			w->ready = true;
+		r = pthread_cond_wait(&w->cond, &w->mutex.lock);
+		if (r != 0) {
+			printf("(%s)\n", strerror(r));
+			BUG_ON(r);
+		}
+		w->work_cb(w->arg);
+	}
+
+	mutex_unlock(&w->mutex);
+
+	pthread_exit(NULL);
+}
diff --git a/tools/linker-tables/lib/string.c b/tools/linker-tables/lib/string.c
new file mode 100644
index 000000000000..95631c742f1d
--- /dev/null
+++ b/tools/linker-tables/lib/string.c
@@ -0,0 +1,26 @@
+/*
+ *  linux/lib/string.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  Licensed under GPLv2 - taken from linux-next next-20160803
+ */
+
+#include <linux/kernel.h>
+
+/**
+ * memset - Fill a region of memory with the given value
+ * @s: Pointer to the start of the area.
+ * @c: The byte to fill the area with
+ * @count: The size of the area.
+ *
+ * Do not use memset() to access IO space, use memset_io() instead.
+ */
+void *memset(void *s, int c, size_t count)
+{
+	char *xs = s;
+
+	while (count--)
+		*xs++ = c;
+	return s;
+}
diff --git a/tools/linker-tables/main.c b/tools/linker-tables/main.c
new file mode 100644
index 000000000000..c0b1f4c95112
--- /dev/null
+++ b/tools/linker-tables/main.c
@@ -0,0 +1,20 @@
+#include <linux/string.h>
+#include <xen/xen.h>
+#include <asm/x86.h>
+#include <asm/bootparam.h>
+
+struct boot_params boot_params __attribute__((aligned(16)));
+
+int main(int arg, char *argc[])
+{
+	memset(&boot_params, 0, sizeof(struct boot_params));
+
+	if (arg <= 1)
+		startup_64();
+	else {
+		boot_params.hdr.hardware_subarch = X86_SUBARCH_XEN;
+		startup_xen();
+	}
+
+	return 0;
+}
diff --git a/tools/linker-tables/pci-quirks.c b/tools/linker-tables/pci-quirks.c
new file mode 100644
index 000000000000..2cd1116dd0fc
--- /dev/null
+++ b/tools/linker-tables/pci-quirks.c
@@ -0,0 +1,13 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <linux/pci.h>
+
+DEFINE_LINKTABLE_RO(struct pci_fixup, pci_fixup_early);
+
+static void foo_fixup(void) {
+	pr_info("foo_fixup\n");
+};
+
+LINKTABLE_RO(pci_fixup_early, 50) quirk_foo = {
+	.hook = foo_fixup,
+};
diff --git a/tools/linker-tables/pci.c b/tools/linker-tables/pci.c
new file mode 100644
index 000000000000..131b98e1170e
--- /dev/null
+++ b/tools/linker-tables/pci.c
@@ -0,0 +1,29 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <asm/bootparam.h>
+#include <linux/pci.h>
+
+DECLARE_LINKTABLE(struct pci_fixup, pci_fixup_early);
+
+void early_init_pci(void) {
+
+	const struct pci_fixup *fixup;
+	unsigned int tbl_size = LINKTABLE_SIZE(pci_fixup_early);
+
+	pr_info("Initializing pci ...\n");
+
+	pr_info("PCI fixup size: %d\n", tbl_size);
+
+	sleep(1);
+	pr_info("Demo: Using LINKTABLE_FOR_EACH\n");
+	LINKTABLE_FOR_EACH(fixup, pci_fixup_early)
+		fixup->hook();
+
+	pr_info("Demo: Using LINKTABLE_RUN_ALL\n");
+	LINKTABLE_RUN_ALL(pci_fixup_early, hook,);
+
+	pr_info("Completed initializing pci !\n");
+}
+
+x86_init_early_all(early_init_pci);
-- 
2.10.1


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* Re: [PATCH v5 04/14] tables.h: add linker table support
  2016-12-22  2:38       ` Luis R. Rodriguez
  (?)
@ 2016-12-22 13:58         ` Andy Shevchenko
  -1 siblings, 0 replies; 480+ messages in thread
From: Andy Shevchenko @ 2016-12-22 13:58 UTC (permalink / raw)
  To: Luis R. Rodriguez, hpa, acme, tglx, mingo, jpoimboe, bp, npiggin,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm

On Wed, 2016-12-21 at 18:38 -0800, Luis R. Rodriguez wrote:
> 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.




> +/**
> + * 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)				
> \

Hmm... SOMEONE LIKES CAPITAL LETTERS FOR everything, right? :-)

I would expect more standard 
linktable_for_each()
macro

Same to the rest of similar macros.


> +/**
> + * 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 < LINKTABLE_SIZE(tbl); i++)		
> \
> +		err = (LINKTABLE_START(tbl)[i]).func (args);		


> \
> +		err;							

Indentation here a bit confusing.

> \
> +})


-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v5 04/14] tables.h: add linker table support
@ 2016-12-22 13:58         ` Andy Shevchenko
  0 siblings, 0 replies; 480+ messages in thread
From: Andy Shevchenko @ 2016-12-22 13:58 UTC (permalink / raw)
  To: Luis R. Rodriguez, hpa, acme, tglx, mingo, jpoimboe, bp, npiggin,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm

On Wed, 2016-12-21 at 18:38 -0800, Luis R. Rodriguez wrote:
> 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.




> +/**
> + * 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)				
> \

Hmm... SOMEONE LIKES CAPITAL LETTERS FOR everything, right? :-)

I would expect more standard 
linktable_for_each()
macro

Same to the rest of similar macros.


> +/**
> + * 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 < LINKTABLE_SIZE(tbl); i++)		
> \
> +		err = (LINKTABLE_START(tbl)[i]).func (args);		


> \
> +		err;							

Indentation here a bit confusing.

> \
> +})


-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v5 04/14] tables.h: add linker table support
@ 2016-12-22 13:58         ` Andy Shevchenko
  0 siblings, 0 replies; 480+ messages in thread
From: Andy Shevchenko @ 2016-12-22 13:58 UTC (permalink / raw)
  To: Luis R. Rodriguez, hpa, acme, tglx, mingo, jpoimboe, bp, npiggin,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley

On Wed, 2016-12-21 at 18:38 -0800, Luis R. Rodriguez wrote:
> 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.




> +/**
> + * 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)				
> \

Hmm... SOMEONE LIKES CAPITAL LETTERS FOR everything, right? :-)

I would expect more standard 
linktable_for_each()
macro

Same to the rest of similar macros.


> +/**
> + * 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 < LINKTABLE_SIZE(tbl); i++)		
> \
> +		err = (LINKTABLE_START(tbl)[i]).func (args);		


> \
> +		err;							

Indentation here a bit confusing.

> \
> +})


-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v5 09/14] jump_label: port __jump_table to linker tables
  2016-12-22  2:38       ` Luis R. Rodriguez
  (?)
@ 2016-12-22 14:08         ` Andy Shevchenko
  -1 siblings, 0 replies; 480+ messages in thread
From: Andy Shevchenko @ 2016-12-22 14:08 UTC (permalink / raw)
  To: Luis R. Rodriguez, hpa, acme, tglx, mingo, jpoimboe, bp, npiggin,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt

On Wed, 2016-12-21 at 18:38 -0800, Luis R. Rodriguez wrote:
> Move the __jump_table from the a custom section solution
> to a generic solution, this avoiding extra vmlinux.lds.h
> customizations.
> 
> This also demos the use of the .data linker table and of
> the shared asm call push_section_tbl().
> 

>  {
>  	asm_volatile_goto("1:\n\t"
>  		 WASM(nop) "\n\t"
> -		 ".pushsection __jump_table,  \"aw\"\n\t"
> +		 push_section_tbl_any(.data, __jump_table, aw)
>  		 ".word 1b, %l[l_yes], %c0\n\t"
>  		 ".popsection\n\t"
>  		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
> @@ -26,7 +28,7 @@ static __always_inline bool
> arch_static_branch_jump(struct static_key *key, bool
>  {
>  	asm_volatile_goto("1:\n\t"
>  		 WASM(b) " %l[l_yes]\n\t"
> -		 ".pushsection __jump_table,  \"aw\"\n\t"
> +		 push_section_tbl_any(.data, __jump_table, aw)
>  		 ".word 1b, %l[l_yes], %c0\n\t"
>  		 ".popsection\n\t"

Does it make sense to introduce something like

#define pop_section_tbl ".popsection\n\t"
#define pop_section_tbl_any pop_section_tbl

?

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v5 09/14] jump_label: port __jump_table to linker tables
@ 2016-12-22 14:08         ` Andy Shevchenko
  0 siblings, 0 replies; 480+ messages in thread
From: Andy Shevchenko @ 2016-12-22 14:08 UTC (permalink / raw)
  To: Luis R. Rodriguez, hpa, acme, tglx, mingo, jpoimboe, bp, npiggin,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt, ak

On Wed, 2016-12-21 at 18:38 -0800, Luis R. Rodriguez wrote:
> Move the __jump_table from the a custom section solution
> to a generic solution, this avoiding extra vmlinux.lds.h
> customizations.
> 
> This also demos the use of the .data linker table and of
> the shared asm call push_section_tbl().
> 

>  {
>  	asm_volatile_goto("1:\n\t"
>  		 WASM(nop) "\n\t"
> -		 ".pushsection __jump_table,  \"aw\"\n\t"
> +		 push_section_tbl_any(.data, __jump_table, aw)
>  		 ".word 1b, %l[l_yes], %c0\n\t"
>  		 ".popsection\n\t"
>  		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
> @@ -26,7 +28,7 @@ static __always_inline bool
> arch_static_branch_jump(struct static_key *key, bool
>  {
>  	asm_volatile_goto("1:\n\t"
>  		 WASM(b) " %l[l_yes]\n\t"
> -		 ".pushsection __jump_table,  \"aw\"\n\t"
> +		 push_section_tbl_any(.data, __jump_table, aw)
>  		 ".word 1b, %l[l_yes], %c0\n\t"
>  		 ".popsection\n\t"

Does it make sense to introduce something like

#define pop_section_tbl ".popsection\n\t"
#define pop_section_tbl_any pop_section_tbl

?

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v5 09/14] jump_label: port __jump_table to linker tables
@ 2016-12-22 14:08         ` Andy Shevchenko
  0 siblings, 0 replies; 480+ messages in thread
From: Andy Shevchenko @ 2016-12-22 14:08 UTC (permalink / raw)
  To: Luis R. Rodriguez, hpa, acme, tglx, mingo, jpoimboe, bp, npiggin,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley

On Wed, 2016-12-21 at 18:38 -0800, Luis R. Rodriguez wrote:
> Move the __jump_table from the a custom section solution
> to a generic solution, this avoiding extra vmlinux.lds.h
> customizations.
> 
> This also demos the use of the .data linker table and of
> the shared asm call push_section_tbl().
> 

>  {
>  	asm_volatile_goto("1:\n\t"
>  		 WASM(nop) "\n\t"
> -		 ".pushsection __jump_table,  \"aw\"\n\t"
> +		 push_section_tbl_any(.data, __jump_table, aw)
>  		 ".word 1b, %l[l_yes], %c0\n\t"
>  		 ".popsection\n\t"
>  		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
> @@ -26,7 +28,7 @@ static __always_inline bool
> arch_static_branch_jump(struct static_key *key, bool
>  {
>  	asm_volatile_goto("1:\n\t"
>  		 WASM(b) " %l[l_yes]\n\t"
> -		 ".pushsection __jump_table,  \"aw\"\n\t"
> +		 push_section_tbl_any(.data, __jump_table, aw)
>  		 ".word 1b, %l[l_yes], %c0\n\t"
>  		 ".popsection\n\t"

Does it make sense to introduce something like

#define pop_section_tbl ".popsection\n\t"
#define pop_section_tbl_any pop_section_tbl

?

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v5 04/14] tables.h: add linker table support
  2016-12-22 13:58         ` Andy Shevchenko
  (?)
@ 2017-01-03 21:25           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-03 21:25 UTC (permalink / raw)
  To: Andy Shevchenko, hpa
  Cc: Luis R. Rodriguez, acme, tglx, mingo, jpoimboe, bp, npiggin,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, gregkh, rusty, gnomes, alan, dwmw2,
	arnd, ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel

On Thu, Dec 22, 2016 at 03:58:18PM +0200, Andy Shevchenko wrote:
> On Wed, 2016-12-21 at 18:38 -0800, Luis R. Rodriguez wrote:
> > +#define LINKTABLE_FOR_EACH(pointer, tbl)				
> 
> Hmm... SOMEONE LIKES CAPITAL LETTERS FOR everything, right? :-)
>
> I would expect more standard linktable_for_each() macro

hpa had recommended this, if he prefers a lower case I can change that
but I really do consider this bikeshedding.

> Same to the rest of similar macros.

Same answer here.

> > +/**
> > + * 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 < LINKTABLE_SIZE(tbl); i++)		
> > \
> > +		err = (LINKTABLE_START(tbl)[i]).func (args);		
> 
> 
> > \
> > +		err;							
> 
> Indentation here a bit confusing.

Ah yes, good catch, fixed.

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v5 04/14] tables.h: add linker table support
@ 2017-01-03 21:25           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-03 21:25 UTC (permalink / raw)
  To: Andy Shevchenko, hpa
  Cc: Luis R. Rodriguez, acme, tglx, mingo, jpoimboe, bp, npiggin,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, gregkh, rusty, gnomes, alan, dwmw2,
	arnd, ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel

On Thu, Dec 22, 2016 at 03:58:18PM +0200, Andy Shevchenko wrote:
> On Wed, 2016-12-21 at 18:38 -0800, Luis R. Rodriguez wrote:
> > +#define LINKTABLE_FOR_EACH(pointer, tbl)				
> 
> Hmm... SOMEONE LIKES CAPITAL LETTERS FOR everything, right? :-)
>
> I would expect more standard linktable_for_each() macro

hpa had recommended this, if he prefers a lower case I can change that
but I really do consider this bikeshedding.

> Same to the rest of similar macros.

Same answer here.

> > +/**
> > + * 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 < LINKTABLE_SIZE(tbl); i++)		
> > \
> > +		err = (LINKTABLE_START(tbl)[i]).func (args);		
> 
> 
> > \
> > +		err;							
> 
> Indentation here a bit confusing.

Ah yes, good catch, fixed.

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v5 04/14] tables.h: add linker table support
@ 2017-01-03 21:25           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-03 21:25 UTC (permalink / raw)
  To: Andy Shevchenko, hpa
  Cc: Luis R. Rodriguez, acme, tglx, mingo, jpoimboe, bp, npiggin,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, gregkh, rusty, gnomes, alan, dwmw2,
	arnd, ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, paul.gortmaker,
	xen-devel, ak, pali.rohar, dvhart, platform-driver-x86, mmarek,
	linux, jkosina, korea.drzix, linux-kbuild, tony.luck, akpm,
	linux-ia64, linux-arm-kernel, linux-sh, sparclinux,
	catalin.marinas, will.deacon, rostedt, jani.nikula, mchehab,
	markus.heiser, jolsa, msalter, chris, jcmvbkbc, linux-xtensa,
	adrian.hunter, dsahern, namhyung, wangnan0, dmitry.torokhov,
	joro, paulus, mpe, James.Bottomley

On Thu, Dec 22, 2016 at 03:58:18PM +0200, Andy Shevchenko wrote:
> On Wed, 2016-12-21 at 18:38 -0800, Luis R. Rodriguez wrote:
> > +#define LINKTABLE_FOR_EACH(pointer, tbl)				
> 
> Hmm... SOMEONE LIKES CAPITAL LETTERS FOR everything, right? :-)
>
> I would expect more standard linktable_for_each() macro

hpa had recommended this, if he prefers a lower case I can change that
but I really do consider this bikeshedding.

> Same to the rest of similar macros.

Same answer here.

> > +/**
> > + * 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 < LINKTABLE_SIZE(tbl); i++)		
> > \
> > +		err = (LINKTABLE_START(tbl)[i]).func (args);		
> 
> 
> > \
> > +		err;							
> 
> Indentation here a bit confusing.

Ah yes, good catch, fixed.

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v5 09/14] jump_label: port __jump_table to linker tables
  2016-12-22 14:08         ` Andy Shevchenko
  (?)
@ 2017-01-03 21:27           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-03 21:27 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: gnomes, dalias, linux-ia64, jkosina, benh, ming.lei,
	heiko.carstens, platform-driver-x86, James.Bottomley,
	paul.gortmaker, paulus, mpe, hpa, masami.hiramatsu.pt, wangnan0,
	mchehab, linux-arch, markus.heiser, sparclinux, xen-devel, linux,
	linux-sh, will.deacon, korea.drzix, x86, anil.s.keshavamurthy,
	fontana, mingo, dsahern, linux-arm-kernel, catalin.marinas,
	dvhart, dwmw2, linux, david.vrabel, linux-xte

On Thu, Dec 22, 2016 at 04:08:22PM +0200, Andy Shevchenko wrote:
> On Wed, 2016-12-21 at 18:38 -0800, Luis R. Rodriguez wrote:
> > Move the __jump_table from the a custom section solution
> > to a generic solution, this avoiding extra vmlinux.lds.h
> > customizations.
> > 
> > This also demos the use of the .data linker table and of
> > the shared asm call push_section_tbl().
> > 
> 
> >  {
> >  	asm_volatile_goto("1:\n\t"
> >  		 WASM(nop) "\n\t"
> > -		 ".pushsection __jump_table,  \"aw\"\n\t"
> > +		 push_section_tbl_any(.data, __jump_table, aw)
> >  		 ".word 1b, %l[l_yes], %c0\n\t"
> >  		 ".popsection\n\t"
> >  		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
> > @@ -26,7 +28,7 @@ static __always_inline bool
> > arch_static_branch_jump(struct static_key *key, bool
> >  {
> >  	asm_volatile_goto("1:\n\t"
> >  		 WASM(b) " %l[l_yes]\n\t"
> > -		 ".pushsection __jump_table,  \"aw\"\n\t"
> > +		 push_section_tbl_any(.data, __jump_table, aw)
> >  		 ".word 1b, %l[l_yes], %c0\n\t"
> >  		 ".popsection\n\t"
> 
> Does it make sense to introduce something like
> 
> #define pop_section_tbl ".popsection\n\t"
> #define pop_section_tbl_any pop_section_tbl

Absolutely ! However this would be an evolution, and I would much
prefer to add this later as an atomic step later to enable other
users to also be using this shared macro. I did not have an immediate
need for a pop_section_tbl() macro as its not section specific.

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v5 09/14] jump_label: port __jump_table to linker tables
@ 2017-01-03 21:27           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-03 21:27 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: gnomes, dalias, linux-ia64, jkosina, benh, ming.lei,
	heiko.carstens, platform-driver-x86, James.Bottomley,
	paul.gortmaker, paulus, mpe, hpa, masami.hiramatsu.pt, wangnan0,
	mchehab, linux-arch, markus.heiser, sparclinux, xen-devel, linux,
	linux-sh, will.deacon, korea.drzix, x86, anil.s.keshavamurthy,
	fontana, mingo, dsahern, linux-arm-kernel, catalin.marinas,
	dvhart, dwmw2, linux, david.vrabel, linux-xte

On Thu, Dec 22, 2016 at 04:08:22PM +0200, Andy Shevchenko wrote:
> On Wed, 2016-12-21 at 18:38 -0800, Luis R. Rodriguez wrote:
> > Move the __jump_table from the a custom section solution
> > to a generic solution, this avoiding extra vmlinux.lds.h
> > customizations.
> > 
> > This also demos the use of the .data linker table and of
> > the shared asm call push_section_tbl().
> > 
> 
> >  {
> >  	asm_volatile_goto("1:\n\t"
> >  		 WASM(nop) "\n\t"
> > -		 ".pushsection __jump_table,  \"aw\"\n\t"
> > +		 push_section_tbl_any(.data, __jump_table, aw)
> >  		 ".word 1b, %l[l_yes], %c0\n\t"
> >  		 ".popsection\n\t"
> >  		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
> > @@ -26,7 +28,7 @@ static __always_inline bool
> > arch_static_branch_jump(struct static_key *key, bool
> >  {
> >  	asm_volatile_goto("1:\n\t"
> >  		 WASM(b) " %l[l_yes]\n\t"
> > -		 ".pushsection __jump_table,  \"aw\"\n\t"
> > +		 push_section_tbl_any(.data, __jump_table, aw)
> >  		 ".word 1b, %l[l_yes], %c0\n\t"
> >  		 ".popsection\n\t"
> 
> Does it make sense to introduce something like
> 
> #define pop_section_tbl ".popsection\n\t"
> #define pop_section_tbl_any pop_section_tbl

Absolutely ! However this would be an evolution, and I would much
prefer to add this later as an atomic step later to enable other
users to also be using this shared macro. I did not have an immediate
need for a pop_section_tbl() macro as its not section specific.

  Luis

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v5 09/14] jump_label: port __jump_table to linker tables
@ 2017-01-03 21:27           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-03 21:27 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Luis R. Rodriguez, hpa, acme, tglx, mingo, jpoimboe, bp, npiggin,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, gregkh, rusty, gnomes, alan, dwmw2,
	arnd, ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, paul.gortmaker,
	xen-devel, ak, pali.rohar, dvhart, platform-driver-x86, mmarek,
	linux, jkosina, korea.drzix, linux-kbuild, tony.luck, akpm,
	linux-ia64, linux-arm-kernel, linux-sh, sparclinux,
	catalin.marinas, will.deacon, rostedt, jani.nikula, mchehab,
	markus.heiser, jolsa, msalter, chris, jcmvbkbc, linux-xtensa,
	adrian.hunter, dsahern, namhyung, wangnan0, dmitry.torokhov,
	joro, paulus, mpe, James.Bottomley

On Thu, Dec 22, 2016 at 04:08:22PM +0200, Andy Shevchenko wrote:
> On Wed, 2016-12-21 at 18:38 -0800, Luis R. Rodriguez wrote:
> > Move the __jump_table from the a custom section solution
> > to a generic solution, this avoiding extra vmlinux.lds.h
> > customizations.
> > 
> > This also demos the use of the .data linker table and of
> > the shared asm call push_section_tbl().
> > 
> 
> >  {
> >  	asm_volatile_goto("1:\n\t"
> >  		 WASM(nop) "\n\t"
> > -		 ".pushsection __jump_table,  \"aw\"\n\t"
> > +		 push_section_tbl_any(.data, __jump_table, aw)
> >  		 ".word 1b, %l[l_yes], %c0\n\t"
> >  		 ".popsection\n\t"
> >  		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
> > @@ -26,7 +28,7 @@ static __always_inline bool
> > arch_static_branch_jump(struct static_key *key, bool
> >  {
> >  	asm_volatile_goto("1:\n\t"
> >  		 WASM(b) " %l[l_yes]\n\t"
> > -		 ".pushsection __jump_table,  \"aw\"\n\t"
> > +		 push_section_tbl_any(.data, __jump_table, aw)
> >  		 ".word 1b, %l[l_yes], %c0\n\t"
> >  		 ".popsection\n\t"
> 
> Does it make sense to introduce something like
> 
> #define pop_section_tbl ".popsection\n\t"
> #define pop_section_tbl_any pop_section_tbl

Absolutely ! However this would be an evolution, and I would much
prefer to add this later as an atomic step later to enable other
users to also be using this shared macro. I did not have an immediate
need for a pop_section_tbl() macro as its not section specific.

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v5 04/14] tables.h: add linker table support
  2017-01-03 21:25           ` Luis R. Rodriguez
  (?)
  (?)
@ 2017-01-04  9:47           ` Andy Shevchenko
  2017-01-06 20:00             ` Luis R. Rodriguez
  -1 siblings, 1 reply; 480+ messages in thread
From: Andy Shevchenko @ 2017-01-04  9:47 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: One Thousand Gnomes, dalias, linux-ia64, Jiri Kosina,
	Benjamin Herrenschmidt, ming.lei, Heiko Carstens,
	Platform Driver, James Bottomley, Paul Gortmaker, Paul Mackerras,
	Michael Ellerman, H. Peter Anvin, masami.hiramatsu.pt, wangnan0,
	Mauro Carvalho Chehab, Linux-Arch, markus.heiser, sparclinux,
	xen-devel, Russell King, Linux-SH, Will Deacon, korea.drzix, x86

On Tue, Jan 3, 2017 at 11:25 PM, Luis R. Rodriguez <mcgrof@kernel.org> wrote:
> On Thu, Dec 22, 2016 at 03:58:18PM +0200, Andy Shevchenko wrote:
>> On Wed, 2016-12-21 at 18:38 -0800, Luis R. Rodriguez wrote:
>> > +#define LINKTABLE_FOR_EACH(pointer, tbl)
>>
>> Hmm... SOMEONE LIKES CAPITAL LETTERS FOR everything, right? :-)
>>
>> I would expect more standard linktable_for_each() macro
>
> hpa had recommended this, if he prefers a lower case I can change that


> but I really do consider this bikeshedding.

I don't think so:
$ git grep -n FOR_EACH | wc -l
    83
$ git grep -n for_each | wc -l
 23317

-- 
With Best Regards,
Andy Shevchenko

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v5 04/14] tables.h: add linker table support
  2017-01-04  9:47           ` Andy Shevchenko
@ 2017-01-06 20:00             ` Luis R. Rodriguez
  2017-01-06 20:43               ` Andy Shevchenko
  0 siblings, 1 reply; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-06 20:00 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: One Thousand Gnomes, dalias, linux-ia64, Jiri Kosina,
	Benjamin Herrenschmidt, ming.lei, Heiko Carstens,
	Platform Driver, James Bottomley, Paul Gortmaker, Paul Mackerras,
	Michael Ellerman, H. Peter Anvin, masami.hiramatsu.pt, wangnan0,
	Mauro Carvalho Chehab, Linux-Arch, markus.heiser, sparclinux,
	xen-devel, Russell King, Linux-SH, Will Deacon, korea.drzix, x86

On Wed, Jan 04, 2017 at 11:47:14AM +0200, Andy Shevchenko wrote:
> On Tue, Jan 3, 2017 at 11:25 PM, Luis R. Rodriguez <mcgrof@kernel.org> wrote:
> > On Thu, Dec 22, 2016 at 03:58:18PM +0200, Andy Shevchenko wrote:
> >> On Wed, 2016-12-21 at 18:38 -0800, Luis R. Rodriguez wrote:
> >> > +#define LINKTABLE_FOR_EACH(pointer, tbl)
> >>
> >> Hmm... SOMEONE LIKES CAPITAL LETTERS FOR everything, right? :-)
> >>
> >> I would expect more standard linktable_for_each() macro
> >
> > hpa had recommended this, if he prefers a lower case I can change that
> 
> 
> > but I really do consider this bikeshedding.
> 
> I don't think so:
> $ git grep -n FOR_EACH | wc -l
>     83
> $ git grep -n for_each | wc -l
>  23317

OK, would you also prefer if LINKTABLE_RUN_ERR() and LINKTABLE_RUN_ALL()
were lowercase ? Or is that fine ? To be clear I'll leave upper case the
declarers and defines.

  Luis

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v5 04/14] tables.h: add linker table support
  2017-01-06 20:00             ` Luis R. Rodriguez
@ 2017-01-06 20:43               ` Andy Shevchenko
  2017-01-09 14:22                 ` Luis R. Rodriguez
  0 siblings, 1 reply; 480+ messages in thread
From: Andy Shevchenko @ 2017-01-06 20:43 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: One Thousand Gnomes, dalias, linux-ia64, Jiri Kosina,
	Benjamin Herrenschmidt, ming.lei, Heiko Carstens,
	Platform Driver, James Bottomley, Paul Gortmaker, Paul Mackerras,
	Michael Ellerman, H. Peter Anvin, sparclinux, wangnan0,
	Mauro Carvalho Chehab, Linux-Arch, markus.heiser, xen-devel,
	Russell King, Linux-SH, Will Deacon, korea.drzix, x86, anil

On Fri, Jan 6, 2017 at 10:00 PM, Luis R. Rodriguez <mcgrof@kernel.org> wrote:
> On Wed, Jan 04, 2017 at 11:47:14AM +0200, Andy Shevchenko wrote:
>> On Tue, Jan 3, 2017 at 11:25 PM, Luis R. Rodriguez <mcgrof@kernel.org> wrote:
>> > On Thu, Dec 22, 2016 at 03:58:18PM +0200, Andy Shevchenko wrote:
>> >> On Wed, 2016-12-21 at 18:38 -0800, Luis R. Rodriguez wrote:
>> >> > +#define LINKTABLE_FOR_EACH(pointer, tbl)
>> >>
>> >> Hmm... SOMEONE LIKES CAPITAL LETTERS FOR everything, right? :-)
>> >>
>> >> I would expect more standard linktable_for_each() macro
>> >
>> > hpa had recommended this, if he prefers a lower case I can change that
>>
>>
>> > but I really do consider this bikeshedding.
>>
>> I don't think so:
>> $ git grep -n FOR_EACH | wc -l
>>     83
>> $ git grep -n for_each | wc -l
>>  23317
>
> OK, would you also prefer if LINKTABLE_RUN_ERR() and LINKTABLE_RUN_ALL()
> were lowercase ? Or is that fine ? To be clear I'll leave upper case the
> declarers and defines.

My understanding that macros to run code -- lower case, definitions --
upper case.

Thus, *_run_*() macros to lower.

-- 
With Best Regards,
Andy Shevchenko

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v5 04/14] tables.h: add linker table support
  2017-01-06 20:43               ` Andy Shevchenko
@ 2017-01-09 14:22                 ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:22 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: One Thousand Gnomes, dalias, linux-ia64, Jiri Kosina,
	Benjamin Herrenschmidt, ming.lei, Heiko Carstens,
	Platform Driver, James Bottomley, Paul Gortmaker, Paul Mackerras,
	Michael Ellerman, H. Peter Anvin, sparclinux, wangnan0,
	Mauro Carvalho Chehab, Linux-Arch, markus.heiser, xen-devel,
	Russell King, Linux-SH, Will Deacon, korea.drzix, x86, anil

On Fri, Jan 06, 2017 at 10:43:59PM +0200, Andy Shevchenko wrote:
> On Fri, Jan 6, 2017 at 10:00 PM, Luis R. Rodriguez <mcgrof@kernel.org> wrote:
> > On Wed, Jan 04, 2017 at 11:47:14AM +0200, Andy Shevchenko wrote:
> >> On Tue, Jan 3, 2017 at 11:25 PM, Luis R. Rodriguez <mcgrof@kernel.org> wrote:
> >> > On Thu, Dec 22, 2016 at 03:58:18PM +0200, Andy Shevchenko wrote:
> >> >> On Wed, 2016-12-21 at 18:38 -0800, Luis R. Rodriguez wrote:
> >> >> > +#define LINKTABLE_FOR_EACH(pointer, tbl)
> >> >>
> >> >> Hmm... SOMEONE LIKES CAPITAL LETTERS FOR everything, right? :-)
> >> >>
> >> >> I would expect more standard linktable_for_each() macro
> >> >
> >> > hpa had recommended this, if he prefers a lower case I can change that
> >>
> >>
> >> > but I really do consider this bikeshedding.
> >>
> >> I don't think so:
> >> $ git grep -n FOR_EACH | wc -l
> >>     83
> >> $ git grep -n for_each | wc -l
> >>  23317
> >
> > OK, would you also prefer if LINKTABLE_RUN_ERR() and LINKTABLE_RUN_ALL()
> > were lowercase ? Or is that fine ? To be clear I'll leave upper case the
> > declarers and defines.
> 
> My understanding that macros to run code -- lower case, definitions --
> upper case.
> 
> Thus, *_run_*() macros to lower.

Very well, I've changed these, and since there were users I had to change
a bit of the other patches so will send a v6 series follow up.

  Luis

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v6 00/14] linux: generalize sections, ranges and linker tables
  2016-12-22  2:37     ` Luis R. Rodriguez
  (?)
@ 2017-01-09 14:58       ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This v6 addresses Andy Shevchenko's feedback from the v5 series [0] to use
lowercase on a few of the tables.h macros. No other changes have been done to
this series. As I had mentioned on the last cover-letter the v5 series had
gone through a lot of testing both compile and run time, with the linktable
test driver forced-enabled as a debug measure to try to capture errors as
many architectures as possible:

    alpha      arc        arcv2       arm       arm64       blackfin    c6x                                                                                                     
    cris       crisv32    frv         h8300     hexagon     i386        ia64                                                                                                    
    m32r       m68k       m68k_nommu  metag     microblaze  mips_22     mips_24                                                                                                 
    mips_25    mn10300    nios2       openrisc  parisc      parisc64    powerpc                                                                                                 
    s390       score      sh          sparc32   sparc64     tile        um                                                                                                      
    unicore32  x86_64     xtensa                                                                                                                                                

The only architecture that was not tested was avr32 and that is because
linux-next fails to compile on it. I'd like to greatly thank Guenter Roeck for
his help with testing.

The debug patch which force enables the test driver is not submitted for
upstream inclusion but is kept as part of the public tree for those curious,
its the last patch [1]. This tree is based on linux-next tag next-20170109.

[0] https://lkml.kernel.org/r/20161222023811.21246-1-mcgrof@kernel.org
[1] https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h 170109-linker-tables-v6

Luis R. Rodriguez (14):
  generic-sections: add section core helpers
  xtensa: skip adding literal when SORT() is used
  ranges.h: add helpers to build and identify Linux section ranges
  tables.h: add linker table support
  kbuild: enable option to force compile force-obj-y and force-lib-y
  firmware/Makefile: force recompilation if makefile changes
  firmware: port built-in section to linker table
  jump_label: move guard #endif down where it belongs
  jump_label: port __jump_table to linker tables
  dynamic_debug: port to use linker tables
  kprobes: move kprobe declarations to asm-generic/kprobes.h
  kprobes: port .kprobes.text to section range
  kprobes: port blacklist kprobes to linker table
  lib: add linker tables test driver

 Documentation/index.rst                   |   1 +
 Documentation/kbuild/makefiles.txt        |  36 ++
 Documentation/sections/background.rst     | 105 ++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  19 +
 Documentation/sections/linker-tables.rst  | 227 +++++++++
 Documentation/sections/ranges.rst         |  74 +++
 Documentation/sections/section-core.rst   | 153 ++++++
 MAINTAINERS                               |  32 ++
 arch/alpha/include/asm/Kbuild             |   4 +
 arch/arc/include/asm/Kbuild               |   3 +
 arch/arc/include/asm/kprobes.h            |   6 +-
 arch/arc/kernel/vmlinux.lds.S             |   1 -
 arch/arm/include/asm/Kbuild               |   3 +
 arch/arm/include/asm/jump_label.h         |   6 +-
 arch/arm/include/asm/kprobes.h            |   4 +
 arch/arm/kernel/entry-armv.S              |   3 +-
 arch/arm/kernel/vmlinux-xip.lds.S         |   1 -
 arch/arm/kernel/vmlinux.lds.S             |   1 -
 arch/arm/probes/decode.h                  |   1 +
 arch/arm64/include/asm/Kbuild             |   3 +
 arch/arm64/include/asm/jump_label.h       |   6 +-
 arch/arm64/include/asm/kprobes.h          |   4 +
 arch/arm64/kernel/armv8_deprecated.c      |   1 +
 arch/arm64/kernel/insn.c                  |   1 +
 arch/arm64/kernel/probes/decode-insn.h    |   2 +
 arch/arm64/kernel/probes/kprobes.c        |   4 +-
 arch/arm64/kernel/vmlinux.lds.S           |   1 -
 arch/avr32/include/asm/Kbuild             |   3 +
 arch/avr32/include/asm/kprobes.h          |   7 +-
 arch/avr32/kernel/entry-avr32b.S          |  13 +-
 arch/avr32/kernel/vmlinux.lds.S           |   1 -
 arch/blackfin/include/asm/Kbuild          |   4 +
 arch/blackfin/kernel/vmlinux.lds.S        |   1 -
 arch/c6x/include/asm/Kbuild               |   3 +
 arch/c6x/include/asm/tables.h             |  26 +
 arch/c6x/kernel/vmlinux.lds.S             |   1 -
 arch/cris/include/asm/Kbuild              |   4 +
 arch/frv/include/asm/Kbuild               |   4 +
 arch/h8300/include/asm/Kbuild             |   4 +
 arch/hexagon/include/asm/Kbuild           |   4 +
 arch/hexagon/kernel/vmlinux.lds.S         |   1 -
 arch/ia64/include/asm/Kbuild              |   3 +
 arch/ia64/include/asm/kprobes.h           |  12 +-
 arch/ia64/kernel/jprobes.S                |   3 +-
 arch/ia64/kernel/vmlinux.lds.S            |   1 -
 arch/ia64/lib/flush.S                     |   6 +-
 arch/m32r/include/asm/Kbuild              |   4 +
 arch/m68k/include/asm/Kbuild              |   4 +
 arch/metag/include/asm/Kbuild             |   4 +
 arch/metag/kernel/vmlinux.lds.S           |   1 -
 arch/microblaze/include/asm/Kbuild        |   4 +
 arch/microblaze/kernel/vmlinux.lds.S      |   1 -
 arch/mips/include/asm/Kbuild              |   3 +
 arch/mips/include/asm/jump_label.h        |   6 +-
 arch/mips/include/asm/kprobes.h           |   6 +-
 arch/mips/kernel/vmlinux.lds.S            |   1 -
 arch/mn10300/include/asm/Kbuild           |   3 +
 arch/mn10300/include/asm/kprobes.h        |   7 +-
 arch/mn10300/kernel/vmlinux.lds.S         |   1 -
 arch/nios2/include/asm/Kbuild             |   4 +
 arch/nios2/kernel/vmlinux.lds.S           |   1 -
 arch/openrisc/include/asm/Kbuild          |   4 +
 arch/openrisc/kernel/vmlinux.lds.S        |   1 -
 arch/parisc/include/asm/Kbuild            |   4 +
 arch/parisc/kernel/vmlinux.lds.S          |   1 -
 arch/powerpc/include/asm/Kbuild           |   3 +
 arch/powerpc/include/asm/jump_label.h     |   8 +-
 arch/powerpc/include/asm/kprobes.h        |   3 +
 arch/powerpc/include/asm/ppc_asm.h        |   3 +-
 arch/powerpc/kernel/vmlinux.lds.S         |   3 +-
 arch/s390/include/asm/Kbuild              |   3 +
 arch/s390/include/asm/jump_label.h        |   6 +-
 arch/s390/include/asm/kprobes.h           |   7 +-
 arch/s390/kernel/entry.S                  |   5 +-
 arch/s390/kernel/kprobes.c                |   6 +-
 arch/s390/kernel/mcount.S                 |   3 +-
 arch/s390/kernel/vmlinux.lds.S            |   1 -
 arch/score/include/asm/Kbuild             |   4 +
 arch/score/kernel/vmlinux.lds.S           |   1 -
 arch/sh/include/asm/Kbuild                |   3 +
 arch/sh/include/asm/kprobes.h             |   5 +-
 arch/sh/kernel/vmlinux.lds.S              |   1 -
 arch/sparc/include/asm/Kbuild             |   3 +
 arch/sparc/include/asm/jump_label.h       |   6 +-
 arch/sparc/include/asm/kprobes.h          |  10 +-
 arch/sparc/kernel/vmlinux.lds.S           |   1 -
 arch/sparc/mm/ultra.S                     |   3 +-
 arch/tile/include/asm/Kbuild              |   3 +
 arch/tile/include/asm/jump_label.h        |   5 +-
 arch/tile/include/asm/kprobes.h           |   6 +-
 arch/tile/kernel/vmlinux.lds.S            |   1 -
 arch/um/include/asm/Kbuild                |   4 +
 arch/unicore32/include/asm/Kbuild         |   3 +
 arch/unicore32/include/asm/section-core.h |  19 +
 arch/x86/include/asm/Kbuild               |   3 +
 arch/x86/include/asm/asm.h                |   4 +-
 arch/x86/include/asm/jump_label.h         |  10 +-
 arch/x86/include/asm/kprobes.h            |   9 +-
 arch/x86/kernel/cpu/microcode/core.c      |   8 +-
 arch/x86/kernel/kprobes/core.c            |  11 +-
 arch/x86/kernel/vmlinux.lds.S             |   1 -
 arch/x86/tools/relocs.c                   |   4 +
 arch/xtensa/include/asm/Kbuild            |   4 +
 arch/xtensa/kernel/Makefile               |   8 +-
 drivers/base/firmware_class.c             |  12 +-
 firmware/Makefile                         |   6 +-
 include/asm-generic/kprobes.h             |  26 +
 include/asm-generic/ranges.h              |  93 ++++
 include/asm-generic/section-core.h        | 348 +++++++++++++
 include/asm-generic/sections.h            |   4 +-
 include/asm-generic/tables.h              |  48 ++
 include/asm-generic/vmlinux.lds.h         |  47 +-
 include/linux/compiler.h                  |   8 -
 include/linux/dynamic_debug.h             |   5 +-
 include/linux/init.h                      |  89 +++-
 include/linux/jump_label.h                |   8 +-
 include/linux/kprobes.h                   |  24 +-
 include/linux/ranges.h                    | 183 +++++++
 include/linux/sections.h                  |  87 ++++
 include/linux/tables.h                    | 683 +++++++++++++++++++++++++
 init/Kconfig                              |  22 +
 kernel/jump_label.c                       |  17 +-
 kernel/kprobes.c                          |  17 +-
 lib/Kconfig.debug                         |   6 +
 lib/Makefile                              |   1 +
 lib/dynamic_debug.c                       |  13 +-
 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 ++
 scripts/Makefile.build                    |   7 +-
 scripts/Makefile.clean                    |   2 +
 scripts/Makefile.lib                      |  11 +
 scripts/mod/modpost.c                     |   2 +-
 scripts/module-common.lds                 |   2 +
 scripts/recordmcount.c                    |   2 +-
 scripts/recordmcount.pl                   |   2 +-
 tools/objtool/special.c                   |   2 +-
 143 files changed, 3632 insertions(+), 200 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/linker-tables.rst
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/c6x/include/asm/tables.h
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/kprobes.h
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/asm-generic/tables.h
 create mode 100644 include/linux/ranges.h
 create mode 100644 include/linux/sections.h
 create mode 100644 include/linux/tables.h
 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

-- 
2.11.0


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v6 00/14] linux: generalize sections, ranges and linker tables
@ 2017-01-09 14:58       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This v6 addresses Andy Shevchenko's feedback from the v5 series [0] to use
lowercase on a few of the tables.h macros. No other changes have been done to
this series. As I had mentioned on the last cover-letter the v5 series had
gone through a lot of testing both compile and run time, with the linktable
test driver forced-enabled as a debug measure to try to capture errors as
many architectures as possible:

    alpha      arc        arcv2       arm       arm64       blackfin    c6x                                                                                                     
    cris       crisv32    frv         h8300     hexagon     i386        ia64                                                                                                    
    m32r       m68k       m68k_nommu  metag     microblaze  mips_22     mips_24                                                                                                 
    mips_25    mn10300    nios2       openrisc  parisc      parisc64    powerpc                                                                                                 
    s390       score      sh          sparc32   sparc64     tile        um                                                                                                      
    unicore32  x86_64     xtensa                                                                                                                                                

The only architecture that was not tested was avr32 and that is because
linux-next fails to compile on it. I'd like to greatly thank Guenter Roeck for
his help with testing.

The debug patch which force enables the test driver is not submitted for
upstream inclusion but is kept as part of the public tree for those curious,
its the last patch [1]. This tree is based on linux-next tag next-20170109.

[0] https://lkml.kernel.org/r/20161222023811.21246-1-mcgrof@kernel.org
[1] https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h=20170109-linker-tables-v6

Luis R. Rodriguez (14):
  generic-sections: add section core helpers
  xtensa: skip adding literal when SORT() is used
  ranges.h: add helpers to build and identify Linux section ranges
  tables.h: add linker table support
  kbuild: enable option to force compile force-obj-y and force-lib-y
  firmware/Makefile: force recompilation if makefile changes
  firmware: port built-in section to linker table
  jump_label: move guard #endif down where it belongs
  jump_label: port __jump_table to linker tables
  dynamic_debug: port to use linker tables
  kprobes: move kprobe declarations to asm-generic/kprobes.h
  kprobes: port .kprobes.text to section range
  kprobes: port blacklist kprobes to linker table
  lib: add linker tables test driver

 Documentation/index.rst                   |   1 +
 Documentation/kbuild/makefiles.txt        |  36 ++
 Documentation/sections/background.rst     | 105 ++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  19 +
 Documentation/sections/linker-tables.rst  | 227 +++++++++
 Documentation/sections/ranges.rst         |  74 +++
 Documentation/sections/section-core.rst   | 153 ++++++
 MAINTAINERS                               |  32 ++
 arch/alpha/include/asm/Kbuild             |   4 +
 arch/arc/include/asm/Kbuild               |   3 +
 arch/arc/include/asm/kprobes.h            |   6 +-
 arch/arc/kernel/vmlinux.lds.S             |   1 -
 arch/arm/include/asm/Kbuild               |   3 +
 arch/arm/include/asm/jump_label.h         |   6 +-
 arch/arm/include/asm/kprobes.h            |   4 +
 arch/arm/kernel/entry-armv.S              |   3 +-
 arch/arm/kernel/vmlinux-xip.lds.S         |   1 -
 arch/arm/kernel/vmlinux.lds.S             |   1 -
 arch/arm/probes/decode.h                  |   1 +
 arch/arm64/include/asm/Kbuild             |   3 +
 arch/arm64/include/asm/jump_label.h       |   6 +-
 arch/arm64/include/asm/kprobes.h          |   4 +
 arch/arm64/kernel/armv8_deprecated.c      |   1 +
 arch/arm64/kernel/insn.c                  |   1 +
 arch/arm64/kernel/probes/decode-insn.h    |   2 +
 arch/arm64/kernel/probes/kprobes.c        |   4 +-
 arch/arm64/kernel/vmlinux.lds.S           |   1 -
 arch/avr32/include/asm/Kbuild             |   3 +
 arch/avr32/include/asm/kprobes.h          |   7 +-
 arch/avr32/kernel/entry-avr32b.S          |  13 +-
 arch/avr32/kernel/vmlinux.lds.S           |   1 -
 arch/blackfin/include/asm/Kbuild          |   4 +
 arch/blackfin/kernel/vmlinux.lds.S        |   1 -
 arch/c6x/include/asm/Kbuild               |   3 +
 arch/c6x/include/asm/tables.h             |  26 +
 arch/c6x/kernel/vmlinux.lds.S             |   1 -
 arch/cris/include/asm/Kbuild              |   4 +
 arch/frv/include/asm/Kbuild               |   4 +
 arch/h8300/include/asm/Kbuild             |   4 +
 arch/hexagon/include/asm/Kbuild           |   4 +
 arch/hexagon/kernel/vmlinux.lds.S         |   1 -
 arch/ia64/include/asm/Kbuild              |   3 +
 arch/ia64/include/asm/kprobes.h           |  12 +-
 arch/ia64/kernel/jprobes.S                |   3 +-
 arch/ia64/kernel/vmlinux.lds.S            |   1 -
 arch/ia64/lib/flush.S                     |   6 +-
 arch/m32r/include/asm/Kbuild              |   4 +
 arch/m68k/include/asm/Kbuild              |   4 +
 arch/metag/include/asm/Kbuild             |   4 +
 arch/metag/kernel/vmlinux.lds.S           |   1 -
 arch/microblaze/include/asm/Kbuild        |   4 +
 arch/microblaze/kernel/vmlinux.lds.S      |   1 -
 arch/mips/include/asm/Kbuild              |   3 +
 arch/mips/include/asm/jump_label.h        |   6 +-
 arch/mips/include/asm/kprobes.h           |   6 +-
 arch/mips/kernel/vmlinux.lds.S            |   1 -
 arch/mn10300/include/asm/Kbuild           |   3 +
 arch/mn10300/include/asm/kprobes.h        |   7 +-
 arch/mn10300/kernel/vmlinux.lds.S         |   1 -
 arch/nios2/include/asm/Kbuild             |   4 +
 arch/nios2/kernel/vmlinux.lds.S           |   1 -
 arch/openrisc/include/asm/Kbuild          |   4 +
 arch/openrisc/kernel/vmlinux.lds.S        |   1 -
 arch/parisc/include/asm/Kbuild            |   4 +
 arch/parisc/kernel/vmlinux.lds.S          |   1 -
 arch/powerpc/include/asm/Kbuild           |   3 +
 arch/powerpc/include/asm/jump_label.h     |   8 +-
 arch/powerpc/include/asm/kprobes.h        |   3 +
 arch/powerpc/include/asm/ppc_asm.h        |   3 +-
 arch/powerpc/kernel/vmlinux.lds.S         |   3 +-
 arch/s390/include/asm/Kbuild              |   3 +
 arch/s390/include/asm/jump_label.h        |   6 +-
 arch/s390/include/asm/kprobes.h           |   7 +-
 arch/s390/kernel/entry.S                  |   5 +-
 arch/s390/kernel/kprobes.c                |   6 +-
 arch/s390/kernel/mcount.S                 |   3 +-
 arch/s390/kernel/vmlinux.lds.S            |   1 -
 arch/score/include/asm/Kbuild             |   4 +
 arch/score/kernel/vmlinux.lds.S           |   1 -
 arch/sh/include/asm/Kbuild                |   3 +
 arch/sh/include/asm/kprobes.h             |   5 +-
 arch/sh/kernel/vmlinux.lds.S              |   1 -
 arch/sparc/include/asm/Kbuild             |   3 +
 arch/sparc/include/asm/jump_label.h       |   6 +-
 arch/sparc/include/asm/kprobes.h          |  10 +-
 arch/sparc/kernel/vmlinux.lds.S           |   1 -
 arch/sparc/mm/ultra.S                     |   3 +-
 arch/tile/include/asm/Kbuild              |   3 +
 arch/tile/include/asm/jump_label.h        |   5 +-
 arch/tile/include/asm/kprobes.h           |   6 +-
 arch/tile/kernel/vmlinux.lds.S            |   1 -
 arch/um/include/asm/Kbuild                |   4 +
 arch/unicore32/include/asm/Kbuild         |   3 +
 arch/unicore32/include/asm/section-core.h |  19 +
 arch/x86/include/asm/Kbuild               |   3 +
 arch/x86/include/asm/asm.h                |   4 +-
 arch/x86/include/asm/jump_label.h         |  10 +-
 arch/x86/include/asm/kprobes.h            |   9 +-
 arch/x86/kernel/cpu/microcode/core.c      |   8 +-
 arch/x86/kernel/kprobes/core.c            |  11 +-
 arch/x86/kernel/vmlinux.lds.S             |   1 -
 arch/x86/tools/relocs.c                   |   4 +
 arch/xtensa/include/asm/Kbuild            |   4 +
 arch/xtensa/kernel/Makefile               |   8 +-
 drivers/base/firmware_class.c             |  12 +-
 firmware/Makefile                         |   6 +-
 include/asm-generic/kprobes.h             |  26 +
 include/asm-generic/ranges.h              |  93 ++++
 include/asm-generic/section-core.h        | 348 +++++++++++++
 include/asm-generic/sections.h            |   4 +-
 include/asm-generic/tables.h              |  48 ++
 include/asm-generic/vmlinux.lds.h         |  47 +-
 include/linux/compiler.h                  |   8 -
 include/linux/dynamic_debug.h             |   5 +-
 include/linux/init.h                      |  89 +++-
 include/linux/jump_label.h                |   8 +-
 include/linux/kprobes.h                   |  24 +-
 include/linux/ranges.h                    | 183 +++++++
 include/linux/sections.h                  |  87 ++++
 include/linux/tables.h                    | 683 +++++++++++++++++++++++++
 init/Kconfig                              |  22 +
 kernel/jump_label.c                       |  17 +-
 kernel/kprobes.c                          |  17 +-
 lib/Kconfig.debug                         |   6 +
 lib/Makefile                              |   1 +
 lib/dynamic_debug.c                       |  13 +-
 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 ++
 scripts/Makefile.build                    |   7 +-
 scripts/Makefile.clean                    |   2 +
 scripts/Makefile.lib                      |  11 +
 scripts/mod/modpost.c                     |   2 +-
 scripts/module-common.lds                 |   2 +
 scripts/recordmcount.c                    |   2 +-
 scripts/recordmcount.pl                   |   2 +-
 tools/objtool/special.c                   |   2 +-
 143 files changed, 3632 insertions(+), 200 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/linker-tables.rst
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/c6x/include/asm/tables.h
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/kprobes.h
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/asm-generic/tables.h
 create mode 100644 include/linux/ranges.h
 create mode 100644 include/linux/sections.h
 create mode 100644 include/linux/tables.h
 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

-- 
2.11.0

^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v6 00/14] linux: generalize sections, ranges and linker tables
@ 2017-01-09 14:58       ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

This v6 addresses Andy Shevchenko's feedback from the v5 series [0] to use
lowercase on a few of the tables.h macros. No other changes have been done to
this series. As I had mentioned on the last cover-letter the v5 series had
gone through a lot of testing both compile and run time, with the linktable
test driver forced-enabled as a debug measure to try to capture errors as
many architectures as possible:

    alpha      arc        arcv2       arm       arm64       blackfin    c6x                                                                                                     
    cris       crisv32    frv         h8300     hexagon     i386        ia64                                                                                                    
    m32r       m68k       m68k_nommu  metag     microblaze  mips_22     mips_24                                                                                                 
    mips_25    mn10300    nios2       openrisc  parisc      parisc64    powerpc                                                                                                 
    s390       score      sh          sparc32   sparc64     tile        um                                                                                                      
    unicore32  x86_64     xtensa                                                                                                                                                

The only architecture that was not tested was avr32 and that is because
linux-next fails to compile on it. I'd like to greatly thank Guenter Roeck for
his help with testing.

The debug patch which force enables the test driver is not submitted for
upstream inclusion but is kept as part of the public tree for those curious,
its the last patch [1]. This tree is based on linux-next tag next-20170109.

[0] https://lkml.kernel.org/r/20161222023811.21246-1-mcgrof@kernel.org
[1] https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h=20170109-linker-tables-v6

Luis R. Rodriguez (14):
  generic-sections: add section core helpers
  xtensa: skip adding literal when SORT() is used
  ranges.h: add helpers to build and identify Linux section ranges
  tables.h: add linker table support
  kbuild: enable option to force compile force-obj-y and force-lib-y
  firmware/Makefile: force recompilation if makefile changes
  firmware: port built-in section to linker table
  jump_label: move guard #endif down where it belongs
  jump_label: port __jump_table to linker tables
  dynamic_debug: port to use linker tables
  kprobes: move kprobe declarations to asm-generic/kprobes.h
  kprobes: port .kprobes.text to section range
  kprobes: port blacklist kprobes to linker table
  lib: add linker tables test driver

 Documentation/index.rst                   |   1 +
 Documentation/kbuild/makefiles.txt        |  36 ++
 Documentation/sections/background.rst     | 105 ++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  19 +
 Documentation/sections/linker-tables.rst  | 227 +++++++++
 Documentation/sections/ranges.rst         |  74 +++
 Documentation/sections/section-core.rst   | 153 ++++++
 MAINTAINERS                               |  32 ++
 arch/alpha/include/asm/Kbuild             |   4 +
 arch/arc/include/asm/Kbuild               |   3 +
 arch/arc/include/asm/kprobes.h            |   6 +-
 arch/arc/kernel/vmlinux.lds.S             |   1 -
 arch/arm/include/asm/Kbuild               |   3 +
 arch/arm/include/asm/jump_label.h         |   6 +-
 arch/arm/include/asm/kprobes.h            |   4 +
 arch/arm/kernel/entry-armv.S              |   3 +-
 arch/arm/kernel/vmlinux-xip.lds.S         |   1 -
 arch/arm/kernel/vmlinux.lds.S             |   1 -
 arch/arm/probes/decode.h                  |   1 +
 arch/arm64/include/asm/Kbuild             |   3 +
 arch/arm64/include/asm/jump_label.h       |   6 +-
 arch/arm64/include/asm/kprobes.h          |   4 +
 arch/arm64/kernel/armv8_deprecated.c      |   1 +
 arch/arm64/kernel/insn.c                  |   1 +
 arch/arm64/kernel/probes/decode-insn.h    |   2 +
 arch/arm64/kernel/probes/kprobes.c        |   4 +-
 arch/arm64/kernel/vmlinux.lds.S           |   1 -
 arch/avr32/include/asm/Kbuild             |   3 +
 arch/avr32/include/asm/kprobes.h          |   7 +-
 arch/avr32/kernel/entry-avr32b.S          |  13 +-
 arch/avr32/kernel/vmlinux.lds.S           |   1 -
 arch/blackfin/include/asm/Kbuild          |   4 +
 arch/blackfin/kernel/vmlinux.lds.S        |   1 -
 arch/c6x/include/asm/Kbuild               |   3 +
 arch/c6x/include/asm/tables.h             |  26 +
 arch/c6x/kernel/vmlinux.lds.S             |   1 -
 arch/cris/include/asm/Kbuild              |   4 +
 arch/frv/include/asm/Kbuild               |   4 +
 arch/h8300/include/asm/Kbuild             |   4 +
 arch/hexagon/include/asm/Kbuild           |   4 +
 arch/hexagon/kernel/vmlinux.lds.S         |   1 -
 arch/ia64/include/asm/Kbuild              |   3 +
 arch/ia64/include/asm/kprobes.h           |  12 +-
 arch/ia64/kernel/jprobes.S                |   3 +-
 arch/ia64/kernel/vmlinux.lds.S            |   1 -
 arch/ia64/lib/flush.S                     |   6 +-
 arch/m32r/include/asm/Kbuild              |   4 +
 arch/m68k/include/asm/Kbuild              |   4 +
 arch/metag/include/asm/Kbuild             |   4 +
 arch/metag/kernel/vmlinux.lds.S           |   1 -
 arch/microblaze/include/asm/Kbuild        |   4 +
 arch/microblaze/kernel/vmlinux.lds.S      |   1 -
 arch/mips/include/asm/Kbuild              |   3 +
 arch/mips/include/asm/jump_label.h        |   6 +-
 arch/mips/include/asm/kprobes.h           |   6 +-
 arch/mips/kernel/vmlinux.lds.S            |   1 -
 arch/mn10300/include/asm/Kbuild           |   3 +
 arch/mn10300/include/asm/kprobes.h        |   7 +-
 arch/mn10300/kernel/vmlinux.lds.S         |   1 -
 arch/nios2/include/asm/Kbuild             |   4 +
 arch/nios2/kernel/vmlinux.lds.S           |   1 -
 arch/openrisc/include/asm/Kbuild          |   4 +
 arch/openrisc/kernel/vmlinux.lds.S        |   1 -
 arch/parisc/include/asm/Kbuild            |   4 +
 arch/parisc/kernel/vmlinux.lds.S          |   1 -
 arch/powerpc/include/asm/Kbuild           |   3 +
 arch/powerpc/include/asm/jump_label.h     |   8 +-
 arch/powerpc/include/asm/kprobes.h        |   3 +
 arch/powerpc/include/asm/ppc_asm.h        |   3 +-
 arch/powerpc/kernel/vmlinux.lds.S         |   3 +-
 arch/s390/include/asm/Kbuild              |   3 +
 arch/s390/include/asm/jump_label.h        |   6 +-
 arch/s390/include/asm/kprobes.h           |   7 +-
 arch/s390/kernel/entry.S                  |   5 +-
 arch/s390/kernel/kprobes.c                |   6 +-
 arch/s390/kernel/mcount.S                 |   3 +-
 arch/s390/kernel/vmlinux.lds.S            |   1 -
 arch/score/include/asm/Kbuild             |   4 +
 arch/score/kernel/vmlinux.lds.S           |   1 -
 arch/sh/include/asm/Kbuild                |   3 +
 arch/sh/include/asm/kprobes.h             |   5 +-
 arch/sh/kernel/vmlinux.lds.S              |   1 -
 arch/sparc/include/asm/Kbuild             |   3 +
 arch/sparc/include/asm/jump_label.h       |   6 +-
 arch/sparc/include/asm/kprobes.h          |  10 +-
 arch/sparc/kernel/vmlinux.lds.S           |   1 -
 arch/sparc/mm/ultra.S                     |   3 +-
 arch/tile/include/asm/Kbuild              |   3 +
 arch/tile/include/asm/jump_label.h        |   5 +-
 arch/tile/include/asm/kprobes.h           |   6 +-
 arch/tile/kernel/vmlinux.lds.S            |   1 -
 arch/um/include/asm/Kbuild                |   4 +
 arch/unicore32/include/asm/Kbuild         |   3 +
 arch/unicore32/include/asm/section-core.h |  19 +
 arch/x86/include/asm/Kbuild               |   3 +
 arch/x86/include/asm/asm.h                |   4 +-
 arch/x86/include/asm/jump_label.h         |  10 +-
 arch/x86/include/asm/kprobes.h            |   9 +-
 arch/x86/kernel/cpu/microcode/core.c      |   8 +-
 arch/x86/kernel/kprobes/core.c            |  11 +-
 arch/x86/kernel/vmlinux.lds.S             |   1 -
 arch/x86/tools/relocs.c                   |   4 +
 arch/xtensa/include/asm/Kbuild            |   4 +
 arch/xtensa/kernel/Makefile               |   8 +-
 drivers/base/firmware_class.c             |  12 +-
 firmware/Makefile                         |   6 +-
 include/asm-generic/kprobes.h             |  26 +
 include/asm-generic/ranges.h              |  93 ++++
 include/asm-generic/section-core.h        | 348 +++++++++++++
 include/asm-generic/sections.h            |   4 +-
 include/asm-generic/tables.h              |  48 ++
 include/asm-generic/vmlinux.lds.h         |  47 +-
 include/linux/compiler.h                  |   8 -
 include/linux/dynamic_debug.h             |   5 +-
 include/linux/init.h                      |  89 +++-
 include/linux/jump_label.h                |   8 +-
 include/linux/kprobes.h                   |  24 +-
 include/linux/ranges.h                    | 183 +++++++
 include/linux/sections.h                  |  87 ++++
 include/linux/tables.h                    | 683 +++++++++++++++++++++++++
 init/Kconfig                              |  22 +
 kernel/jump_label.c                       |  17 +-
 kernel/kprobes.c                          |  17 +-
 lib/Kconfig.debug                         |   6 +
 lib/Makefile                              |   1 +
 lib/dynamic_debug.c                       |  13 +-
 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 ++
 scripts/Makefile.build                    |   7 +-
 scripts/Makefile.clean                    |   2 +
 scripts/Makefile.lib                      |  11 +
 scripts/mod/modpost.c                     |   2 +-
 scripts/module-common.lds                 |   2 +
 scripts/recordmcount.c                    |   2 +-
 scripts/recordmcount.pl                   |   2 +-
 tools/objtool/special.c                   |   2 +-
 143 files changed, 3632 insertions(+), 200 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/linker-tables.rst
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/c6x/include/asm/tables.h
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/kprobes.h
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/asm-generic/tables.h
 create mode 100644 include/linux/ranges.h
 create mode 100644 include/linux/sections.h
 create mode 100644 include/linux/tables.h
 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

-- 
2.11.0


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v6 01/14] generic-sections: add section core helpers
  2017-01-09 14:58       ` Luis R. Rodriguez
                           ` (2 preceding siblings ...)
  (?)
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="windows-1254", Size: 47014 bytes --]

Linux makes extensive use of custom ELF header sections,
documentation for these are well scatterred. Unify this
documentation in a central place and provide helpers to
build custom Linux sections.

This also generalizes sections code to enable avoiding
modifying the linker scripts when we want to add new
custom Linux sections. In order to make this generally
useful we need to ensure all architectures can make use of
core section helpers but that they can also override should
this be needed. Instead of relying on section.h this adds
a sections-core.h since this will be targetted to be safe
to be used on asm code, linker scripts and C code.

v5:

o Huge documentation revamp based on a careful review of the ELF
  specifications. Includes documentation now also about usage of
  two dots (..) when prefixing ELF program specific sections.

o Replace macros for sections names in favor of just using
  the section names explicitly in the linker script. This is
  perhaps more work to grep but this is what folks seem to
  currently prefer.

o Fix .text and .rodata documentation to explain memory protection
  strategies which architectures can embrace upon initialization
  (documents CONFIG_DEBUG_RODATA and mark_rodata_ro())

o Skip the 'Linux section ordering' documentation section, we'll instead
  add this on subsequent patch which will expand on it considerably

o Dropped tree on MAINTAINERS -- as per discussions with Arnd, hpa and
  Josh, its easier to just let changes for sections go in through the
  respective tree that needs the changes.

o Fix typos on documentation

o Dropped SECTION_ALL(), __SECTION_CORE(), SECTION_CORE_ALL() macros
  since we are favoring using explicit section names. These are
  useless if we are being explicit.

o Drop LINUX_SECTION_SIZE(), LINUX_SECTION_EMPTY() in favor of having
  section ranges and linker tables define their own, to avoid confusion
  and make code more readable.

o Add __define_initcall() documentation and a small section describing
  our current initcall levels. This should help also clarify what was
  meant about keeping backward compatiblity.

v4:

o Port to shiny new sphinx documentation format

o fix a unicore32 build, turns out this actually fixes unicore32
  defconfig builds which were failing for a long while. unicore32
  does not seem to grok well the type passed on a section declaration,
  this ignores it.

o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
  this was causing final linker issues with blackfin -- this is
  a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
  being metatag. metatag is not supported on 0-day so I cannot confirm
  compilation there.

o Added SECTION_CORE() for C code, used later by __LINUX_RANGE()

o Since SECTION_CORE() is defined for linker script and C code, share
  the same helper and just use a __stringify() for the C code as is done
  for the other C helpers.

o move generic sections to asm-generic/section-core.h instead.
  PowerPC compilation blows up if asm/jump_labels.h gets
  section.h included, fixing this is not in any way easy.
  The list of issues are endless. Moving new data to a new
  simple file resolves this.

o since things are now in asm-generic/section-core.h the
  guard changes on asm-generic/sections.h and each architecture
  sections.h are no longer needed

o Give generic sections some maintainer love, that change is
  Acked-by Arnd Bergmann, Josh and hpa.

o A few checkpatch.pl style fixes

o As suggested by James Hogan use generic-y to copy generic
  header files on architectures that do not have a sections.h
  instead of writing a simple file only to include the generic one.

v3:

o add missing sections.h for architectures that did not
  have it

o move generic sections to asm-generic/sections.h

o add generic asm helpers section_type(), section_type_asmtype(),
  push_section_type() -- these helpers enable easy use for
  for later declaring and using of custom linux sections using
  more standard APIs in both C code, asm code (C asm calls, or
  asm files), enabling future standardized section types to
  be more immediately accessible to asm code, not just C code.
  Note for ASM_CMD_SEP we use by default "\n", architectures needed
  to override can do so on their own sections.h prior to inclusion
  of asm-generic/sections.h

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/index.rst                   |   1 +
 Documentation/sections/background.rst     | 105 ++++++++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  17 ++
 Documentation/sections/section-core.rst   | 148 ++++++++++++++
 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/Kbuild               |   1 +
 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/section-core.h |  19 ++
 arch/x86/include/asm/Kbuild               |   1 +
 arch/xtensa/include/asm/Kbuild            |   1 +
 include/asm-generic/section-core.h        | 307 ++++++++++++++++++++++++++++++
 include/asm-generic/sections.h            |   2 +
 include/asm-generic/vmlinux.lds.h         |   1 +
 include/linux/init.h                      |  89 +++++++--
 include/linux/sections.h                  |  87 +++++++++
 42 files changed, 809 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/linux/sections.h

diff --git a/Documentation/index.rst b/Documentation/index.rst
index cb5d77699c60..71e0305c036d 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -57,6 +57,7 @@ needed).
    media/index
    gpu/index
    security/index
+   sections/index
    sound/index
    crypto/index
 
diff --git a/Documentation/sections/background.rst b/Documentation/sections/background.rst
new file mode 100644
index 000000000000..0ecf9104aaa2
--- /dev/null
+++ b/Documentation/sections/background.rst
@@ -0,0 +1,105 @@
+===========
+ELF section background
+===========
+
+About
+==+
+The purpose of this chapter is to help those not familiar with ELF to brush up
+the latest ELF specifications in order to help understand how Linux uses and
+defines its own ELF sections.
+
+Standardized ELF
+========
+
+The first publication documenting ELF was UNIX System Laboratories' (USL)
+*System V Release 4 Application Binary Interface* (`SRV4 ABI`_) specification.
+Originally ELF was only a small part of the SRV4 ABI, with time however new
+specifications only put focus on ELF, such was the case of the *TIS Portable
+Formats Specification version 1.2* (`TIS 1.2`_). As of TIS 1.2, ELF was
+supplemented with processor specific ELF addendums, available on the *Linux
+Foundation referenced specification page* (`LF ref page`_). The latest ELF
+specification is the *System V Application Binary Interface - DRAFT - 24 April
+2001* (`gabi4`_).
+
+.. _SRV4 ABI: http://www.sco.com/developers/devspecs/gabi41.pdf
+.. _TIS 1.2: https://refspecs.linuxbase.org/elf/elf.pdf
+.. _LF ref page: https://refspecs.linuxbase.org/
+.. _gabi4: https://refspecs.linuxbase.org/elf/gabi4+/contents.html
+
+ELF views on Linux
+=========
+
+There are two views which can be used for inspecting data in an ELF file, a
+Linking view, and an Execution view. A Section Header Table enables one to
+describe an object using the Linking view while a Program Header Table enables
+one to describe an object using the Execution view. The views are not mutually
+exclusive. For intance, vmlinux can be viewed under both views, ``readelf -S
+vmlinux`` for the Linking view, and ``readelf -l vmlinux`` for the Execution
+view.  In Linux only the vmlinux file will have an Execution view, even modules
+lack an Execution view given that vmlinux is the only file that describes how
+the the kernel runs from the start.  All other Linux kernel object files have
+an available Linking view.
+
+Under the Linking view, the Section Header Table describes all available
+sections. The Section Header Table is an array of ELF section header data
+structures. If on a 32-bit system this is ``struct elf32_shd``, if on a 64-bit
+this is ``struct elf64_shdr``. Sections are only visible on object files that
+have a Linking view, since all Linux kernel files have Linking view, all kernel
+objects have ELF sections.
+
+Limitations on ELF sections
+=============+
+We provide a summary on the limitations of ELF sections. Refer to the public
+ELF specifications for details. Note that 64-bit limitations may depend
+on processor specific section attributes to be used, refer to your processsor
+specification if unsure.
+
+Its worth ellaborating on the limitations on the name of an ELF section:
+ELF section names are stored as strings as per the ELF specification, and
+as can be expected, these don't have explicit limitations. The implicit
+limitation then depends on the size of an ELF object file and ELF section.
+
+If using really large kernels or objects with large amounts of sections one
+would still need to be sure that ELF loader in charge of loading the Linux
+kernel is properly updated to handle coping with the latest ELF extensions.
+
+   .. flat-table:: Limitations on ELF Sections
+
+      * - Section attribute
+        - 32-bit
+        - 64-bit
+
+      * - ELF section name
+        - Size of an ELF section
+        - Size of an ELF section
+
+      * - Size of an ELF section
+        - 4 GiB
+        - 16 EiB
+
+      * - Max number of sections in an object file
+        - 4 GiEntries (4294967296)
+        - 16 EiEntries (18446744073709551616)
+
+Program specific ELF sections
+==============+
+The ELF specification allows for a section type to be specified as
+*Program specific section*, defined as ``SHT_PROGBITS``. This sections type
+enables programs to customize sections for their own use. In assembly this
+specified ``@progbits`` on most architectures, on ARM this is ``%progbits``.
+
+``SHT_PROGBITS`` is used by Linux for defining and using Linux ELF sections.
+
+Special ELF Sections
+==========
+
+The ELF specification defines *Special ELF Sections* on chapter 4 (`gabi4
+ch4`_). These are defined as sections which hold program and control
+information. Of these sections, a few have the section type as
+``SHT_PROGBITS``. This enables Linux to *further customize* use of the section
+beyond what the ELF specification suggests.
+
+.. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
new file mode 100644
index 000000000000..faa1c57595e1
--- /dev/null
+++ b/Documentation/sections/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel ELF sections'
+html_search_language = 'en'
diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
new file mode 100644
index 000000000000..f37511ef05e7
--- /dev/null
+++ b/Documentation/sections/index.rst
@@ -0,0 +1,17 @@
+============+Linux Kernel ELF sections
+============+
+This book documents the different ELF sections used on the Linux kernel.
+We start off by providing references to how ELF was standardized, references
+to the standards on ELF sections, review limitations of ELF sections, and
+finally how Linux uses ELF sections in the Linux kernel. Certain important
+Linux ELF sections are documented carefully: we describe the goal of the
+ELF section, and address concurrency considerations when applicable. A few
+common a set of Linux helpers for ELF sections are also documented.
+
+.. toctree::
+   :maxdepth: 4
+
+   background
+   section-core
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
new file mode 100644
index 000000000000..ac5815a0d9b3
--- /dev/null
+++ b/Documentation/sections/section-core.rst
@@ -0,0 +1,148 @@
+=================+Linux ELF program specific sections
+=================+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux ELF program specific sections
+
+Linux linker script
+=========+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux linker script
+
+Memory protection
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Memory protection
+
+mark_rodata_ro
+-----------------------
+.. kernel-doc:: include/linux/init.h
+   :functions: mark_rodata_ro
+
+.rodata
+-------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .rodata
+
+.text
+-----
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .text
+
+.data
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .data
+
+Linux .init\* sections
+===========
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux init sections
+
+.init.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.text
+
+.init.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.data
+
+.init.rodata
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.rodata
+
+Initcall levels
+---------------
+.. kernel-doc:: include/linux/init.h
+   :doc: Initcall levels
+
+.initcall
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .initcall
+
+__define_initcall
+-----------------
+.. kernel-doc:: include/linux/init.h
+   :functions: __define_initcall
+
+Linux .exit\* sections
+===========
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux exit sections
+
+.exit.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.text
+
+.exit.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.data
+
+.exitcall.exit
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exitcall.exit
+
+Linux .ref\* sections
+==========+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux references to init sections
+
+.ref.text
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.text
+
+.ref.data
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.data
+
+.ref.rodata
+-----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.rodata
+
+Generic Linux kernel section helpers
+==================
+
+Introduction
+-------------
+.. kernel-doc:: include/linux/sections.h
+   :doc: Introduction
+
+LINUX_SECTION_ALIGNMENT
+-----------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_ALIGNMENT
+
+LINUX_SECTION_START
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_START
+
+LINUX_SECTION_END
+-----------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_END
+
+DECLARE_LINUX_SECTION
+---------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION
+
+DECLARE_LINUX_SECTION_RO
+------------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION_RO
diff --git a/MAINTAINERS b/MAINTAINERS
index c68a6bb17966..ae86136f4b9a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5424,6 +5424,18 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTIONS
+M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
+M:	Josh Poimboeuf <jpoimboe@redhat.com>
+M:	"H. Peter Anvin" <hpa@zytor.com>
+L:	linux-arch@vger.kernel.org
+L:	linux-kernel@vger.kernel.org
+S:	Supported
+F:	include/asm-generic/section-core.h
+F:	include/asm-generic/sections.h
+F:	include/asm-generic/vmlinux.lds.h
+F:	Documentation/sections/section-core.rst
+
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index bf8475ce85ee..5422827f1585 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += section-core.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index c332604606dd..7b2cb3dea5fc 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index efb21757d41f..9b69a22a9ae1 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += unaligned.h
 
 generated-y += mach-types.h
 generated-y += unistd-nr.h
+generic-y += section-core.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 8365a84c2640..00ace5e826f1 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 241b9b9729d8..f2c3b656a0e7 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 2fb67b59d188..bf20541bcf21 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -47,3 +47,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 64465e7e2245..38127ce747be 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -62,3 +62,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 1778805f6380..385cd88a9d9e 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += types.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 1fa084cf1a43..46d7c599d9b8 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 373cb23301e3..1ec04ec1c82b 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -75,3 +75,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index db8ddabc6bd2..37d7bfae7619 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -60,3 +60,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 502a91d8dbbd..672c6d5da18c 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 860e440611c9..6111e1523750 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1f2e5d31cb24..1277b45bf4f9 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -34,3 +34,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 167150c701d1..b1011375cd7a 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -55,3 +55,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index b0ae88c9fed9..c6c2cf6edc98 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index ed07179fe26a..7a932b4a5531 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 1c8dd0f5cd5d..f8145bc85835 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index d63330e88379..c9c7cb82b00f 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 2832f031fb11..86175e701869 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -71,3 +71,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 91f53c07f410..18a9d4c5ead7 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -28,3 +28,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 5c4fbc80dc6c..4322d9746cdb 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
+generic-y += section-core.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 8aea32fe8bd2..63a1c2924b91 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index a05218ff3fe4..f089a264cd38 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 751c3373a92c..7b0356dca562 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 0569bfac4afb..438f86573dc5 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 2d1f5638974c..fb6b831c1fba 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 052f7f6d0551..580bd5ff828f 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -26,3 +26,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
new file mode 100644
index 000000000000..0b9c68429a1a
--- /dev/null
+++ b/arch/unicore32/include/asm/section-core.h
@@ -0,0 +1,19 @@
+#ifndef __UNICORE_SECTION_CORE_ASM_H__
+#define __UNICORE_SECTION_CORE_ASM_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/.
+ */
+
+/* Unicore32 has known to not work properly with the type set, so ignore it */
+
+#define __set_section_core_type(___section, ___core, ___name,		\
+				___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags
+
+#include <asm-generic/section-core.h>
+
+#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 2b892e2313a9..af975f21eeee 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
+generic-y += section-core.h
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index b7fbaa56b51a..7879c31e66a7 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..bb16befc4251
--- /dev/null
+++ b/include/asm-generic/section-core.h
@@ -0,0 +1,307 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Linux ELF program specific sections
+ *
+ * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and
+ * definition of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
+ * sections. This chaper is dedicated to documenting Linux program specific
+ * sections and helpers available to make use of these easier to implement and
+ * use.
+ *
+ * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
+ */
+
+/**
+ * DOC: Linux linker script
+ *
+ * Linux uses a custom linker script to build the vmlinux binary, it uses it to
+ * strategically place and define Linux ELF sections.  Each architecture needs
+ * to implement its own linker script, it is expected to reside in
+ * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
+ * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
+ * as well as some helpers documented in this chapter.
+ *
+ * In assembly it is common practice to use dots (``.``) in labels to avoid
+ * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
+ * name but not a C symbol. Historically then, two dots are used (``..``)
+ * have been used in linker scripts when adding program specific sections
+ * when there are concerns to avoid clashes with compiler generated sections.
+ */
+
+/**
+ * DOC: Memory protection
+ *
+ * Linux allows architectures which support memory protection features to
+ * take advantage of them by letting architectures define and enable
+ * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.
+ * mark_rodata_ro() can be used for instance to mark specific sections as
+ * read-only or non-executable.
+ *
+ * Linux typically follows a convention to have the .rodata ELF section follow
+ * after the .text ELF section, it does this to help architectures which
+ * support memory protection to mark both .text and .rodata as read-only in
+ * one shot.
+ *
+ * For more details refer to mark_rodata_ro().
+ */
+
+/**
+ * DOC: .rodata
+ *
+ * ELF section used for data which must be protected from write access.
+ */
+
+/**
+ * DOC: .text
+ *
+ * ELF section name used for code (functions) used during regular
+ * kernel run time.
+ */
+
+/**
+ * DOC: .data
+ *
+ * ELF section used for read-write data.
+ */
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: .init.text
+ *
+ * ELF section for code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+
+/**
+ * DOC: .init.data
+ *
+ * ELF section used for data structures used only during boot or driver
+ * initialization.
+ */
+
+/**
+ * DOC: .init.rodata
+ *
+ * ELF section used for read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+
+/**
+ * DOC: .initcall
+ *
+ * ELF section used for subsystem init calls. There are init levels
+ * representing different functionality in the kernel. For more details
+ * refer to __define_initcall().
+ */
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: .exit.text
+ *
+ * ELF section used to for code (functions) used only during module unload.
+ */
+
+/**
+ * DOC: .exit.data
+ *
+ * ELF section used to for data structures used only during module
+ * unload.
+ */
+
+/**
+ * DOC: .exitcall.exit
+ *
+ * ELF section used for exit routines, order is important and maintained by
+ * link order.
+ */
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: .ref.text
+ *
+ * ELF section used to annotate code (functions) which has been vetteed as
+ * valid for its reference or use of other code (functions) or data structures
+ * which are part of the init sections.
+ */
+
+/**
+ * DOC: .ref.data
+ *
+ * ELF section used for data structures which have been vetteed for its
+ * reference or use of other code (functions) or data structures part of the
+ * init sections.
+ */
+
+/**
+ * DOC: .ref.rodata
+ *
+ * ELF section used to annotate const code (functions) const data structures
+ * which has been vetteed for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section..___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section..__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifndef LINKER_SCRIPT
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align\x16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 4df64a1fc09e..b145ae8d9cbe 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_GENERIC_SECTIONS_H_
 #define _ASM_GENERIC_SECTIONS_H_
 
+#include <asm/section-core.h>
+
 /* References to section boundaries */
 
 #include <linux/compiler.h>
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 0968d13b3885..483f60c451f9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -55,6 +55,7 @@
 #endif
 
 #include <linux/export.h>
+#include <asm/section-core.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
diff --git a/include/linux/init.h b/include/linux/init.h
index 885c3e6d0f9d..116e3262332a 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -130,6 +130,24 @@ int __init init_rootfs(void);
 extern bool rodata_enabled;
 #endif
 #ifdef CONFIG_DEBUG_RODATA
+/**
+ * mark_rodata_ro - implemement memory protection for ELF sections
+ *
+ * Architectures which support memory protection define a kernel configuration
+ * entry for CONFIG_DEBUG_RODATA, enable it in and implement mark_rodata_ro().
+ * mark_rodata_ro() should strive to adjust the .rodata and .text ELF sections
+ * with read-only memory protection to prevent modifications of these sections
+ * after bootup. It can also try to use memory protection to prevent execution
+ * on the .rodata ELF section.
+ *
+ * In order to help architectures set both .text and .rodata as read-only with
+ * memory protections in one shot Linux has typically followed the convention
+ * to have the .rodata ELF section follow the .text ELF section on the vmlinux
+ * linker script.
+ *
+ * Linux calls mark_rodata_ro() after freeing .init code and prior to calling
+ * the first init userspace process.
+ */
 void mark_rodata_ro(void);
 #endif
 
@@ -140,25 +158,70 @@ extern bool initcall_debug;
 #endif
   
 #ifndef MODULE
+/**
+ * DOC: Initcall levels
+ *
+ * When Linux boots the kernel do_initcalls() iterates over each Linux
+ * initialization level ID and calls all routines embedded on each level ID.
+ * Prior to v2.5.2.3 Linux had only one init level onto which all init
+ * functions folded onto using __initcall(). After v2.5.2.4 Linux split up
+ * initcalls into 7 separate initcall subsection levels, each level describing
+ * different functionality part of the kernel (commit `9d6ba121b7e17085`_
+ * (v2.5.2.3 -> v2.5.2.4)). In order to remain backward compatible __initcall()
+ * calls were left mapped to device_initcall().
+ *
+ * Each init level consists of a dedicated ELF section, init functions are
+ * associated to an init level by linking it into the respective level's
+ * ELF section.
+ *
+ * Lower order init levels run prior to higher order init levels. Ordering
+ * inside each initcall level is determined by respective link order.
+ *
+ * .. _9d6ba121b7e17085: https://git.kernel.org/cgit/linux/kernel/git/history/history.git/commit/?id6ba121b7e17085c95139233686b27a4d4c650e
+ */
 
 #ifndef __ASSEMBLY__
 
-/*
- * initcalls are now grouped by functionality into separate
- * subsections. Ordering inside the subsections is determined
- * by link order. 
- * For backwards compatibility, initcall() puts the call in 
- * the device init subsection.
+/**
+ * __define_initcall - wrapper for definiting init levels
  *
- * The `id' arg to __define_initcall() is needed so that multiple initcalls
- * can point at the same handler without causing duplicate-symbol build errors.
+ * @fn: init routine
+ * @id: init level
  *
- * Initcalls are run by placing pointers in initcall sections that the
- * kernel iterates at runtime. The linker can do dead code / data elimination
- * and remove that completely, so the initcall sections have to be marked
- * as KEEP() in the linker script.
+ * Defines a kernel initialization level. A respective linker script entry
+ * is required to ensure the init level is accounted for and to ensure symbols
+ * exist for iterating over all functions in the init level. A init level
+ * represents a series of functionality in the kernel.
+ *
+ * Ordering within an initialization level is determined by link order, so
+ * for instance if a Makefile had::
+ *
+ *	obj-y += foo.o
+ *	obj-y += bar.o
+ *
+ * And foo.c::
+ *
+ *	subsys_initcall(foo_init);
+ *
+ * And bar.c had::
+ *
+ *	subsys_initcall(bar_init);
+ *
+ * foo_init() would be called prior to bar_init().
+ *
+ * Note that @id in __define_initcall() also enables multiple initcalls
+ * to be created using the same handler for different init levels without
+ * causing duplicate-symbol build errors.
+ *
+ * Initcalls are run by placing start symbols to initcall levels inside ELF
+ * sections, the kernel in turn uses these symbols to iterate over each init
+ * level at runtime with do_initcall_level(). The end of each init level is
+ * marked by the subsequent's symbol's start address until we reach the symbol
+ * ``__initcall_end``. The linker can do dead code / data elimination and each
+ * init level start symbol could be removed completely in this process, to
+ * avoid this each init level start symbols must be marked as 'KEEP()' in the
+ * linker script to avoid any linker optimization heuristic on initcalls.
  */
-
 #define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
 	__attribute__((__section__(".initcall" #id ".init"))) = fn;
diff --git a/include/linux/sections.h b/include/linux/sections.h
new file mode 100644
index 000000000000..6771c727bcd1
--- /dev/null
+++ b/include/linux/sections.h
@@ -0,0 +1,87 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_CORE(section, core, name, level)			\
+	#section ".." #core "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 01/14] generic-sections: add section core helpers
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt, ak

Linux makes extensive use of custom ELF header sections,
documentation for these are well scatterred. Unify this
documentation in a central place and provide helpers to
build custom Linux sections.

This also generalizes sections code to enable avoiding
modifying the linker scripts when we want to add new
custom Linux sections. In order to make this generally
useful we need to ensure all architectures can make use of
core section helpers but that they can also override should
this be needed. Instead of relying on section.h this adds
a sections-core.h since this will be targetted to be safe
to be used on asm code, linker scripts and C code.

v5:

o Huge documentation revamp based on a careful review of the ELF
  specifications. Includes documentation now also about usage of
  two dots (..) when prefixing ELF program specific sections.

o Replace macros for sections names in favor of just using
  the section names explicitly in the linker script. This is
  perhaps more work to grep but this is what folks seem to
  currently prefer.

o Fix .text and .rodata documentation to explain memory protection
  strategies which architectures can embrace upon initialization
  (documents CONFIG_DEBUG_RODATA and mark_rodata_ro())

o Skip the 'Linux section ordering' documentation section, we'll instead
  add this on subsequent patch which will expand on it considerably

o Dropped tree on MAINTAINERS -- as per discussions with Arnd, hpa and
  Josh, its easier to just let changes for sections go in through the
  respective tree that needs the changes.

o Fix typos on documentation

o Dropped SECTION_ALL(), __SECTION_CORE(), SECTION_CORE_ALL() macros
  since we are favoring using explicit section names. These are
  useless if we are being explicit.

o Drop LINUX_SECTION_SIZE(), LINUX_SECTION_EMPTY() in favor of having
  section ranges and linker tables define their own, to avoid confusion
  and make code more readable.

o Add __define_initcall() documentation and a small section describing
  our current initcall levels. This should help also clarify what was
  meant about keeping backward compatiblity.

v4:

o Port to shiny new sphinx documentation format

o fix a unicore32 build, turns out this actually fixes unicore32
  defconfig builds which were failing for a long while. unicore32
  does not seem to grok well the type passed on a section declaration,
  this ignores it.

o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
  this was causing final linker issues with blackfin -- this is
  a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
  being metatag. metatag is not supported on 0-day so I cannot confirm
  compilation there.

o Added SECTION_CORE() for C code, used later by __LINUX_RANGE()

o Since SECTION_CORE() is defined for linker script and C code, share
  the same helper and just use a __stringify() for the C code as is done
  for the other C helpers.

o move generic sections to asm-generic/section-core.h instead.
  PowerPC compilation blows up if asm/jump_labels.h gets
  section.h included, fixing this is not in any way easy.
  The list of issues are endless. Moving new data to a new
  simple file resolves this.

o since things are now in asm-generic/section-core.h the
  guard changes on asm-generic/sections.h and each architecture
  sections.h are no longer needed

o Give generic sections some maintainer love, that change is
  Acked-by Arnd Bergmann, Josh and hpa.

o A few checkpatch.pl style fixes

o As suggested by James Hogan use generic-y to copy generic
  header files on architectures that do not have a sections.h
  instead of writing a simple file only to include the generic one.

v3:

o add missing sections.h for architectures that did not
  have it

o move generic sections to asm-generic/sections.h

o add generic asm helpers section_type(), section_type_asmtype(),
  push_section_type() -- these helpers enable easy use for
  for later declaring and using of custom linux sections using
  more standard APIs in both C code, asm code (C asm calls, or
  asm files), enabling future standardized section types to
  be more immediately accessible to asm code, not just C code.
  Note for ASM_CMD_SEP we use by default "\n", architectures needed
  to override can do so on their own sections.h prior to inclusion
  of asm-generic/sections.h

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/index.rst                   |   1 +
 Documentation/sections/background.rst     | 105 ++++++++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  17 ++
 Documentation/sections/section-core.rst   | 148 ++++++++++++++
 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/Kbuild               |   1 +
 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/section-core.h |  19 ++
 arch/x86/include/asm/Kbuild               |   1 +
 arch/xtensa/include/asm/Kbuild            |   1 +
 include/asm-generic/section-core.h        | 307 ++++++++++++++++++++++++++++++
 include/asm-generic/sections.h            |   2 +
 include/asm-generic/vmlinux.lds.h         |   1 +
 include/linux/init.h                      |  89 +++++++--
 include/linux/sections.h                  |  87 +++++++++
 42 files changed, 809 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/linux/sections.h

diff --git a/Documentation/index.rst b/Documentation/index.rst
index cb5d77699c60..71e0305c036d 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -57,6 +57,7 @@ needed).
    media/index
    gpu/index
    security/index
+   sections/index
    sound/index
    crypto/index
 
diff --git a/Documentation/sections/background.rst b/Documentation/sections/background.rst
new file mode 100644
index 000000000000..0ecf9104aaa2
--- /dev/null
+++ b/Documentation/sections/background.rst
@@ -0,0 +1,105 @@
+======================
+ELF section background
+======================
+
+About
+=====
+
+The purpose of this chapter is to help those not familiar with ELF to brush up
+the latest ELF specifications in order to help understand how Linux uses and
+defines its own ELF sections.
+
+Standardized ELF
+================
+
+The first publication documenting ELF was UNIX System Laboratories' (USL)
+*System V Release 4 Application Binary Interface* (`SRV4 ABI`_) specification.
+Originally ELF was only a small part of the SRV4 ABI, with time however new
+specifications only put focus on ELF, such was the case of the *TIS Portable
+Formats Specification version 1.2* (`TIS 1.2`_). As of TIS 1.2, ELF was
+supplemented with processor specific ELF addendums, available on the *Linux
+Foundation referenced specification page* (`LF ref page`_). The latest ELF
+specification is the *System V Application Binary Interface - DRAFT - 24 April
+2001* (`gabi4`_).
+
+.. _SRV4 ABI: http://www.sco.com/developers/devspecs/gabi41.pdf
+.. _TIS 1.2: https://refspecs.linuxbase.org/elf/elf.pdf
+.. _LF ref page: https://refspecs.linuxbase.org/
+.. _gabi4: https://refspecs.linuxbase.org/elf/gabi4+/contents.html
+
+ELF views on Linux
+==================
+
+There are two views which can be used for inspecting data in an ELF file, a
+Linking view, and an Execution view. A Section Header Table enables one to
+describe an object using the Linking view while a Program Header Table enables
+one to describe an object using the Execution view. The views are not mutually
+exclusive. For intance, vmlinux can be viewed under both views, ``readelf -S
+vmlinux`` for the Linking view, and ``readelf -l vmlinux`` for the Execution
+view.  In Linux only the vmlinux file will have an Execution view, even modules
+lack an Execution view given that vmlinux is the only file that describes how
+the the kernel runs from the start.  All other Linux kernel object files have
+an available Linking view.
+
+Under the Linking view, the Section Header Table describes all available
+sections. The Section Header Table is an array of ELF section header data
+structures. If on a 32-bit system this is ``struct elf32_shd``, if on a 64-bit
+this is ``struct elf64_shdr``. Sections are only visible on object files that
+have a Linking view, since all Linux kernel files have Linking view, all kernel
+objects have ELF sections.
+
+Limitations on ELF sections
+===========================
+
+We provide a summary on the limitations of ELF sections. Refer to the public
+ELF specifications for details. Note that 64-bit limitations may depend
+on processor specific section attributes to be used, refer to your processsor
+specification if unsure.
+
+Its worth ellaborating on the limitations on the name of an ELF section:
+ELF section names are stored as strings as per the ELF specification, and
+as can be expected, these don't have explicit limitations. The implicit
+limitation then depends on the size of an ELF object file and ELF section.
+
+If using really large kernels or objects with large amounts of sections one
+would still need to be sure that ELF loader in charge of loading the Linux
+kernel is properly updated to handle coping with the latest ELF extensions.
+
+   .. flat-table:: Limitations on ELF Sections
+
+      * - Section attribute
+        - 32-bit
+        - 64-bit
+
+      * - ELF section name
+        - Size of an ELF section
+        - Size of an ELF section
+
+      * - Size of an ELF section
+        - 4 GiB
+        - 16 EiB
+
+      * - Max number of sections in an object file
+        - 4 GiEntries (4294967296)
+        - 16 EiEntries (18446744073709551616)
+
+Program specific ELF sections
+=============================
+
+The ELF specification allows for a section type to be specified as
+*Program specific section*, defined as ``SHT_PROGBITS``. This sections type
+enables programs to customize sections for their own use. In assembly this
+specified ``@progbits`` on most architectures, on ARM this is ``%progbits``.
+
+``SHT_PROGBITS`` is used by Linux for defining and using Linux ELF sections.
+
+Special ELF Sections
+====================
+
+The ELF specification defines *Special ELF Sections* on chapter 4 (`gabi4
+ch4`_). These are defined as sections which hold program and control
+information. Of these sections, a few have the section type as
+``SHT_PROGBITS``. This enables Linux to *further customize* use of the section
+beyond what the ELF specification suggests.
+
+.. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
new file mode 100644
index 000000000000..faa1c57595e1
--- /dev/null
+++ b/Documentation/sections/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel ELF sections'
+html_search_language = 'en'
diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
new file mode 100644
index 000000000000..f37511ef05e7
--- /dev/null
+++ b/Documentation/sections/index.rst
@@ -0,0 +1,17 @@
+=========================
+Linux Kernel ELF sections
+=========================
+
+This book documents the different ELF sections used on the Linux kernel.
+We start off by providing references to how ELF was standardized, references
+to the standards on ELF sections, review limitations of ELF sections, and
+finally how Linux uses ELF sections in the Linux kernel. Certain important
+Linux ELF sections are documented carefully: we describe the goal of the
+ELF section, and address concurrency considerations when applicable. A few
+common a set of Linux helpers for ELF sections are also documented.
+
+.. toctree::
+   :maxdepth: 4
+
+   background
+   section-core
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
new file mode 100644
index 000000000000..ac5815a0d9b3
--- /dev/null
+++ b/Documentation/sections/section-core.rst
@@ -0,0 +1,148 @@
+===================================
+Linux ELF program specific sections
+===================================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux ELF program specific sections
+
+Linux linker script
+===================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux linker script
+
+Memory protection
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Memory protection
+
+mark_rodata_ro
+-----------------------
+.. kernel-doc:: include/linux/init.h
+   :functions: mark_rodata_ro
+
+.rodata
+-------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .rodata
+
+.text
+-----
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .text
+
+.data
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .data
+
+Linux .init\* sections
+======================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux init sections
+
+.init.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.text
+
+.init.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.data
+
+.init.rodata
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.rodata
+
+Initcall levels
+---------------
+.. kernel-doc:: include/linux/init.h
+   :doc: Initcall levels
+
+.initcall
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .initcall
+
+__define_initcall
+-----------------
+.. kernel-doc:: include/linux/init.h
+   :functions: __define_initcall
+
+Linux .exit\* sections
+======================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux exit sections
+
+.exit.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.text
+
+.exit.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.data
+
+.exitcall.exit
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exitcall.exit
+
+Linux .ref\* sections
+=====================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux references to init sections
+
+.ref.text
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.text
+
+.ref.data
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.data
+
+.ref.rodata
+-----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.rodata
+
+Generic Linux kernel section helpers
+====================================
+
+Introduction
+-------------
+.. kernel-doc:: include/linux/sections.h
+   :doc: Introduction
+
+LINUX_SECTION_ALIGNMENT
+-----------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_ALIGNMENT
+
+LINUX_SECTION_START
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_START
+
+LINUX_SECTION_END
+-----------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_END
+
+DECLARE_LINUX_SECTION
+---------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION
+
+DECLARE_LINUX_SECTION_RO
+------------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION_RO
diff --git a/MAINTAINERS b/MAINTAINERS
index c68a6bb17966..ae86136f4b9a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5424,6 +5424,18 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTIONS
+M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
+M:	Josh Poimboeuf <jpoimboe@redhat.com>
+M:	"H. Peter Anvin" <hpa@zytor.com>
+L:	linux-arch@vger.kernel.org
+L:	linux-kernel@vger.kernel.org
+S:	Supported
+F:	include/asm-generic/section-core.h
+F:	include/asm-generic/sections.h
+F:	include/asm-generic/vmlinux.lds.h
+F:	Documentation/sections/section-core.rst
+
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index bf8475ce85ee..5422827f1585 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += section-core.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index c332604606dd..7b2cb3dea5fc 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index efb21757d41f..9b69a22a9ae1 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += unaligned.h
 
 generated-y += mach-types.h
 generated-y += unistd-nr.h
+generic-y += section-core.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 8365a84c2640..00ace5e826f1 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 241b9b9729d8..f2c3b656a0e7 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 2fb67b59d188..bf20541bcf21 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -47,3 +47,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 64465e7e2245..38127ce747be 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -62,3 +62,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 1778805f6380..385cd88a9d9e 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += types.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 1fa084cf1a43..46d7c599d9b8 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 373cb23301e3..1ec04ec1c82b 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -75,3 +75,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index db8ddabc6bd2..37d7bfae7619 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -60,3 +60,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 502a91d8dbbd..672c6d5da18c 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 860e440611c9..6111e1523750 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1f2e5d31cb24..1277b45bf4f9 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -34,3 +34,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 167150c701d1..b1011375cd7a 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -55,3 +55,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index b0ae88c9fed9..c6c2cf6edc98 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index ed07179fe26a..7a932b4a5531 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 1c8dd0f5cd5d..f8145bc85835 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index d63330e88379..c9c7cb82b00f 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 2832f031fb11..86175e701869 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -71,3 +71,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 91f53c07f410..18a9d4c5ead7 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -28,3 +28,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 5c4fbc80dc6c..4322d9746cdb 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
+generic-y += section-core.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 8aea32fe8bd2..63a1c2924b91 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index a05218ff3fe4..f089a264cd38 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 751c3373a92c..7b0356dca562 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 0569bfac4afb..438f86573dc5 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 2d1f5638974c..fb6b831c1fba 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 052f7f6d0551..580bd5ff828f 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -26,3 +26,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
new file mode 100644
index 000000000000..0b9c68429a1a
--- /dev/null
+++ b/arch/unicore32/include/asm/section-core.h
@@ -0,0 +1,19 @@
+#ifndef __UNICORE_SECTION_CORE_ASM_H__
+#define __UNICORE_SECTION_CORE_ASM_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/.
+ */
+
+/* Unicore32 has known to not work properly with the type set, so ignore it */
+
+#define __set_section_core_type(___section, ___core, ___name,		\
+				___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags
+
+#include <asm-generic/section-core.h>
+
+#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 2b892e2313a9..af975f21eeee 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
+generic-y += section-core.h
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index b7fbaa56b51a..7879c31e66a7 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..bb16befc4251
--- /dev/null
+++ b/include/asm-generic/section-core.h
@@ -0,0 +1,307 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Linux ELF program specific sections
+ *
+ * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and
+ * definition of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
+ * sections. This chaper is dedicated to documenting Linux program specific
+ * sections and helpers available to make use of these easier to implement and
+ * use.
+ *
+ * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
+ */
+
+/**
+ * DOC: Linux linker script
+ *
+ * Linux uses a custom linker script to build the vmlinux binary, it uses it to
+ * strategically place and define Linux ELF sections.  Each architecture needs
+ * to implement its own linker script, it is expected to reside in
+ * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
+ * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
+ * as well as some helpers documented in this chapter.
+ *
+ * In assembly it is common practice to use dots (``.``) in labels to avoid
+ * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
+ * name but not a C symbol. Historically then, two dots are used (``..``)
+ * have been used in linker scripts when adding program specific sections
+ * when there are concerns to avoid clashes with compiler generated sections.
+ */
+
+/**
+ * DOC: Memory protection
+ *
+ * Linux allows architectures which support memory protection features to
+ * take advantage of them by letting architectures define and enable
+ * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.
+ * mark_rodata_ro() can be used for instance to mark specific sections as
+ * read-only or non-executable.
+ *
+ * Linux typically follows a convention to have the .rodata ELF section follow
+ * after the .text ELF section, it does this to help architectures which
+ * support memory protection to mark both .text and .rodata as read-only in
+ * one shot.
+ *
+ * For more details refer to mark_rodata_ro().
+ */
+
+/**
+ * DOC: .rodata
+ *
+ * ELF section used for data which must be protected from write access.
+ */
+
+/**
+ * DOC: .text
+ *
+ * ELF section name used for code (functions) used during regular
+ * kernel run time.
+ */
+
+/**
+ * DOC: .data
+ *
+ * ELF section used for read-write data.
+ */
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: .init.text
+ *
+ * ELF section for code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+
+/**
+ * DOC: .init.data
+ *
+ * ELF section used for data structures used only during boot or driver
+ * initialization.
+ */
+
+/**
+ * DOC: .init.rodata
+ *
+ * ELF section used for read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+
+/**
+ * DOC: .initcall
+ *
+ * ELF section used for subsystem init calls. There are init levels
+ * representing different functionality in the kernel. For more details
+ * refer to __define_initcall().
+ */
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: .exit.text
+ *
+ * ELF section used to for code (functions) used only during module unload.
+ */
+
+/**
+ * DOC: .exit.data
+ *
+ * ELF section used to for data structures used only during module
+ * unload.
+ */
+
+/**
+ * DOC: .exitcall.exit
+ *
+ * ELF section used for exit routines, order is important and maintained by
+ * link order.
+ */
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: .ref.text
+ *
+ * ELF section used to annotate code (functions) which has been vetteed as
+ * valid for its reference or use of other code (functions) or data structures
+ * which are part of the init sections.
+ */
+
+/**
+ * DOC: .ref.data
+ *
+ * ELF section used for data structures which have been vetteed for its
+ * reference or use of other code (functions) or data structures part of the
+ * init sections.
+ */
+
+/**
+ * DOC: .ref.rodata
+ *
+ * ELF section used to annotate const code (functions) const data structures
+ * which has been vetteed for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section..___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section..__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifndef LINKER_SCRIPT
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align=16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 4df64a1fc09e..b145ae8d9cbe 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_GENERIC_SECTIONS_H_
 #define _ASM_GENERIC_SECTIONS_H_
 
+#include <asm/section-core.h>
+
 /* References to section boundaries */
 
 #include <linux/compiler.h>
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 0968d13b3885..483f60c451f9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -55,6 +55,7 @@
 #endif
 
 #include <linux/export.h>
+#include <asm/section-core.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
diff --git a/include/linux/init.h b/include/linux/init.h
index 885c3e6d0f9d..116e3262332a 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -130,6 +130,24 @@ int __init init_rootfs(void);
 extern bool rodata_enabled;
 #endif
 #ifdef CONFIG_DEBUG_RODATA
+/**
+ * mark_rodata_ro - implemement memory protection for ELF sections
+ *
+ * Architectures which support memory protection define a kernel configuration
+ * entry for CONFIG_DEBUG_RODATA, enable it in and implement mark_rodata_ro().
+ * mark_rodata_ro() should strive to adjust the .rodata and .text ELF sections
+ * with read-only memory protection to prevent modifications of these sections
+ * after bootup. It can also try to use memory protection to prevent execution
+ * on the .rodata ELF section.
+ *
+ * In order to help architectures set both .text and .rodata as read-only with
+ * memory protections in one shot Linux has typically followed the convention
+ * to have the .rodata ELF section follow the .text ELF section on the vmlinux
+ * linker script.
+ *
+ * Linux calls mark_rodata_ro() after freeing .init code and prior to calling
+ * the first init userspace process.
+ */
 void mark_rodata_ro(void);
 #endif
 
@@ -140,25 +158,70 @@ extern bool initcall_debug;
 #endif
   
 #ifndef MODULE
+/**
+ * DOC: Initcall levels
+ *
+ * When Linux boots the kernel do_initcalls() iterates over each Linux
+ * initialization level ID and calls all routines embedded on each level ID.
+ * Prior to v2.5.2.3 Linux had only one init level onto which all init
+ * functions folded onto using __initcall(). After v2.5.2.4 Linux split up
+ * initcalls into 7 separate initcall subsection levels, each level describing
+ * different functionality part of the kernel (commit `9d6ba121b7e17085`_
+ * (v2.5.2.3 -> v2.5.2.4)). In order to remain backward compatible __initcall()
+ * calls were left mapped to device_initcall().
+ *
+ * Each init level consists of a dedicated ELF section, init functions are
+ * associated to an init level by linking it into the respective level's
+ * ELF section.
+ *
+ * Lower order init levels run prior to higher order init levels. Ordering
+ * inside each initcall level is determined by respective link order.
+ *
+ * .. _9d6ba121b7e17085: https://git.kernel.org/cgit/linux/kernel/git/history/history.git/commit/?id=9d6ba121b7e17085c95139233686b27a4d4c650e
+ */
 
 #ifndef __ASSEMBLY__
 
-/*
- * initcalls are now grouped by functionality into separate
- * subsections. Ordering inside the subsections is determined
- * by link order. 
- * For backwards compatibility, initcall() puts the call in 
- * the device init subsection.
+/**
+ * __define_initcall - wrapper for definiting init levels
  *
- * The `id' arg to __define_initcall() is needed so that multiple initcalls
- * can point at the same handler without causing duplicate-symbol build errors.
+ * @fn: init routine
+ * @id: init level
  *
- * Initcalls are run by placing pointers in initcall sections that the
- * kernel iterates at runtime. The linker can do dead code / data elimination
- * and remove that completely, so the initcall sections have to be marked
- * as KEEP() in the linker script.
+ * Defines a kernel initialization level. A respective linker script entry
+ * is required to ensure the init level is accounted for and to ensure symbols
+ * exist for iterating over all functions in the init level. A init level
+ * represents a series of functionality in the kernel.
+ *
+ * Ordering within an initialization level is determined by link order, so
+ * for instance if a Makefile had::
+ *
+ *	obj-y += foo.o
+ *	obj-y += bar.o
+ *
+ * And foo.c::
+ *
+ *	subsys_initcall(foo_init);
+ *
+ * And bar.c had::
+ *
+ *	subsys_initcall(bar_init);
+ *
+ * foo_init() would be called prior to bar_init().
+ *
+ * Note that @id in __define_initcall() also enables multiple initcalls
+ * to be created using the same handler for different init levels without
+ * causing duplicate-symbol build errors.
+ *
+ * Initcalls are run by placing start symbols to initcall levels inside ELF
+ * sections, the kernel in turn uses these symbols to iterate over each init
+ * level at runtime with do_initcall_level(). The end of each init level is
+ * marked by the subsequent's symbol's start address until we reach the symbol
+ * ``__initcall_end``. The linker can do dead code / data elimination and each
+ * init level start symbol could be removed completely in this process, to
+ * avoid this each init level start symbols must be marked as 'KEEP()' in the
+ * linker script to avoid any linker optimization heuristic on initcalls.
  */
-
 #define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
 	__attribute__((__section__(".initcall" #id ".init"))) = fn;
diff --git a/include/linux/sections.h b/include/linux/sections.h
new file mode 100644
index 000000000000..6771c727bcd1
--- /dev/null
+++ b/include/linux/sections.h
@@ -0,0 +1,87 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_CORE(section, core, name, level)			\
+	#section ".." #core "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
-- 
2.11.0


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 01/14] generic-sections: add section core helpers
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

Linux makes extensive use of custom ELF header sections,
documentation for these are well scatterred. Unify this
documentation in a central place and provide helpers to
build custom Linux sections.

This also generalizes sections code to enable avoiding
modifying the linker scripts when we want to add new
custom Linux sections. In order to make this generally
useful we need to ensure all architectures can make use of
core section helpers but that they can also override should
this be needed. Instead of relying on section.h this adds
a sections-core.h since this will be targetted to be safe
to be used on asm code, linker scripts and C code.

v5:

o Huge documentation revamp based on a careful review of the ELF
  specifications. Includes documentation now also about usage of
  two dots (..) when prefixing ELF program specific sections.

o Replace macros for sections names in favor of just using
  the section names explicitly in the linker script. This is
  perhaps more work to grep but this is what folks seem to
  currently prefer.

o Fix .text and .rodata documentation to explain memory protection
  strategies which architectures can embrace upon initialization
  (documents CONFIG_DEBUG_RODATA and mark_rodata_ro())

o Skip the 'Linux section ordering' documentation section, we'll instead
  add this on subsequent patch which will expand on it considerably

o Dropped tree on MAINTAINERS -- as per discussions with Arnd, hpa and
  Josh, its easier to just let changes for sections go in through the
  respective tree that needs the changes.

o Fix typos on documentation

o Dropped SECTION_ALL(), __SECTION_CORE(), SECTION_CORE_ALL() macros
  since we are favoring using explicit section names. These are
  useless if we are being explicit.

o Drop LINUX_SECTION_SIZE(), LINUX_SECTION_EMPTY() in favor of having
  section ranges and linker tables define their own, to avoid confusion
  and make code more readable.

o Add __define_initcall() documentation and a small section describing
  our current initcall levels. This should help also clarify what was
  meant about keeping backward compatiblity.

v4:

o Port to shiny new sphinx documentation format

o fix a unicore32 build, turns out this actually fixes unicore32
  defconfig builds which were failing for a long while. unicore32
  does not seem to grok well the type passed on a section declaration,
  this ignores it.

o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
  this was causing final linker issues with blackfin -- this is
  a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
  being metatag. metatag is not supported on 0-day so I cannot confirm
  compilation there.

o Added SECTION_CORE() for C code, used later by __LINUX_RANGE()

o Since SECTION_CORE() is defined for linker script and C code, share
  the same helper and just use a __stringify() for the C code as is done
  for the other C helpers.

o move generic sections to asm-generic/section-core.h instead.
  PowerPC compilation blows up if asm/jump_labels.h gets
  section.h included, fixing this is not in any way easy.
  The list of issues are endless. Moving new data to a new
  simple file resolves this.

o since things are now in asm-generic/section-core.h the
  guard changes on asm-generic/sections.h and each architecture
  sections.h are no longer needed

o Give generic sections some maintainer love, that change is
  Acked-by Arnd Bergmann, Josh and hpa.

o A few checkpatch.pl style fixes

o As suggested by James Hogan use generic-y to copy generic
  header files on architectures that do not have a sections.h
  instead of writing a simple file only to include the generic one.

v3:

o add missing sections.h for architectures that did not
  have it

o move generic sections to asm-generic/sections.h

o add generic asm helpers section_type(), section_type_asmtype(),
  push_section_type() -- these helpers enable easy use for
  for later declaring and using of custom linux sections using
  more standard APIs in both C code, asm code (C asm calls, or
  asm files), enabling future standardized section types to
  be more immediately accessible to asm code, not just C code.
  Note for ASM_CMD_SEP we use by default "\n", architectures needed
  to override can do so on their own sections.h prior to inclusion
  of asm-generic/sections.h

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/index.rst                   |   1 +
 Documentation/sections/background.rst     | 105 ++++++++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  17 ++
 Documentation/sections/section-core.rst   | 148 ++++++++++++++
 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/Kbuild               |   1 +
 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/section-core.h |  19 ++
 arch/x86/include/asm/Kbuild               |   1 +
 arch/xtensa/include/asm/Kbuild            |   1 +
 include/asm-generic/section-core.h        | 307 ++++++++++++++++++++++++++++++
 include/asm-generic/sections.h            |   2 +
 include/asm-generic/vmlinux.lds.h         |   1 +
 include/linux/init.h                      |  89 +++++++--
 include/linux/sections.h                  |  87 +++++++++
 42 files changed, 809 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/linux/sections.h

diff --git a/Documentation/index.rst b/Documentation/index.rst
index cb5d77699c60..71e0305c036d 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -57,6 +57,7 @@ needed).
    media/index
    gpu/index
    security/index
+   sections/index
    sound/index
    crypto/index
 
diff --git a/Documentation/sections/background.rst b/Documentation/sections/background.rst
new file mode 100644
index 000000000000..0ecf9104aaa2
--- /dev/null
+++ b/Documentation/sections/background.rst
@@ -0,0 +1,105 @@
+======================
+ELF section background
+======================
+
+About
+=====
+
+The purpose of this chapter is to help those not familiar with ELF to brush up
+the latest ELF specifications in order to help understand how Linux uses and
+defines its own ELF sections.
+
+Standardized ELF
+================
+
+The first publication documenting ELF was UNIX System Laboratories' (USL)
+*System V Release 4 Application Binary Interface* (`SRV4 ABI`_) specification.
+Originally ELF was only a small part of the SRV4 ABI, with time however new
+specifications only put focus on ELF, such was the case of the *TIS Portable
+Formats Specification version 1.2* (`TIS 1.2`_). As of TIS 1.2, ELF was
+supplemented with processor specific ELF addendums, available on the *Linux
+Foundation referenced specification page* (`LF ref page`_). The latest ELF
+specification is the *System V Application Binary Interface - DRAFT - 24 April
+2001* (`gabi4`_).
+
+.. _SRV4 ABI: http://www.sco.com/developers/devspecs/gabi41.pdf
+.. _TIS 1.2: https://refspecs.linuxbase.org/elf/elf.pdf
+.. _LF ref page: https://refspecs.linuxbase.org/
+.. _gabi4: https://refspecs.linuxbase.org/elf/gabi4+/contents.html
+
+ELF views on Linux
+==================
+
+There are two views which can be used for inspecting data in an ELF file, a
+Linking view, and an Execution view. A Section Header Table enables one to
+describe an object using the Linking view while a Program Header Table enables
+one to describe an object using the Execution view. The views are not mutually
+exclusive. For intance, vmlinux can be viewed under both views, ``readelf -S
+vmlinux`` for the Linking view, and ``readelf -l vmlinux`` for the Execution
+view.  In Linux only the vmlinux file will have an Execution view, even modules
+lack an Execution view given that vmlinux is the only file that describes how
+the the kernel runs from the start.  All other Linux kernel object files have
+an available Linking view.
+
+Under the Linking view, the Section Header Table describes all available
+sections. The Section Header Table is an array of ELF section header data
+structures. If on a 32-bit system this is ``struct elf32_shd``, if on a 64-bit
+this is ``struct elf64_shdr``. Sections are only visible on object files that
+have a Linking view, since all Linux kernel files have Linking view, all kernel
+objects have ELF sections.
+
+Limitations on ELF sections
+===========================
+
+We provide a summary on the limitations of ELF sections. Refer to the public
+ELF specifications for details. Note that 64-bit limitations may depend
+on processor specific section attributes to be used, refer to your processsor
+specification if unsure.
+
+Its worth ellaborating on the limitations on the name of an ELF section:
+ELF section names are stored as strings as per the ELF specification, and
+as can be expected, these don't have explicit limitations. The implicit
+limitation then depends on the size of an ELF object file and ELF section.
+
+If using really large kernels or objects with large amounts of sections one
+would still need to be sure that ELF loader in charge of loading the Linux
+kernel is properly updated to handle coping with the latest ELF extensions.
+
+   .. flat-table:: Limitations on ELF Sections
+
+      * - Section attribute
+        - 32-bit
+        - 64-bit
+
+      * - ELF section name
+        - Size of an ELF section
+        - Size of an ELF section
+
+      * - Size of an ELF section
+        - 4 GiB
+        - 16 EiB
+
+      * - Max number of sections in an object file
+        - 4 GiEntries (4294967296)
+        - 16 EiEntries (18446744073709551616)
+
+Program specific ELF sections
+=============================
+
+The ELF specification allows for a section type to be specified as
+*Program specific section*, defined as ``SHT_PROGBITS``. This sections type
+enables programs to customize sections for their own use. In assembly this
+specified ``@progbits`` on most architectures, on ARM this is ``%progbits``.
+
+``SHT_PROGBITS`` is used by Linux for defining and using Linux ELF sections.
+
+Special ELF Sections
+====================
+
+The ELF specification defines *Special ELF Sections* on chapter 4 (`gabi4
+ch4`_). These are defined as sections which hold program and control
+information. Of these sections, a few have the section type as
+``SHT_PROGBITS``. This enables Linux to *further customize* use of the section
+beyond what the ELF specification suggests.
+
+.. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
new file mode 100644
index 000000000000..faa1c57595e1
--- /dev/null
+++ b/Documentation/sections/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel ELF sections'
+html_search_language = 'en'
diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
new file mode 100644
index 000000000000..f37511ef05e7
--- /dev/null
+++ b/Documentation/sections/index.rst
@@ -0,0 +1,17 @@
+=========================
+Linux Kernel ELF sections
+=========================
+
+This book documents the different ELF sections used on the Linux kernel.
+We start off by providing references to how ELF was standardized, references
+to the standards on ELF sections, review limitations of ELF sections, and
+finally how Linux uses ELF sections in the Linux kernel. Certain important
+Linux ELF sections are documented carefully: we describe the goal of the
+ELF section, and address concurrency considerations when applicable. A few
+common a set of Linux helpers for ELF sections are also documented.
+
+.. toctree::
+   :maxdepth: 4
+
+   background
+   section-core
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
new file mode 100644
index 000000000000..ac5815a0d9b3
--- /dev/null
+++ b/Documentation/sections/section-core.rst
@@ -0,0 +1,148 @@
+===================================
+Linux ELF program specific sections
+===================================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux ELF program specific sections
+
+Linux linker script
+===================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux linker script
+
+Memory protection
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Memory protection
+
+mark_rodata_ro
+-----------------------
+.. kernel-doc:: include/linux/init.h
+   :functions: mark_rodata_ro
+
+.rodata
+-------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .rodata
+
+.text
+-----
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .text
+
+.data
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .data
+
+Linux .init\* sections
+======================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux init sections
+
+.init.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.text
+
+.init.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.data
+
+.init.rodata
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.rodata
+
+Initcall levels
+---------------
+.. kernel-doc:: include/linux/init.h
+   :doc: Initcall levels
+
+.initcall
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .initcall
+
+__define_initcall
+-----------------
+.. kernel-doc:: include/linux/init.h
+   :functions: __define_initcall
+
+Linux .exit\* sections
+======================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux exit sections
+
+.exit.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.text
+
+.exit.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.data
+
+.exitcall.exit
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exitcall.exit
+
+Linux .ref\* sections
+=====================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux references to init sections
+
+.ref.text
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.text
+
+.ref.data
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.data
+
+.ref.rodata
+-----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.rodata
+
+Generic Linux kernel section helpers
+====================================
+
+Introduction
+-------------
+.. kernel-doc:: include/linux/sections.h
+   :doc: Introduction
+
+LINUX_SECTION_ALIGNMENT
+-----------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_ALIGNMENT
+
+LINUX_SECTION_START
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_START
+
+LINUX_SECTION_END
+-----------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_END
+
+DECLARE_LINUX_SECTION
+---------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION
+
+DECLARE_LINUX_SECTION_RO
+------------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION_RO
diff --git a/MAINTAINERS b/MAINTAINERS
index c68a6bb17966..ae86136f4b9a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5424,6 +5424,18 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTIONS
+M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
+M:	Josh Poimboeuf <jpoimboe@redhat.com>
+M:	"H. Peter Anvin" <hpa@zytor.com>
+L:	linux-arch@vger.kernel.org
+L:	linux-kernel@vger.kernel.org
+S:	Supported
+F:	include/asm-generic/section-core.h
+F:	include/asm-generic/sections.h
+F:	include/asm-generic/vmlinux.lds.h
+F:	Documentation/sections/section-core.rst
+
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index bf8475ce85ee..5422827f1585 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += section-core.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index c332604606dd..7b2cb3dea5fc 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index efb21757d41f..9b69a22a9ae1 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += unaligned.h
 
 generated-y += mach-types.h
 generated-y += unistd-nr.h
+generic-y += section-core.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 8365a84c2640..00ace5e826f1 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 241b9b9729d8..f2c3b656a0e7 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 2fb67b59d188..bf20541bcf21 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -47,3 +47,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 64465e7e2245..38127ce747be 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -62,3 +62,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 1778805f6380..385cd88a9d9e 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += types.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 1fa084cf1a43..46d7c599d9b8 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 373cb23301e3..1ec04ec1c82b 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -75,3 +75,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index db8ddabc6bd2..37d7bfae7619 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -60,3 +60,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 502a91d8dbbd..672c6d5da18c 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 860e440611c9..6111e1523750 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1f2e5d31cb24..1277b45bf4f9 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -34,3 +34,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 167150c701d1..b1011375cd7a 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -55,3 +55,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index b0ae88c9fed9..c6c2cf6edc98 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index ed07179fe26a..7a932b4a5531 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 1c8dd0f5cd5d..f8145bc85835 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index d63330e88379..c9c7cb82b00f 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 2832f031fb11..86175e701869 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -71,3 +71,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 91f53c07f410..18a9d4c5ead7 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -28,3 +28,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 5c4fbc80dc6c..4322d9746cdb 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
+generic-y += section-core.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 8aea32fe8bd2..63a1c2924b91 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index a05218ff3fe4..f089a264cd38 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 751c3373a92c..7b0356dca562 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 0569bfac4afb..438f86573dc5 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 2d1f5638974c..fb6b831c1fba 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 052f7f6d0551..580bd5ff828f 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -26,3 +26,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
new file mode 100644
index 000000000000..0b9c68429a1a
--- /dev/null
+++ b/arch/unicore32/include/asm/section-core.h
@@ -0,0 +1,19 @@
+#ifndef __UNICORE_SECTION_CORE_ASM_H__
+#define __UNICORE_SECTION_CORE_ASM_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/.
+ */
+
+/* Unicore32 has known to not work properly with the type set, so ignore it */
+
+#define __set_section_core_type(___section, ___core, ___name,		\
+				___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags
+
+#include <asm-generic/section-core.h>
+
+#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 2b892e2313a9..af975f21eeee 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
+generic-y += section-core.h
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index b7fbaa56b51a..7879c31e66a7 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..bb16befc4251
--- /dev/null
+++ b/include/asm-generic/section-core.h
@@ -0,0 +1,307 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Linux ELF program specific sections
+ *
+ * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and
+ * definition of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
+ * sections. This chaper is dedicated to documenting Linux program specific
+ * sections and helpers available to make use of these easier to implement and
+ * use.
+ *
+ * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
+ */
+
+/**
+ * DOC: Linux linker script
+ *
+ * Linux uses a custom linker script to build the vmlinux binary, it uses it to
+ * strategically place and define Linux ELF sections.  Each architecture needs
+ * to implement its own linker script, it is expected to reside in
+ * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
+ * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
+ * as well as some helpers documented in this chapter.
+ *
+ * In assembly it is common practice to use dots (``.``) in labels to avoid
+ * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
+ * name but not a C symbol. Historically then, two dots are used (``..``)
+ * have been used in linker scripts when adding program specific sections
+ * when there are concerns to avoid clashes with compiler generated sections.
+ */
+
+/**
+ * DOC: Memory protection
+ *
+ * Linux allows architectures which support memory protection features to
+ * take advantage of them by letting architectures define and enable
+ * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.
+ * mark_rodata_ro() can be used for instance to mark specific sections as
+ * read-only or non-executable.
+ *
+ * Linux typically follows a convention to have the .rodata ELF section follow
+ * after the .text ELF section, it does this to help architectures which
+ * support memory protection to mark both .text and .rodata as read-only in
+ * one shot.
+ *
+ * For more details refer to mark_rodata_ro().
+ */
+
+/**
+ * DOC: .rodata
+ *
+ * ELF section used for data which must be protected from write access.
+ */
+
+/**
+ * DOC: .text
+ *
+ * ELF section name used for code (functions) used during regular
+ * kernel run time.
+ */
+
+/**
+ * DOC: .data
+ *
+ * ELF section used for read-write data.
+ */
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: .init.text
+ *
+ * ELF section for code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+
+/**
+ * DOC: .init.data
+ *
+ * ELF section used for data structures used only during boot or driver
+ * initialization.
+ */
+
+/**
+ * DOC: .init.rodata
+ *
+ * ELF section used for read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+
+/**
+ * DOC: .initcall
+ *
+ * ELF section used for subsystem init calls. There are init levels
+ * representing different functionality in the kernel. For more details
+ * refer to __define_initcall().
+ */
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: .exit.text
+ *
+ * ELF section used to for code (functions) used only during module unload.
+ */
+
+/**
+ * DOC: .exit.data
+ *
+ * ELF section used to for data structures used only during module
+ * unload.
+ */
+
+/**
+ * DOC: .exitcall.exit
+ *
+ * ELF section used for exit routines, order is important and maintained by
+ * link order.
+ */
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: .ref.text
+ *
+ * ELF section used to annotate code (functions) which has been vetteed as
+ * valid for its reference or use of other code (functions) or data structures
+ * which are part of the init sections.
+ */
+
+/**
+ * DOC: .ref.data
+ *
+ * ELF section used for data structures which have been vetteed for its
+ * reference or use of other code (functions) or data structures part of the
+ * init sections.
+ */
+
+/**
+ * DOC: .ref.rodata
+ *
+ * ELF section used to annotate const code (functions) const data structures
+ * which has been vetteed for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section..___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section..__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifndef LINKER_SCRIPT
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align=16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 4df64a1fc09e..b145ae8d9cbe 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_GENERIC_SECTIONS_H_
 #define _ASM_GENERIC_SECTIONS_H_
 
+#include <asm/section-core.h>
+
 /* References to section boundaries */
 
 #include <linux/compiler.h>
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 0968d13b3885..483f60c451f9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -55,6 +55,7 @@
 #endif
 
 #include <linux/export.h>
+#include <asm/section-core.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
diff --git a/include/linux/init.h b/include/linux/init.h
index 885c3e6d0f9d..116e3262332a 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -130,6 +130,24 @@ int __init init_rootfs(void);
 extern bool rodata_enabled;
 #endif
 #ifdef CONFIG_DEBUG_RODATA
+/**
+ * mark_rodata_ro - implemement memory protection for ELF sections
+ *
+ * Architectures which support memory protection define a kernel configuration
+ * entry for CONFIG_DEBUG_RODATA, enable it in and implement mark_rodata_ro().
+ * mark_rodata_ro() should strive to adjust the .rodata and .text ELF sections
+ * with read-only memory protection to prevent modifications of these sections
+ * after bootup. It can also try to use memory protection to prevent execution
+ * on the .rodata ELF section.
+ *
+ * In order to help architectures set both .text and .rodata as read-only with
+ * memory protections in one shot Linux has typically followed the convention
+ * to have the .rodata ELF section follow the .text ELF section on the vmlinux
+ * linker script.
+ *
+ * Linux calls mark_rodata_ro() after freeing .init code and prior to calling
+ * the first init userspace process.
+ */
 void mark_rodata_ro(void);
 #endif
 
@@ -140,25 +158,70 @@ extern bool initcall_debug;
 #endif
   
 #ifndef MODULE
+/**
+ * DOC: Initcall levels
+ *
+ * When Linux boots the kernel do_initcalls() iterates over each Linux
+ * initialization level ID and calls all routines embedded on each level ID.
+ * Prior to v2.5.2.3 Linux had only one init level onto which all init
+ * functions folded onto using __initcall(). After v2.5.2.4 Linux split up
+ * initcalls into 7 separate initcall subsection levels, each level describing
+ * different functionality part of the kernel (commit `9d6ba121b7e17085`_
+ * (v2.5.2.3 -> v2.5.2.4)). In order to remain backward compatible __initcall()
+ * calls were left mapped to device_initcall().
+ *
+ * Each init level consists of a dedicated ELF section, init functions are
+ * associated to an init level by linking it into the respective level's
+ * ELF section.
+ *
+ * Lower order init levels run prior to higher order init levels. Ordering
+ * inside each initcall level is determined by respective link order.
+ *
+ * .. _9d6ba121b7e17085: https://git.kernel.org/cgit/linux/kernel/git/history/history.git/commit/?id=9d6ba121b7e17085c95139233686b27a4d4c650e
+ */
 
 #ifndef __ASSEMBLY__
 
-/*
- * initcalls are now grouped by functionality into separate
- * subsections. Ordering inside the subsections is determined
- * by link order. 
- * For backwards compatibility, initcall() puts the call in 
- * the device init subsection.
+/**
+ * __define_initcall - wrapper for definiting init levels
  *
- * The `id' arg to __define_initcall() is needed so that multiple initcalls
- * can point at the same handler without causing duplicate-symbol build errors.
+ * @fn: init routine
+ * @id: init level
  *
- * Initcalls are run by placing pointers in initcall sections that the
- * kernel iterates at runtime. The linker can do dead code / data elimination
- * and remove that completely, so the initcall sections have to be marked
- * as KEEP() in the linker script.
+ * Defines a kernel initialization level. A respective linker script entry
+ * is required to ensure the init level is accounted for and to ensure symbols
+ * exist for iterating over all functions in the init level. A init level
+ * represents a series of functionality in the kernel.
+ *
+ * Ordering within an initialization level is determined by link order, so
+ * for instance if a Makefile had::
+ *
+ *	obj-y += foo.o
+ *	obj-y += bar.o
+ *
+ * And foo.c::
+ *
+ *	subsys_initcall(foo_init);
+ *
+ * And bar.c had::
+ *
+ *	subsys_initcall(bar_init);
+ *
+ * foo_init() would be called prior to bar_init().
+ *
+ * Note that @id in __define_initcall() also enables multiple initcalls
+ * to be created using the same handler for different init levels without
+ * causing duplicate-symbol build errors.
+ *
+ * Initcalls are run by placing start symbols to initcall levels inside ELF
+ * sections, the kernel in turn uses these symbols to iterate over each init
+ * level at runtime with do_initcall_level(). The end of each init level is
+ * marked by the subsequent's symbol's start address until we reach the symbol
+ * ``__initcall_end``. The linker can do dead code / data elimination and each
+ * init level start symbol could be removed completely in this process, to
+ * avoid this each init level start symbols must be marked as 'KEEP()' in the
+ * linker script to avoid any linker optimization heuristic on initcalls.
  */
-
 #define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
 	__attribute__((__section__(".initcall" #id ".init"))) = fn;
diff --git a/include/linux/sections.h b/include/linux/sections.h
new file mode 100644
index 000000000000..6771c727bcd1
--- /dev/null
+++ b/include/linux/sections.h
@@ -0,0 +1,87 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_CORE(section, core, name, level)			\
+	#section ".." #core "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 01/14] generic-sections: add section core helpers
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="windows-1254", Size: 47016 bytes --]

Linux makes extensive use of custom ELF header sections,
documentation for these are well scatterred. Unify this
documentation in a central place and provide helpers to
build custom Linux sections.

This also generalizes sections code to enable avoiding
modifying the linker scripts when we want to add new
custom Linux sections. In order to make this generally
useful we need to ensure all architectures can make use of
core section helpers but that they can also override should
this be needed. Instead of relying on section.h this adds
a sections-core.h since this will be targetted to be safe
to be used on asm code, linker scripts and C code.

v5:

o Huge documentation revamp based on a careful review of the ELF
  specifications. Includes documentation now also about usage of
  two dots (..) when prefixing ELF program specific sections.

o Replace macros for sections names in favor of just using
  the section names explicitly in the linker script. This is
  perhaps more work to grep but this is what folks seem to
  currently prefer.

o Fix .text and .rodata documentation to explain memory protection
  strategies which architectures can embrace upon initialization
  (documents CONFIG_DEBUG_RODATA and mark_rodata_ro())

o Skip the 'Linux section ordering' documentation section, we'll instead
  add this on subsequent patch which will expand on it considerably

o Dropped tree on MAINTAINERS -- as per discussions with Arnd, hpa and
  Josh, its easier to just let changes for sections go in through the
  respective tree that needs the changes.

o Fix typos on documentation

o Dropped SECTION_ALL(), __SECTION_CORE(), SECTION_CORE_ALL() macros
  since we are favoring using explicit section names. These are
  useless if we are being explicit.

o Drop LINUX_SECTION_SIZE(), LINUX_SECTION_EMPTY() in favor of having
  section ranges and linker tables define their own, to avoid confusion
  and make code more readable.

o Add __define_initcall() documentation and a small section describing
  our current initcall levels. This should help also clarify what was
  meant about keeping backward compatiblity.

v4:

o Port to shiny new sphinx documentation format

o fix a unicore32 build, turns out this actually fixes unicore32
  defconfig builds which were failing for a long while. unicore32
  does not seem to grok well the type passed on a section declaration,
  this ignores it.

o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
  this was causing final linker issues with blackfin -- this is
  a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
  being metatag. metatag is not supported on 0-day so I cannot confirm
  compilation there.

o Added SECTION_CORE() for C code, used later by __LINUX_RANGE()

o Since SECTION_CORE() is defined for linker script and C code, share
  the same helper and just use a __stringify() for the C code as is done
  for the other C helpers.

o move generic sections to asm-generic/section-core.h instead.
  PowerPC compilation blows up if asm/jump_labels.h gets
  section.h included, fixing this is not in any way easy.
  The list of issues are endless. Moving new data to a new
  simple file resolves this.

o since things are now in asm-generic/section-core.h the
  guard changes on asm-generic/sections.h and each architecture
  sections.h are no longer needed

o Give generic sections some maintainer love, that change is
  Acked-by Arnd Bergmann, Josh and hpa.

o A few checkpatch.pl style fixes

o As suggested by James Hogan use generic-y to copy generic
  header files on architectures that do not have a sections.h
  instead of writing a simple file only to include the generic one.

v3:

o add missing sections.h for architectures that did not
  have it

o move generic sections to asm-generic/sections.h

o add generic asm helpers section_type(), section_type_asmtype(),
  push_section_type() -- these helpers enable easy use for
  for later declaring and using of custom linux sections using
  more standard APIs in both C code, asm code (C asm calls, or
  asm files), enabling future standardized section types to
  be more immediately accessible to asm code, not just C code.
  Note for ASM_CMD_SEP we use by default "\n", architectures needed
  to override can do so on their own sections.h prior to inclusion
  of asm-generic/sections.h

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/index.rst                   |   1 +
 Documentation/sections/background.rst     | 105 ++++++++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  17 ++
 Documentation/sections/section-core.rst   | 148 ++++++++++++++
 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/Kbuild               |   1 +
 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/section-core.h |  19 ++
 arch/x86/include/asm/Kbuild               |   1 +
 arch/xtensa/include/asm/Kbuild            |   1 +
 include/asm-generic/section-core.h        | 307 ++++++++++++++++++++++++++++++
 include/asm-generic/sections.h            |   2 +
 include/asm-generic/vmlinux.lds.h         |   1 +
 include/linux/init.h                      |  89 +++++++--
 include/linux/sections.h                  |  87 +++++++++
 42 files changed, 809 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/linux/sections.h

diff --git a/Documentation/index.rst b/Documentation/index.rst
index cb5d77699c60..71e0305c036d 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -57,6 +57,7 @@ needed).
    media/index
    gpu/index
    security/index
+   sections/index
    sound/index
    crypto/index
 
diff --git a/Documentation/sections/background.rst b/Documentation/sections/background.rst
new file mode 100644
index 000000000000..0ecf9104aaa2
--- /dev/null
+++ b/Documentation/sections/background.rst
@@ -0,0 +1,105 @@
+===========
+ELF section background
+===========
+
+About
+==+
+The purpose of this chapter is to help those not familiar with ELF to brush up
+the latest ELF specifications in order to help understand how Linux uses and
+defines its own ELF sections.
+
+Standardized ELF
+========
+
+The first publication documenting ELF was UNIX System Laboratories' (USL)
+*System V Release 4 Application Binary Interface* (`SRV4 ABI`_) specification.
+Originally ELF was only a small part of the SRV4 ABI, with time however new
+specifications only put focus on ELF, such was the case of the *TIS Portable
+Formats Specification version 1.2* (`TIS 1.2`_). As of TIS 1.2, ELF was
+supplemented with processor specific ELF addendums, available on the *Linux
+Foundation referenced specification page* (`LF ref page`_). The latest ELF
+specification is the *System V Application Binary Interface - DRAFT - 24 April
+2001* (`gabi4`_).
+
+.. _SRV4 ABI: http://www.sco.com/developers/devspecs/gabi41.pdf
+.. _TIS 1.2: https://refspecs.linuxbase.org/elf/elf.pdf
+.. _LF ref page: https://refspecs.linuxbase.org/
+.. _gabi4: https://refspecs.linuxbase.org/elf/gabi4+/contents.html
+
+ELF views on Linux
+=========
+
+There are two views which can be used for inspecting data in an ELF file, a
+Linking view, and an Execution view. A Section Header Table enables one to
+describe an object using the Linking view while a Program Header Table enables
+one to describe an object using the Execution view. The views are not mutually
+exclusive. For intance, vmlinux can be viewed under both views, ``readelf -S
+vmlinux`` for the Linking view, and ``readelf -l vmlinux`` for the Execution
+view.  In Linux only the vmlinux file will have an Execution view, even modules
+lack an Execution view given that vmlinux is the only file that describes how
+the the kernel runs from the start.  All other Linux kernel object files have
+an available Linking view.
+
+Under the Linking view, the Section Header Table describes all available
+sections. The Section Header Table is an array of ELF section header data
+structures. If on a 32-bit system this is ``struct elf32_shd``, if on a 64-bit
+this is ``struct elf64_shdr``. Sections are only visible on object files that
+have a Linking view, since all Linux kernel files have Linking view, all kernel
+objects have ELF sections.
+
+Limitations on ELF sections
+=============+
+We provide a summary on the limitations of ELF sections. Refer to the public
+ELF specifications for details. Note that 64-bit limitations may depend
+on processor specific section attributes to be used, refer to your processsor
+specification if unsure.
+
+Its worth ellaborating on the limitations on the name of an ELF section:
+ELF section names are stored as strings as per the ELF specification, and
+as can be expected, these don't have explicit limitations. The implicit
+limitation then depends on the size of an ELF object file and ELF section.
+
+If using really large kernels or objects with large amounts of sections one
+would still need to be sure that ELF loader in charge of loading the Linux
+kernel is properly updated to handle coping with the latest ELF extensions.
+
+   .. flat-table:: Limitations on ELF Sections
+
+      * - Section attribute
+        - 32-bit
+        - 64-bit
+
+      * - ELF section name
+        - Size of an ELF section
+        - Size of an ELF section
+
+      * - Size of an ELF section
+        - 4 GiB
+        - 16 EiB
+
+      * - Max number of sections in an object file
+        - 4 GiEntries (4294967296)
+        - 16 EiEntries (18446744073709551616)
+
+Program specific ELF sections
+==============+
+The ELF specification allows for a section type to be specified as
+*Program specific section*, defined as ``SHT_PROGBITS``. This sections type
+enables programs to customize sections for their own use. In assembly this
+specified ``@progbits`` on most architectures, on ARM this is ``%progbits``.
+
+``SHT_PROGBITS`` is used by Linux for defining and using Linux ELF sections.
+
+Special ELF Sections
+==========
+
+The ELF specification defines *Special ELF Sections* on chapter 4 (`gabi4
+ch4`_). These are defined as sections which hold program and control
+information. Of these sections, a few have the section type as
+``SHT_PROGBITS``. This enables Linux to *further customize* use of the section
+beyond what the ELF specification suggests.
+
+.. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
new file mode 100644
index 000000000000..faa1c57595e1
--- /dev/null
+++ b/Documentation/sections/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel ELF sections'
+html_search_language = 'en'
diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
new file mode 100644
index 000000000000..f37511ef05e7
--- /dev/null
+++ b/Documentation/sections/index.rst
@@ -0,0 +1,17 @@
+============+Linux Kernel ELF sections
+============+
+This book documents the different ELF sections used on the Linux kernel.
+We start off by providing references to how ELF was standardized, references
+to the standards on ELF sections, review limitations of ELF sections, and
+finally how Linux uses ELF sections in the Linux kernel. Certain important
+Linux ELF sections are documented carefully: we describe the goal of the
+ELF section, and address concurrency considerations when applicable. A few
+common a set of Linux helpers for ELF sections are also documented.
+
+.. toctree::
+   :maxdepth: 4
+
+   background
+   section-core
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
new file mode 100644
index 000000000000..ac5815a0d9b3
--- /dev/null
+++ b/Documentation/sections/section-core.rst
@@ -0,0 +1,148 @@
+=================+Linux ELF program specific sections
+=================+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux ELF program specific sections
+
+Linux linker script
+=========+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux linker script
+
+Memory protection
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Memory protection
+
+mark_rodata_ro
+-----------------------
+.. kernel-doc:: include/linux/init.h
+   :functions: mark_rodata_ro
+
+.rodata
+-------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .rodata
+
+.text
+-----
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .text
+
+.data
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .data
+
+Linux .init\* sections
+===========
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux init sections
+
+.init.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.text
+
+.init.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.data
+
+.init.rodata
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.rodata
+
+Initcall levels
+---------------
+.. kernel-doc:: include/linux/init.h
+   :doc: Initcall levels
+
+.initcall
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .initcall
+
+__define_initcall
+-----------------
+.. kernel-doc:: include/linux/init.h
+   :functions: __define_initcall
+
+Linux .exit\* sections
+===========
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux exit sections
+
+.exit.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.text
+
+.exit.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.data
+
+.exitcall.exit
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exitcall.exit
+
+Linux .ref\* sections
+==========+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux references to init sections
+
+.ref.text
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.text
+
+.ref.data
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.data
+
+.ref.rodata
+-----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.rodata
+
+Generic Linux kernel section helpers
+==================
+
+Introduction
+-------------
+.. kernel-doc:: include/linux/sections.h
+   :doc: Introduction
+
+LINUX_SECTION_ALIGNMENT
+-----------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_ALIGNMENT
+
+LINUX_SECTION_START
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_START
+
+LINUX_SECTION_END
+-----------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_END
+
+DECLARE_LINUX_SECTION
+---------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION
+
+DECLARE_LINUX_SECTION_RO
+------------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION_RO
diff --git a/MAINTAINERS b/MAINTAINERS
index c68a6bb17966..ae86136f4b9a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5424,6 +5424,18 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTIONS
+M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
+M:	Josh Poimboeuf <jpoimboe@redhat.com>
+M:	"H. Peter Anvin" <hpa@zytor.com>
+L:	linux-arch@vger.kernel.org
+L:	linux-kernel@vger.kernel.org
+S:	Supported
+F:	include/asm-generic/section-core.h
+F:	include/asm-generic/sections.h
+F:	include/asm-generic/vmlinux.lds.h
+F:	Documentation/sections/section-core.rst
+
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index bf8475ce85ee..5422827f1585 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += section-core.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index c332604606dd..7b2cb3dea5fc 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index efb21757d41f..9b69a22a9ae1 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += unaligned.h
 
 generated-y += mach-types.h
 generated-y += unistd-nr.h
+generic-y += section-core.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 8365a84c2640..00ace5e826f1 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 241b9b9729d8..f2c3b656a0e7 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 2fb67b59d188..bf20541bcf21 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -47,3 +47,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 64465e7e2245..38127ce747be 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -62,3 +62,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 1778805f6380..385cd88a9d9e 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += types.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 1fa084cf1a43..46d7c599d9b8 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 373cb23301e3..1ec04ec1c82b 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -75,3 +75,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index db8ddabc6bd2..37d7bfae7619 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -60,3 +60,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 502a91d8dbbd..672c6d5da18c 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 860e440611c9..6111e1523750 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1f2e5d31cb24..1277b45bf4f9 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -34,3 +34,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 167150c701d1..b1011375cd7a 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -55,3 +55,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index b0ae88c9fed9..c6c2cf6edc98 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index ed07179fe26a..7a932b4a5531 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 1c8dd0f5cd5d..f8145bc85835 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index d63330e88379..c9c7cb82b00f 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 2832f031fb11..86175e701869 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -71,3 +71,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 91f53c07f410..18a9d4c5ead7 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -28,3 +28,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 5c4fbc80dc6c..4322d9746cdb 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
+generic-y += section-core.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 8aea32fe8bd2..63a1c2924b91 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index a05218ff3fe4..f089a264cd38 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 751c3373a92c..7b0356dca562 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 0569bfac4afb..438f86573dc5 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 2d1f5638974c..fb6b831c1fba 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 052f7f6d0551..580bd5ff828f 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -26,3 +26,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
new file mode 100644
index 000000000000..0b9c68429a1a
--- /dev/null
+++ b/arch/unicore32/include/asm/section-core.h
@@ -0,0 +1,19 @@
+#ifndef __UNICORE_SECTION_CORE_ASM_H__
+#define __UNICORE_SECTION_CORE_ASM_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/.
+ */
+
+/* Unicore32 has known to not work properly with the type set, so ignore it */
+
+#define __set_section_core_type(___section, ___core, ___name,		\
+				___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags
+
+#include <asm-generic/section-core.h>
+
+#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 2b892e2313a9..af975f21eeee 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
+generic-y += section-core.h
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index b7fbaa56b51a..7879c31e66a7 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..bb16befc4251
--- /dev/null
+++ b/include/asm-generic/section-core.h
@@ -0,0 +1,307 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Linux ELF program specific sections
+ *
+ * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and
+ * definition of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
+ * sections. This chaper is dedicated to documenting Linux program specific
+ * sections and helpers available to make use of these easier to implement and
+ * use.
+ *
+ * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
+ */
+
+/**
+ * DOC: Linux linker script
+ *
+ * Linux uses a custom linker script to build the vmlinux binary, it uses it to
+ * strategically place and define Linux ELF sections.  Each architecture needs
+ * to implement its own linker script, it is expected to reside in
+ * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
+ * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
+ * as well as some helpers documented in this chapter.
+ *
+ * In assembly it is common practice to use dots (``.``) in labels to avoid
+ * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
+ * name but not a C symbol. Historically then, two dots are used (``..``)
+ * have been used in linker scripts when adding program specific sections
+ * when there are concerns to avoid clashes with compiler generated sections.
+ */
+
+/**
+ * DOC: Memory protection
+ *
+ * Linux allows architectures which support memory protection features to
+ * take advantage of them by letting architectures define and enable
+ * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.
+ * mark_rodata_ro() can be used for instance to mark specific sections as
+ * read-only or non-executable.
+ *
+ * Linux typically follows a convention to have the .rodata ELF section follow
+ * after the .text ELF section, it does this to help architectures which
+ * support memory protection to mark both .text and .rodata as read-only in
+ * one shot.
+ *
+ * For more details refer to mark_rodata_ro().
+ */
+
+/**
+ * DOC: .rodata
+ *
+ * ELF section used for data which must be protected from write access.
+ */
+
+/**
+ * DOC: .text
+ *
+ * ELF section name used for code (functions) used during regular
+ * kernel run time.
+ */
+
+/**
+ * DOC: .data
+ *
+ * ELF section used for read-write data.
+ */
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: .init.text
+ *
+ * ELF section for code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+
+/**
+ * DOC: .init.data
+ *
+ * ELF section used for data structures used only during boot or driver
+ * initialization.
+ */
+
+/**
+ * DOC: .init.rodata
+ *
+ * ELF section used for read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+
+/**
+ * DOC: .initcall
+ *
+ * ELF section used for subsystem init calls. There are init levels
+ * representing different functionality in the kernel. For more details
+ * refer to __define_initcall().
+ */
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: .exit.text
+ *
+ * ELF section used to for code (functions) used only during module unload.
+ */
+
+/**
+ * DOC: .exit.data
+ *
+ * ELF section used to for data structures used only during module
+ * unload.
+ */
+
+/**
+ * DOC: .exitcall.exit
+ *
+ * ELF section used for exit routines, order is important and maintained by
+ * link order.
+ */
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: .ref.text
+ *
+ * ELF section used to annotate code (functions) which has been vetteed as
+ * valid for its reference or use of other code (functions) or data structures
+ * which are part of the init sections.
+ */
+
+/**
+ * DOC: .ref.data
+ *
+ * ELF section used for data structures which have been vetteed for its
+ * reference or use of other code (functions) or data structures part of the
+ * init sections.
+ */
+
+/**
+ * DOC: .ref.rodata
+ *
+ * ELF section used to annotate const code (functions) const data structures
+ * which has been vetteed for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section..___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section..__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifndef LINKER_SCRIPT
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align\x16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 4df64a1fc09e..b145ae8d9cbe 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_GENERIC_SECTIONS_H_
 #define _ASM_GENERIC_SECTIONS_H_
 
+#include <asm/section-core.h>
+
 /* References to section boundaries */
 
 #include <linux/compiler.h>
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 0968d13b3885..483f60c451f9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -55,6 +55,7 @@
 #endif
 
 #include <linux/export.h>
+#include <asm/section-core.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
diff --git a/include/linux/init.h b/include/linux/init.h
index 885c3e6d0f9d..116e3262332a 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -130,6 +130,24 @@ int __init init_rootfs(void);
 extern bool rodata_enabled;
 #endif
 #ifdef CONFIG_DEBUG_RODATA
+/**
+ * mark_rodata_ro - implemement memory protection for ELF sections
+ *
+ * Architectures which support memory protection define a kernel configuration
+ * entry for CONFIG_DEBUG_RODATA, enable it in and implement mark_rodata_ro().
+ * mark_rodata_ro() should strive to adjust the .rodata and .text ELF sections
+ * with read-only memory protection to prevent modifications of these sections
+ * after bootup. It can also try to use memory protection to prevent execution
+ * on the .rodata ELF section.
+ *
+ * In order to help architectures set both .text and .rodata as read-only with
+ * memory protections in one shot Linux has typically followed the convention
+ * to have the .rodata ELF section follow the .text ELF section on the vmlinux
+ * linker script.
+ *
+ * Linux calls mark_rodata_ro() after freeing .init code and prior to calling
+ * the first init userspace process.
+ */
 void mark_rodata_ro(void);
 #endif
 
@@ -140,25 +158,70 @@ extern bool initcall_debug;
 #endif
   
 #ifndef MODULE
+/**
+ * DOC: Initcall levels
+ *
+ * When Linux boots the kernel do_initcalls() iterates over each Linux
+ * initialization level ID and calls all routines embedded on each level ID.
+ * Prior to v2.5.2.3 Linux had only one init level onto which all init
+ * functions folded onto using __initcall(). After v2.5.2.4 Linux split up
+ * initcalls into 7 separate initcall subsection levels, each level describing
+ * different functionality part of the kernel (commit `9d6ba121b7e17085`_
+ * (v2.5.2.3 -> v2.5.2.4)). In order to remain backward compatible __initcall()
+ * calls were left mapped to device_initcall().
+ *
+ * Each init level consists of a dedicated ELF section, init functions are
+ * associated to an init level by linking it into the respective level's
+ * ELF section.
+ *
+ * Lower order init levels run prior to higher order init levels. Ordering
+ * inside each initcall level is determined by respective link order.
+ *
+ * .. _9d6ba121b7e17085: https://git.kernel.org/cgit/linux/kernel/git/history/history.git/commit/?id6ba121b7e17085c95139233686b27a4d4c650e
+ */
 
 #ifndef __ASSEMBLY__
 
-/*
- * initcalls are now grouped by functionality into separate
- * subsections. Ordering inside the subsections is determined
- * by link order. 
- * For backwards compatibility, initcall() puts the call in 
- * the device init subsection.
+/**
+ * __define_initcall - wrapper for definiting init levels
  *
- * The `id' arg to __define_initcall() is needed so that multiple initcalls
- * can point at the same handler without causing duplicate-symbol build errors.
+ * @fn: init routine
+ * @id: init level
  *
- * Initcalls are run by placing pointers in initcall sections that the
- * kernel iterates at runtime. The linker can do dead code / data elimination
- * and remove that completely, so the initcall sections have to be marked
- * as KEEP() in the linker script.
+ * Defines a kernel initialization level. A respective linker script entry
+ * is required to ensure the init level is accounted for and to ensure symbols
+ * exist for iterating over all functions in the init level. A init level
+ * represents a series of functionality in the kernel.
+ *
+ * Ordering within an initialization level is determined by link order, so
+ * for instance if a Makefile had::
+ *
+ *	obj-y += foo.o
+ *	obj-y += bar.o
+ *
+ * And foo.c::
+ *
+ *	subsys_initcall(foo_init);
+ *
+ * And bar.c had::
+ *
+ *	subsys_initcall(bar_init);
+ *
+ * foo_init() would be called prior to bar_init().
+ *
+ * Note that @id in __define_initcall() also enables multiple initcalls
+ * to be created using the same handler for different init levels without
+ * causing duplicate-symbol build errors.
+ *
+ * Initcalls are run by placing start symbols to initcall levels inside ELF
+ * sections, the kernel in turn uses these symbols to iterate over each init
+ * level at runtime with do_initcall_level(). The end of each init level is
+ * marked by the subsequent's symbol's start address until we reach the symbol
+ * ``__initcall_end``. The linker can do dead code / data elimination and each
+ * init level start symbol could be removed completely in this process, to
+ * avoid this each init level start symbols must be marked as 'KEEP()' in the
+ * linker script to avoid any linker optimization heuristic on initcalls.
  */
-
 #define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
 	__attribute__((__section__(".initcall" #id ".init"))) = fn;
diff --git a/include/linux/sections.h b/include/linux/sections.h
new file mode 100644
index 000000000000..6771c727bcd1
--- /dev/null
+++ b/include/linux/sections.h
@@ -0,0 +1,87 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_CORE(section, core, name, level)			\
+	#section ".." #core "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe sparclinux" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 01/14] generic-sections: add section core helpers
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt

Linux makes extensive use of custom ELF header sections,
documentation for these are well scatterred. Unify this
documentation in a central place and provide helpers to
build custom Linux sections.

This also generalizes sections code to enable avoiding
modifying the linker scripts when we want to add new
custom Linux sections. In order to make this generally
useful we need to ensure all architectures can make use of
core section helpers but that they can also override should
this be needed. Instead of relying on section.h this adds
a sections-core.h since this will be targetted to be safe
to be used on asm code, linker scripts and C code.

v5:

o Huge documentation revamp based on a careful review of the ELF
  specifications. Includes documentation now also about usage of
  two dots (..) when prefixing ELF program specific sections.

o Replace macros for sections names in favor of just using
  the section names explicitly in the linker script. This is
  perhaps more work to grep but this is what folks seem to
  currently prefer.

o Fix .text and .rodata documentation to explain memory protection
  strategies which architectures can embrace upon initialization
  (documents CONFIG_DEBUG_RODATA and mark_rodata_ro())

o Skip the 'Linux section ordering' documentation section, we'll instead
  add this on subsequent patch which will expand on it considerably

o Dropped tree on MAINTAINERS -- as per discussions with Arnd, hpa and
  Josh, its easier to just let changes for sections go in through the
  respective tree that needs the changes.

o Fix typos on documentation

o Dropped SECTION_ALL(), __SECTION_CORE(), SECTION_CORE_ALL() macros
  since we are favoring using explicit section names. These are
  useless if we are being explicit.

o Drop LINUX_SECTION_SIZE(), LINUX_SECTION_EMPTY() in favor of having
  section ranges and linker tables define their own, to avoid confusion
  and make code more readable.

o Add __define_initcall() documentation and a small section describing
  our current initcall levels. This should help also clarify what was
  meant about keeping backward compatiblity.

v4:

o Port to shiny new sphinx documentation format

o fix a unicore32 build, turns out this actually fixes unicore32
  defconfig builds which were failing for a long while. unicore32
  does not seem to grok well the type passed on a section declaration,
  this ignores it.

o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
  this was causing final linker issues with blackfin -- this is
  a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
  being metatag. metatag is not supported on 0-day so I cannot confirm
  compilation there.

o Added SECTION_CORE() for C code, used later by __LINUX_RANGE()

o Since SECTION_CORE() is defined for linker script and C code, share
  the same helper and just use a __stringify() for the C code as is done
  for the other C helpers.

o move generic sections to asm-generic/section-core.h instead.
  PowerPC compilation blows up if asm/jump_labels.h gets
  section.h included, fixing this is not in any way easy.
  The list of issues are endless. Moving new data to a new
  simple file resolves this.

o since things are now in asm-generic/section-core.h the
  guard changes on asm-generic/sections.h and each architecture
  sections.h are no longer needed

o Give generic sections some maintainer love, that change is
  Acked-by Arnd Bergmann, Josh and hpa.

o A few checkpatch.pl style fixes

o As suggested by James Hogan use generic-y to copy generic
  header files on architectures that do not have a sections.h
  instead of writing a simple file only to include the generic one.

v3:

o add missing sections.h for architectures that did not
  have it

o move generic sections to asm-generic/sections.h

o add generic asm helpers section_type(), section_type_asmtype(),
  push_section_type() -- these helpers enable easy use for
  for later declaring and using of custom linux sections using
  more standard APIs in both C code, asm code (C asm calls, or
  asm files), enabling future standardized section types to
  be more immediately accessible to asm code, not just C code.
  Note for ASM_CMD_SEP we use by default "\n", architectures needed
  to override can do so on their own sections.h prior to inclusion
  of asm-generic/sections.h

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/index.rst                   |   1 +
 Documentation/sections/background.rst     | 105 ++++++++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  17 ++
 Documentation/sections/section-core.rst   | 148 ++++++++++++++
 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/Kbuild               |   1 +
 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/section-core.h |  19 ++
 arch/x86/include/asm/Kbuild               |   1 +
 arch/xtensa/include/asm/Kbuild            |   1 +
 include/asm-generic/section-core.h        | 307 ++++++++++++++++++++++++++++++
 include/asm-generic/sections.h            |   2 +
 include/asm-generic/vmlinux.lds.h         |   1 +
 include/linux/init.h                      |  89 +++++++--
 include/linux/sections.h                  |  87 +++++++++
 42 files changed, 809 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/linux/sections.h

diff --git a/Documentation/index.rst b/Documentation/index.rst
index cb5d77699c60..71e0305c036d 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -57,6 +57,7 @@ needed).
    media/index
    gpu/index
    security/index
+   sections/index
    sound/index
    crypto/index
 
diff --git a/Documentation/sections/background.rst b/Documentation/sections/background.rst
new file mode 100644
index 000000000000..0ecf9104aaa2
--- /dev/null
+++ b/Documentation/sections/background.rst
@@ -0,0 +1,105 @@
+===========
+ELF section background
+===========
+
+About
+==+
+The purpose of this chapter is to help those not familiar with ELF to brush up
+the latest ELF specifications in order to help understand how Linux uses and
+defines its own ELF sections.
+
+Standardized ELF
+========
+
+The first publication documenting ELF was UNIX System Laboratories' (USL)
+*System V Release 4 Application Binary Interface* (`SRV4 ABI`_) specification.
+Originally ELF was only a small part of the SRV4 ABI, with time however new
+specifications only put focus on ELF, such was the case of the *TIS Portable
+Formats Specification version 1.2* (`TIS 1.2`_). As of TIS 1.2, ELF was
+supplemented with processor specific ELF addendums, available on the *Linux
+Foundation referenced specification page* (`LF ref page`_). The latest ELF
+specification is the *System V Application Binary Interface - DRAFT - 24 April
+2001* (`gabi4`_).
+
+.. _SRV4 ABI: http://www.sco.com/developers/devspecs/gabi41.pdf
+.. _TIS 1.2: https://refspecs.linuxbase.org/elf/elf.pdf
+.. _LF ref page: https://refspecs.linuxbase.org/
+.. _gabi4: https://refspecs.linuxbase.org/elf/gabi4+/contents.html
+
+ELF views on Linux
+=========
+
+There are two views which can be used for inspecting data in an ELF file, a
+Linking view, and an Execution view. A Section Header Table enables one to
+describe an object using the Linking view while a Program Header Table enables
+one to describe an object using the Execution view. The views are not mutually
+exclusive. For intance, vmlinux can be viewed under both views, ``readelf -S
+vmlinux`` for the Linking view, and ``readelf -l vmlinux`` for the Execution
+view.  In Linux only the vmlinux file will have an Execution view, even modules
+lack an Execution view given that vmlinux is the only file that describes how
+the the kernel runs from the start.  All other Linux kernel object files have
+an available Linking view.
+
+Under the Linking view, the Section Header Table describes all available
+sections. The Section Header Table is an array of ELF section header data
+structures. If on a 32-bit system this is ``struct elf32_shd``, if on a 64-bit
+this is ``struct elf64_shdr``. Sections are only visible on object files that
+have a Linking view, since all Linux kernel files have Linking view, all kernel
+objects have ELF sections.
+
+Limitations on ELF sections
+=============+
+We provide a summary on the limitations of ELF sections. Refer to the public
+ELF specifications for details. Note that 64-bit limitations may depend
+on processor specific section attributes to be used, refer to your processsor
+specification if unsure.
+
+Its worth ellaborating on the limitations on the name of an ELF section:
+ELF section names are stored as strings as per the ELF specification, and
+as can be expected, these don't have explicit limitations. The implicit
+limitation then depends on the size of an ELF object file and ELF section.
+
+If using really large kernels or objects with large amounts of sections one
+would still need to be sure that ELF loader in charge of loading the Linux
+kernel is properly updated to handle coping with the latest ELF extensions.
+
+   .. flat-table:: Limitations on ELF Sections
+
+      * - Section attribute
+        - 32-bit
+        - 64-bit
+
+      * - ELF section name
+        - Size of an ELF section
+        - Size of an ELF section
+
+      * - Size of an ELF section
+        - 4 GiB
+        - 16 EiB
+
+      * - Max number of sections in an object file
+        - 4 GiEntries (4294967296)
+        - 16 EiEntries (18446744073709551616)
+
+Program specific ELF sections
+==============+
+The ELF specification allows for a section type to be specified as
+*Program specific section*, defined as ``SHT_PROGBITS``. This sections type
+enables programs to customize sections for their own use. In assembly this
+specified ``@progbits`` on most architectures, on ARM this is ``%progbits``.
+
+``SHT_PROGBITS`` is used by Linux for defining and using Linux ELF sections.
+
+Special ELF Sections
+==========
+
+The ELF specification defines *Special ELF Sections* on chapter 4 (`gabi4
+ch4`_). These are defined as sections which hold program and control
+information. Of these sections, a few have the section type as
+``SHT_PROGBITS``. This enables Linux to *further customize* use of the section
+beyond what the ELF specification suggests.
+
+.. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
new file mode 100644
index 000000000000..faa1c57595e1
--- /dev/null
+++ b/Documentation/sections/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel ELF sections'
+html_search_language = 'en'
diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
new file mode 100644
index 000000000000..f37511ef05e7
--- /dev/null
+++ b/Documentation/sections/index.rst
@@ -0,0 +1,17 @@
+============+Linux Kernel ELF sections
+============+
+This book documents the different ELF sections used on the Linux kernel.
+We start off by providing references to how ELF was standardized, references
+to the standards on ELF sections, review limitations of ELF sections, and
+finally how Linux uses ELF sections in the Linux kernel. Certain important
+Linux ELF sections are documented carefully: we describe the goal of the
+ELF section, and address concurrency considerations when applicable. A few
+common a set of Linux helpers for ELF sections are also documented.
+
+.. toctree::
+   :maxdepth: 4
+
+   background
+   section-core
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
new file mode 100644
index 000000000000..ac5815a0d9b3
--- /dev/null
+++ b/Documentation/sections/section-core.rst
@@ -0,0 +1,148 @@
+=================+Linux ELF program specific sections
+=================+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux ELF program specific sections
+
+Linux linker script
+=========+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux linker script
+
+Memory protection
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Memory protection
+
+mark_rodata_ro
+-----------------------
+.. kernel-doc:: include/linux/init.h
+   :functions: mark_rodata_ro
+
+.rodata
+-------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .rodata
+
+.text
+-----
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .text
+
+.data
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .data
+
+Linux .init\* sections
+===========
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux init sections
+
+.init.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.text
+
+.init.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.data
+
+.init.rodata
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.rodata
+
+Initcall levels
+---------------
+.. kernel-doc:: include/linux/init.h
+   :doc: Initcall levels
+
+.initcall
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .initcall
+
+__define_initcall
+-----------------
+.. kernel-doc:: include/linux/init.h
+   :functions: __define_initcall
+
+Linux .exit\* sections
+===========
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux exit sections
+
+.exit.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.text
+
+.exit.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.data
+
+.exitcall.exit
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exitcall.exit
+
+Linux .ref\* sections
+==========+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux references to init sections
+
+.ref.text
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.text
+
+.ref.data
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.data
+
+.ref.rodata
+-----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.rodata
+
+Generic Linux kernel section helpers
+==================
+
+Introduction
+-------------
+.. kernel-doc:: include/linux/sections.h
+   :doc: Introduction
+
+LINUX_SECTION_ALIGNMENT
+-----------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_ALIGNMENT
+
+LINUX_SECTION_START
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_START
+
+LINUX_SECTION_END
+-----------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_END
+
+DECLARE_LINUX_SECTION
+---------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION
+
+DECLARE_LINUX_SECTION_RO
+------------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION_RO
diff --git a/MAINTAINERS b/MAINTAINERS
index c68a6bb17966..ae86136f4b9a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5424,6 +5424,18 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTIONS
+M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
+M:	Josh Poimboeuf <jpoimboe@redhat.com>
+M:	"H. Peter Anvin" <hpa@zytor.com>
+L:	linux-arch@vger.kernel.org
+L:	linux-kernel@vger.kernel.org
+S:	Supported
+F:	include/asm-generic/section-core.h
+F:	include/asm-generic/sections.h
+F:	include/asm-generic/vmlinux.lds.h
+F:	Documentation/sections/section-core.rst
+
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index bf8475ce85ee..5422827f1585 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += section-core.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index c332604606dd..7b2cb3dea5fc 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index efb21757d41f..9b69a22a9ae1 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += unaligned.h
 
 generated-y += mach-types.h
 generated-y += unistd-nr.h
+generic-y += section-core.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 8365a84c2640..00ace5e826f1 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 241b9b9729d8..f2c3b656a0e7 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 2fb67b59d188..bf20541bcf21 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -47,3 +47,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 64465e7e2245..38127ce747be 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -62,3 +62,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 1778805f6380..385cd88a9d9e 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += types.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 1fa084cf1a43..46d7c599d9b8 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 373cb23301e3..1ec04ec1c82b 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -75,3 +75,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index db8ddabc6bd2..37d7bfae7619 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -60,3 +60,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 502a91d8dbbd..672c6d5da18c 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 860e440611c9..6111e1523750 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1f2e5d31cb24..1277b45bf4f9 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -34,3 +34,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 167150c701d1..b1011375cd7a 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -55,3 +55,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index b0ae88c9fed9..c6c2cf6edc98 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index ed07179fe26a..7a932b4a5531 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 1c8dd0f5cd5d..f8145bc85835 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index d63330e88379..c9c7cb82b00f 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 2832f031fb11..86175e701869 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -71,3 +71,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 91f53c07f410..18a9d4c5ead7 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -28,3 +28,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 5c4fbc80dc6c..4322d9746cdb 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
+generic-y += section-core.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 8aea32fe8bd2..63a1c2924b91 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index a05218ff3fe4..f089a264cd38 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 751c3373a92c..7b0356dca562 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 0569bfac4afb..438f86573dc5 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 2d1f5638974c..fb6b831c1fba 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 052f7f6d0551..580bd5ff828f 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -26,3 +26,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
new file mode 100644
index 000000000000..0b9c68429a1a
--- /dev/null
+++ b/arch/unicore32/include/asm/section-core.h
@@ -0,0 +1,19 @@
+#ifndef __UNICORE_SECTION_CORE_ASM_H__
+#define __UNICORE_SECTION_CORE_ASM_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/.
+ */
+
+/* Unicore32 has known to not work properly with the type set, so ignore it */
+
+#define __set_section_core_type(___section, ___core, ___name,		\
+				___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags
+
+#include <asm-generic/section-core.h>
+
+#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 2b892e2313a9..af975f21eeee 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
+generic-y += section-core.h
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index b7fbaa56b51a..7879c31e66a7 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..bb16befc4251
--- /dev/null
+++ b/include/asm-generic/section-core.h
@@ -0,0 +1,307 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Linux ELF program specific sections
+ *
+ * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and
+ * definition of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
+ * sections. This chaper is dedicated to documenting Linux program specific
+ * sections and helpers available to make use of these easier to implement and
+ * use.
+ *
+ * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
+ */
+
+/**
+ * DOC: Linux linker script
+ *
+ * Linux uses a custom linker script to build the vmlinux binary, it uses it to
+ * strategically place and define Linux ELF sections.  Each architecture needs
+ * to implement its own linker script, it is expected to reside in
+ * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
+ * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
+ * as well as some helpers documented in this chapter.
+ *
+ * In assembly it is common practice to use dots (``.``) in labels to avoid
+ * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
+ * name but not a C symbol. Historically then, two dots are used (``..``)
+ * have been used in linker scripts when adding program specific sections
+ * when there are concerns to avoid clashes with compiler generated sections.
+ */
+
+/**
+ * DOC: Memory protection
+ *
+ * Linux allows architectures which support memory protection features to
+ * take advantage of them by letting architectures define and enable
+ * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.
+ * mark_rodata_ro() can be used for instance to mark specific sections as
+ * read-only or non-executable.
+ *
+ * Linux typically follows a convention to have the .rodata ELF section follow
+ * after the .text ELF section, it does this to help architectures which
+ * support memory protection to mark both .text and .rodata as read-only in
+ * one shot.
+ *
+ * For more details refer to mark_rodata_ro().
+ */
+
+/**
+ * DOC: .rodata
+ *
+ * ELF section used for data which must be protected from write access.
+ */
+
+/**
+ * DOC: .text
+ *
+ * ELF section name used for code (functions) used during regular
+ * kernel run time.
+ */
+
+/**
+ * DOC: .data
+ *
+ * ELF section used for read-write data.
+ */
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: .init.text
+ *
+ * ELF section for code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+
+/**
+ * DOC: .init.data
+ *
+ * ELF section used for data structures used only during boot or driver
+ * initialization.
+ */
+
+/**
+ * DOC: .init.rodata
+ *
+ * ELF section used for read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+
+/**
+ * DOC: .initcall
+ *
+ * ELF section used for subsystem init calls. There are init levels
+ * representing different functionality in the kernel. For more details
+ * refer to __define_initcall().
+ */
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: .exit.text
+ *
+ * ELF section used to for code (functions) used only during module unload.
+ */
+
+/**
+ * DOC: .exit.data
+ *
+ * ELF section used to for data structures used only during module
+ * unload.
+ */
+
+/**
+ * DOC: .exitcall.exit
+ *
+ * ELF section used for exit routines, order is important and maintained by
+ * link order.
+ */
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: .ref.text
+ *
+ * ELF section used to annotate code (functions) which has been vetteed as
+ * valid for its reference or use of other code (functions) or data structures
+ * which are part of the init sections.
+ */
+
+/**
+ * DOC: .ref.data
+ *
+ * ELF section used for data structures which have been vetteed for its
+ * reference or use of other code (functions) or data structures part of the
+ * init sections.
+ */
+
+/**
+ * DOC: .ref.rodata
+ *
+ * ELF section used to annotate const code (functions) const data structures
+ * which has been vetteed for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section..___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section..__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifndef LINKER_SCRIPT
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align\x16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 4df64a1fc09e..b145ae8d9cbe 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_GENERIC_SECTIONS_H_
 #define _ASM_GENERIC_SECTIONS_H_
 
+#include <asm/section-core.h>
+
 /* References to section boundaries */
 
 #include <linux/compiler.h>
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 0968d13b3885..483f60c451f9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -55,6 +55,7 @@
 #endif
 
 #include <linux/export.h>
+#include <asm/section-core.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
diff --git a/include/linux/init.h b/include/linux/init.h
index 885c3e6d0f9d..116e3262332a 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -130,6 +130,24 @@ int __init init_rootfs(void);
 extern bool rodata_enabled;
 #endif
 #ifdef CONFIG_DEBUG_RODATA
+/**
+ * mark_rodata_ro - implemement memory protection for ELF sections
+ *
+ * Architectures which support memory protection define a kernel configuration
+ * entry for CONFIG_DEBUG_RODATA, enable it in and implement mark_rodata_ro().
+ * mark_rodata_ro() should strive to adjust the .rodata and .text ELF sections
+ * with read-only memory protection to prevent modifications of these sections
+ * after bootup. It can also try to use memory protection to prevent execution
+ * on the .rodata ELF section.
+ *
+ * In order to help architectures set both .text and .rodata as read-only with
+ * memory protections in one shot Linux has typically followed the convention
+ * to have the .rodata ELF section follow the .text ELF section on the vmlinux
+ * linker script.
+ *
+ * Linux calls mark_rodata_ro() after freeing .init code and prior to calling
+ * the first init userspace process.
+ */
 void mark_rodata_ro(void);
 #endif
 
@@ -140,25 +158,70 @@ extern bool initcall_debug;
 #endif
   
 #ifndef MODULE
+/**
+ * DOC: Initcall levels
+ *
+ * When Linux boots the kernel do_initcalls() iterates over each Linux
+ * initialization level ID and calls all routines embedded on each level ID.
+ * Prior to v2.5.2.3 Linux had only one init level onto which all init
+ * functions folded onto using __initcall(). After v2.5.2.4 Linux split up
+ * initcalls into 7 separate initcall subsection levels, each level describing
+ * different functionality part of the kernel (commit `9d6ba121b7e17085`_
+ * (v2.5.2.3 -> v2.5.2.4)). In order to remain backward compatible __initcall()
+ * calls were left mapped to device_initcall().
+ *
+ * Each init level consists of a dedicated ELF section, init functions are
+ * associated to an init level by linking it into the respective level's
+ * ELF section.
+ *
+ * Lower order init levels run prior to higher order init levels. Ordering
+ * inside each initcall level is determined by respective link order.
+ *
+ * .. _9d6ba121b7e17085: https://git.kernel.org/cgit/linux/kernel/git/history/history.git/commit/?idù6ba121b7e17085c95139233686b27a4d4c650e
+ */
 
 #ifndef __ASSEMBLY__
 
-/*
- * initcalls are now grouped by functionality into separate
- * subsections. Ordering inside the subsections is determined
- * by link order. 
- * For backwards compatibility, initcall() puts the call in 
- * the device init subsection.
+/**
+ * __define_initcall - wrapper for definiting init levels
  *
- * The `id' arg to __define_initcall() is needed so that multiple initcalls
- * can point at the same handler without causing duplicate-symbol build errors.
+ * @fn: init routine
+ * @id: init level
  *
- * Initcalls are run by placing pointers in initcall sections that the
- * kernel iterates at runtime. The linker can do dead code / data elimination
- * and remove that completely, so the initcall sections have to be marked
- * as KEEP() in the linker script.
+ * Defines a kernel initialization level. A respective linker script entry
+ * is required to ensure the init level is accounted for and to ensure symbols
+ * exist for iterating over all functions in the init level. A init level
+ * represents a series of functionality in the kernel.
+ *
+ * Ordering within an initialization level is determined by link order, so
+ * for instance if a Makefile had::
+ *
+ *	obj-y += foo.o
+ *	obj-y += bar.o
+ *
+ * And foo.c::
+ *
+ *	subsys_initcall(foo_init);
+ *
+ * And bar.c had::
+ *
+ *	subsys_initcall(bar_init);
+ *
+ * foo_init() would be called prior to bar_init().
+ *
+ * Note that @id in __define_initcall() also enables multiple initcalls
+ * to be created using the same handler for different init levels without
+ * causing duplicate-symbol build errors.
+ *
+ * Initcalls are run by placing start symbols to initcall levels inside ELF
+ * sections, the kernel in turn uses these symbols to iterate over each init
+ * level at runtime with do_initcall_level(). The end of each init level is
+ * marked by the subsequent's symbol's start address until we reach the symbol
+ * ``__initcall_end``. The linker can do dead code / data elimination and each
+ * init level start symbol could be removed completely in this process, to
+ * avoid this each init level start symbols must be marked as 'KEEP()' in the
+ * linker script to avoid any linker optimization heuristic on initcalls.
  */
-
 #define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
 	__attribute__((__section__(".initcall" #id ".init"))) = fn;
diff --git a/include/linux/sections.h b/include/linux/sections.h
new file mode 100644
index 000000000000..6771c727bcd1
--- /dev/null
+++ b/include/linux/sections.h
@@ -0,0 +1,87 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_CORE(section, core, name, level)			\
+	#section ".." #core "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe linux-ia64" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 02/14] xtensa: skip adding literal when SORT() is used
  2017-01-09 14:58       ` Luis R. Rodriguez
  (?)
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt

When SORT(foo.*) is used the current sed replacements add
SORT(foo.literal foo.*), this breaks linking. Avoid adding
literals for SORT globs, if needed, these need to be added
manually.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/xtensa/kernel/Makefile | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index 264fb89c444e..ccedd016a8e0 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -30,10 +30,10 @@ AFLAGS_mxhead.o += -mtext-section-literals
 #
 # Replicate rules in scripts/Makefile.build
 
-sed-y = -e ':a; s/\*(\([^)]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
-	-e ':b; s/\*(\([^)]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
-	-e ':c; s/\*(\([^)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
-	-e ':d; s/\*(\([^)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
+sed-y = -e ':a; s/\*(\([^)SORT]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
+	-e ':b; s/\*(\([^)SORT]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
+	-e ':c; s/\*(\([^SORT)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
+	-e ':d; s/\*(\([^SORT)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
 	-e 's/\.{text}/.text/g'
 
 quiet_cmd__cpp_lds_S = LDS     $@
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 02/14] xtensa: skip adding literal when SORT() is used
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt, ak

When SORT(foo.*) is used the current sed replacements add
SORT(foo.literal foo.*), this breaks linking. Avoid adding
literals for SORT globs, if needed, these need to be added
manually.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/xtensa/kernel/Makefile | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index 264fb89c444e..ccedd016a8e0 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -30,10 +30,10 @@ AFLAGS_mxhead.o += -mtext-section-literals
 #
 # Replicate rules in scripts/Makefile.build
 
-sed-y = -e ':a; s/\*(\([^)]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
-	-e ':b; s/\*(\([^)]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
-	-e ':c; s/\*(\([^)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
-	-e ':d; s/\*(\([^)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
+sed-y = -e ':a; s/\*(\([^)SORT]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
+	-e ':b; s/\*(\([^)SORT]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
+	-e ':c; s/\*(\([^SORT)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
+	-e ':d; s/\*(\([^SORT)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
 	-e 's/\.{text}/.text/g'
 
 quiet_cmd__cpp_lds_S = LDS     $@
-- 
2.11.0


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 02/14] xtensa: skip adding literal when SORT() is used
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

When SORT(foo.*) is used the current sed replacements add
SORT(foo.literal foo.*), this breaks linking. Avoid adding
literals for SORT globs, if needed, these need to be added
manually.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/xtensa/kernel/Makefile | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index 264fb89c444e..ccedd016a8e0 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -30,10 +30,10 @@ AFLAGS_mxhead.o += -mtext-section-literals
 #
 # Replicate rules in scripts/Makefile.build
 
-sed-y = -e ':a; s/\*(\([^)]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
-	-e ':b; s/\*(\([^)]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
-	-e ':c; s/\*(\([^)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
-	-e ':d; s/\*(\([^)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
+sed-y = -e ':a; s/\*(\([^)SORT]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
+	-e ':b; s/\*(\([^)SORT]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
+	-e ':c; s/\*(\([^SORT)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
+	-e ':d; s/\*(\([^SORT)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
 	-e 's/\.{text}/.text/g'
 
 quiet_cmd__cpp_lds_S = LDS     $@
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 03/14] ranges.h: add helpers to build and identify Linux section ranges
  2017-01-09 14:58       ` Luis R. Rodriguez
  (?)
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt

Section ranges are on one of the types of custom sections
types used in Linux. This provides a series of helpers for
defining them and using them. Most importantly this also
enables us to avoid modifying the linker script when we
add a new section range.

It turns out a lot of custom sections are actually section ranges,
and these are typically spelled out in their architecture specific
asm/sections.h file -- we enable architectures to override what asm
is used for section ranges but start by default trusting the
asm-generic version all around.

Although typically you will not want to have section ranges ordered
we must use SORT() on vmlinux.lds.S for section ranges to enable us
to extend a section range without modifying the linker script. To
accomplish this we use a special order string for the first element
of a section range -- the empty string "" (refer to __SECTION_RANGE_BEGIN()),
then "~" for the last element (refer to __SECTION_RANGE_BEGIN()). If
you use the "any" order for elements in between and use SORT() you end
up keeping any added element in betweeen and a reference to the
beginning and end of the section range without requiring custom linker
script modifications. Specific order annotations are also supported
to help construct synthetic functions, a demo for which will be provided
later.

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

o Extend commit log to justify SORT() and explain why and how we use
  specific special strings for the beginning, end elements of a section
  range and the "any" order for elements in between.

o Drop SECTION_RNG_ALL() -- we no longer need this on linker scripts

o To make this easier to read, as per Nicholas Piggin, add our own
  SECTION_RANGE_START(), SECTION_RANGE_END(). After reviewing the
  changes affected by this it seemed clearer and better then to also
  use our own specific SECTION_RANGE_SIZE(), and SECTION_RANGE_EMPTY(),
  and SECTION_RANGE_ALIGNMENT() as well.

o We were using LINUX_SECTION_START() and LINUX_SECTION_END() in some places
  but in some other places VMLINUX_SYMBOL(name), VMLINUX_SYMBOL(name##__end).
  Since we are adding SECTION_RANGE_START() and SECTION_RANGE_END() just
  use those consistently.

o Move the linker table *(SORT(.data.rng.*)) to be present before
  the recently added *(.data.[0-9a-zA-Z_]*) to ensure we keep sort order
  on the section range.

o Adds the "Linux section ordering" documentation, as its much more
  relevant after this patch, in particular when treating the "any"
  order level.

o Fix powerpc .text use: -- it does not use TEXT_TEXT so we must
  add our *(SORT(.text.rng.*)) to its linker script manually.

v4:

o tons of documentation love
o fix arch/x86/tools/relocs.c typo - which caused compilation issues
  on old toolchains
o port to new shiny sphinx documentation
o sprinkle a few more needed VMLINUX_SYMBOL() - fixes
  compilation on blackfin
o name changes as suggested 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
- rebrand DECLARE_SECTION_RNG() as DEFINE_SECTION_RANGE() - this is
  the asm version of the respective C version, this will have a
  userspace C demo added later.
o move __LINUX_RANGE() and __LINUX_RANGE_ORDER() - fixes builds
  on sparc
o adds section ranges to linker script
o rename SECTION_RANGE_ALL()
o use default alignment, fixes builds on powerpc and arm for both
  __LINUX_RANGE() and __LINUX_RANGE_ORDER()
o expand documentation to document modules support
o add maintainers
o use generic-y

v3: new in this series, uses copyleft-next

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst        |   1 +
 Documentation/sections/ranges.rst       |  74 +++++++++++++
 Documentation/sections/section-core.rst |   5 +
 MAINTAINERS                             |  10 ++
 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/Kbuild             |   1 +
 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/powerpc/kernel/vmlinux.lds.S       |   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            |  93 ++++++++++++++++
 include/asm-generic/section-core.h      |  41 +++++++
 include/asm-generic/vmlinux.lds.h       |  12 ++-
 include/linux/ranges.h                  | 183 ++++++++++++++++++++++++++++++++
 41 files changed, 451 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/linux/ranges.h

diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
index f37511ef05e7..4a1df389fa91 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -15,3 +15,4 @@ common a set of Linux helpers for ELF sections are also documented.
 
    background
    section-core
+   ranges
diff --git a/Documentation/sections/ranges.rst b/Documentation/sections/ranges.rst
new file mode 100644
index 000000000000..d9d3af4e52cb
--- /dev/null
+++ b/Documentation/sections/ranges.rst
@@ -0,0 +1,74 @@
+==========
+Linux section ranges
+==========
+
+This documents Linux' use of section ranges, how you can use
+them and how they work.
+
+About section ranges
+==========
+
+Introduction
+------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Introduction
+
+Section range module support
+----------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range module support
+
+Section range helpers
+==========+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range helpers
+
+SECTION_RANGE_START
+-------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_START
+
+SECTION_RANGE_END
+-----------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_END
+
+SECTION_RANGE_SIZE
+------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_SIZE
+
+SECTION_RANGE_EMPTY
+-------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_EMPTY
+
+SECTION_RANGE_ADDR_WITHIN
+-------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_ADDR_WITHIN
+
+SECTION_RANGE_ALIGNMENT
+-------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_ALIGNMENT
+
+DECLARE_SECTION_RANGE
+---------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DECLARE_SECTION_RANGE
+
+DEFINE_SECTION_RANGE
+--------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DEFINE_SECTION_RANGE
+
+__LINUX_RANGE
+-------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE
+
+__LINUX_RANGE_ORDER
+-------------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE_ORDER
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
index ac5815a0d9b3..1f613a6c7b78 100644
--- a/Documentation/sections/section-core.rst
+++ b/Documentation/sections/section-core.rst
@@ -114,6 +114,11 @@ Linux .ref\* sections
 .. kernel-doc:: include/asm-generic/section-core.h
    :doc: .ref.rodata
 
+Linux section ordering
+===========
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux section ordering
+
 Generic Linux kernel section helpers
 ==================
 
diff --git a/MAINTAINERS b/MAINTAINERS
index ae86136f4b9a..c96ca032c276 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5424,6 +5424,16 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTION RANGES
+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
+S:	Supported
+F:	include/asm-generic/ranges.h
+F:	include/linux/ranges.h
+F:	Documentation/sections/ranges.rst
+
 GENERIC SECTIONS
 M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
 M:	Josh Poimboeuf <jpoimboe@redhat.com>
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index 5422827f1585..e44c896b91c4 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 7b2cb3dea5fc..a374b7f83888 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -52,3 +52,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 9b69a22a9ae1..0d47f98ccbc0 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -42,3 +42,4 @@ generic-y += unaligned.h
 generated-y += mach-types.h
 generated-y += unistd-nr.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 00ace5e826f1..e9939cbd9067 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index f2c3b656a0e7..edc176348d7c 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -23,3 +23,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index bf20541bcf21..3428415b1996 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 38127ce747be..cede2a950fbf 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 385cd88a9d9e..fb8bb4112773 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 46d7c599d9b8..5191fec655d7 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 1ec04ec1c82b..7929a992566c 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -76,3 +76,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index 37d7bfae7619..af17ee334788 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 672c6d5da18c..d8f226b35a0a 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 6111e1523750..1c6504d29312 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1277b45bf4f9..006e2863ad37 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index b1011375cd7a..4a8471434a3e 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -56,3 +56,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index c6c2cf6edc98..63c083a1f8da 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 7a932b4a5531..e844d6058248 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index f8145bc85835..656af7b69940 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index c9c7cb82b00f..c55880659d67 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 86175e701869..7d6a704b808c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -72,3 +72,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 18a9d4c5ead7..f11d1249738f 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 4322d9746cdb..60d8349241a7 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 7394b770ae1f..fcfc9d102348 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -107,6 +107,7 @@ SECTIONS
 #endif
 		/* careful! __ftr_alt_* sections need to be close to .text */
 		*(.text .fixup __ftr_alt_* .ref.text)
+		*(SORT(.text.rng.*))
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 63a1c2924b91..c1b85a361e5d 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index f089a264cd38..f0cdb2cbca4d 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -15,3 +15,4 @@ generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 7b0356dca562..c9bb7932a3d1 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 438f86573dc5..28280887ac79 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index fb6b831c1fba..33f7069763ae 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 580bd5ff828f..b952dcb3e216 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -27,3 +27,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 8578702d4998..93abbfdab543 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += ranges.h
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index af975f21eeee..f672f2fc181d 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index 73eb7fd4aec4..f96fa2ddf7c9 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -68,6 +68,8 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
 	"__end_rodata|"
 	"__initramfs_start|"
 	"(jiffies|jiffies_64)|"
+	".rodata..rng.*|"
+	".init.text..rng.*|"
 #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 7879c31e66a7..2b7fe48c0225 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -33,3 +33,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/include/asm-generic/ranges.h b/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..75c196864f45
--- /dev/null
+++ b/include/asm-generic/ranges.h
@@ -0,0 +1,93 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  any, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       any, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   any, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(#section "..rng.name.any")))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using
+ * 	binutils SORT(), the number is sorted as a string, as such be
+ * 	sure to fill with zeroes any empty digits. For instance if you are
+ * 	using 3 levels of digits for order levels, use 001 for the first entry,
+ * 	0002 for the second, 999 for the last entry. You can use however many
+ * 	digits you need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(#section "..rng.name." #level)))
+
+#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/section-core.h b/include/asm-generic/section-core.h
index bb16befc4251..65fb076765f8 100644
--- a/include/asm-generic/section-core.h
+++ b/include/asm-generic/section-core.h
@@ -183,6 +183,47 @@
  * or data structures part of the init sections.
  */
 
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections alpha numerically. Linux has historically used 'SORT()' in
+ * ``include/asm-generic/vmlinux.lds.h``, its a well established practice. If
+ * 'SORT()' is used on a section one can provide ordering using a postfix on
+ * each section entry added. For instance if a linker script uses::
+ *
+ *    SORT(.foo.*)
+ *
+ * one can then add entries with explicit ordering using numeric postfixes for
+ * each entry, we refer to these as 'order levels'. Since 'SORT()' sorts alpha
+ * numerically a specific series set of digits must be agreed a-priori which
+ * would give also an idea of the max expected number of entries added to a
+ * section. For instance, if you expect a maximum of 999 entries you can use
+ * 3 digits for a section order level. If you wanted an entry to be ordered
+ * first you could use the postfix '000', if you wanted an entry to follow this
+ * you could use '001', and so on. We could for instance have::
+ *
+ *    .foo.000
+ *    .foo.001
+ *    .foo.002
+ *
+ * Often times one may want the option to specify no order is required for
+ * certain elements added to a section which does use 'SORT()' on the linker
+ * script. You can use any arbitrary string value to to specify no order is
+ * used, so long as its used consistantly. For instance, one possibility is to
+ * use the 'any' postfix.  All entries on the section would then have no
+ * specific ordering::
+ *
+ *    .foo.any
+ *    .foo.any
+ *    .foo.any
+ *
+ * To help establish a convention we reserve the special name 'any' for this
+ * purpose. Developers can use and expect the 'any' postfix string on sections
+ * as a helper to annotate section ordering at link time is not relevant
+ * for entries on a section.
+ */
+
 /* Can be used on foo.S for instance */
 #ifndef __set_section_core_type
 # define __set_section_core_type(___section, ___core, ___name,		\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 483f60c451f9..71bfd3b3c719 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -56,6 +56,7 @@
 
 #include <linux/export.h>
 #include <asm/section-core.h>
+#include <asm/ranges.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
@@ -205,6 +206,7 @@
  */
 #define DATA_DATA							\
 	*(.data .data.[0-9a-zA-Z_]*)					\
+	*(SORT(.data..rng.*))						\
 	*(.ref.data)							\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -273,7 +275,9 @@
 	. = ALIGN((align));						\
 	.rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {		\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
-		*(.rodata) *(.rodata.*)					\
+		*(.rodata)						\
+		*(SORT(.rodata..rng.*))					\
+		*(.rodata.*)						\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		KEEP(*(__vermagic))	/* Kernel version magic */	\
 		. = ALIGN(8);						\
@@ -446,7 +450,9 @@
  * conflicting section names, and must pull in .text.[0-9a-zA-Z_]* */
 #define TEXT_TEXT							\
 		ALIGN_FUNCTION();					\
-		*(.text.hot .text .text.fixup .text.unlikely)		\
+		*(.text.hot .text)					\
+		*(SORT(.text..rng.*))					\
+		*(.text.fixup .text.unlikely)				\
 		*(.ref.text)						\
 	MEM_KEEP(init.text)						\
 	MEM_KEEP(exit.text)						\
@@ -549,6 +555,7 @@
 #define INIT_DATA							\
 	KEEP(*(SORT(___kentry+*)))					\
 	*(.init.data)							\
+	*(SORT(.init.data..rng.*))					\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -572,6 +579,7 @@
 
 #define INIT_TEXT							\
 	*(.init.text)							\
+	*(SORT(.init.text..rng.*))					\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/ranges.h b/include/linux/ranges.h
new file mode 100644
index 000000000000..1e64674f6d7d
--- /dev/null
+++ b/include/linux/ranges.h
@@ -0,0 +1,183 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * SECTION_RANGE_START - get address of start of section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the start address of the section range.
+ * This should give you the address of the first entry.
+ *
+ */
+#define SECTION_RANGE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * SECTION_RANGE_END - get address of end of the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define SECTION_RANGE_END(name)		LINUX_SECTION_END(name)
+
+/**
+ * SECTION_RANGE_SIZE - get number of entries in the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the number of entries in the section range.
+ * Example usage:
+ *
+ *   unsigned int num_ents = LINKTABLE_SIZE(some_fns);
+ */
+#define SECTION_RANGE_SIZE(name)					\
+	((SECTION_RANGE_END(name)) - (SECTION_RANGE_START(name)))
+
+/**
+ * SECTION_RANGE_EMPTY - check if section range has no entries
+ *
+ * @name: name of the section range
+ *
+ * Returns true if the section range is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(some_fns);
+ */
+#define SECTION_RANGE_EMPTY(name)	(SECTION_RANGE_SIZE(name) = 0)
+
+/**
+ * SECTION_RANGE_ADDR_WITHIN - returns true if address is in the section range
+ *
+ * @name: name of the section range
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_RANGE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) SECTION_RANGE_START(name) &&		\
+          addr < (unsigned long) SECTION_RANGE_END(name))
+
+/**
+ * SECTION_RANGE_ALIGNMENT - get the alignment of the section range
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the section range.
+ */
+#define SECTION_RANGE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.")))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.~")))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) SECTION_RANGE_START(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) SECTION_RANGE_END(name)[0] = {}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 03/14] ranges.h: add helpers to build and identify Linux section ranges
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt, ak

Section ranges are on one of the types of custom sections
types used in Linux. This provides a series of helpers for
defining them and using them. Most importantly this also
enables us to avoid modifying the linker script when we
add a new section range.

It turns out a lot of custom sections are actually section ranges,
and these are typically spelled out in their architecture specific
asm/sections.h file -- we enable architectures to override what asm
is used for section ranges but start by default trusting the
asm-generic version all around.

Although typically you will not want to have section ranges ordered
we must use SORT() on vmlinux.lds.S for section ranges to enable us
to extend a section range without modifying the linker script. To
accomplish this we use a special order string for the first element
of a section range -- the empty string "" (refer to __SECTION_RANGE_BEGIN()),
then "~" for the last element (refer to __SECTION_RANGE_BEGIN()). If
you use the "any" order for elements in between and use SORT() you end
up keeping any added element in betweeen and a reference to the
beginning and end of the section range without requiring custom linker
script modifications. Specific order annotations are also supported
to help construct synthetic functions, a demo for which will be provided
later.

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

o Extend commit log to justify SORT() and explain why and how we use
  specific special strings for the beginning, end elements of a section
  range and the "any" order for elements in between.

o Drop SECTION_RNG_ALL() -- we no longer need this on linker scripts

o To make this easier to read, as per Nicholas Piggin, add our own
  SECTION_RANGE_START(), SECTION_RANGE_END(). After reviewing the
  changes affected by this it seemed clearer and better then to also
  use our own specific SECTION_RANGE_SIZE(), and SECTION_RANGE_EMPTY(),
  and SECTION_RANGE_ALIGNMENT() as well.

o We were using LINUX_SECTION_START() and LINUX_SECTION_END() in some places
  but in some other places VMLINUX_SYMBOL(name), VMLINUX_SYMBOL(name##__end).
  Since we are adding SECTION_RANGE_START() and SECTION_RANGE_END() just
  use those consistently.

o Move the linker table *(SORT(.data.rng.*)) to be present before
  the recently added *(.data.[0-9a-zA-Z_]*) to ensure we keep sort order
  on the section range.

o Adds the "Linux section ordering" documentation, as its much more
  relevant after this patch, in particular when treating the "any"
  order level.

o Fix powerpc .text use: -- it does not use TEXT_TEXT so we must
  add our *(SORT(.text.rng.*)) to its linker script manually.

v4:

o tons of documentation love
o fix arch/x86/tools/relocs.c typo - which caused compilation issues
  on old toolchains
o port to new shiny sphinx documentation
o sprinkle a few more needed VMLINUX_SYMBOL() - fixes
  compilation on blackfin
o name changes as suggested 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
- rebrand DECLARE_SECTION_RNG() as DEFINE_SECTION_RANGE() - this is
  the asm version of the respective C version, this will have a
  userspace C demo added later.
o move __LINUX_RANGE() and __LINUX_RANGE_ORDER() - fixes builds
  on sparc
o adds section ranges to linker script
o rename SECTION_RANGE_ALL()
o use default alignment, fixes builds on powerpc and arm for both
  __LINUX_RANGE() and __LINUX_RANGE_ORDER()
o expand documentation to document modules support
o add maintainers
o use generic-y

v3: new in this series, uses copyleft-next

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst        |   1 +
 Documentation/sections/ranges.rst       |  74 +++++++++++++
 Documentation/sections/section-core.rst |   5 +
 MAINTAINERS                             |  10 ++
 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/Kbuild             |   1 +
 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/powerpc/kernel/vmlinux.lds.S       |   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            |  93 ++++++++++++++++
 include/asm-generic/section-core.h      |  41 +++++++
 include/asm-generic/vmlinux.lds.h       |  12 ++-
 include/linux/ranges.h                  | 183 ++++++++++++++++++++++++++++++++
 41 files changed, 451 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/linux/ranges.h

diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
index f37511ef05e7..4a1df389fa91 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -15,3 +15,4 @@ common a set of Linux helpers for ELF sections are also documented.
 
    background
    section-core
+   ranges
diff --git a/Documentation/sections/ranges.rst b/Documentation/sections/ranges.rst
new file mode 100644
index 000000000000..d9d3af4e52cb
--- /dev/null
+++ b/Documentation/sections/ranges.rst
@@ -0,0 +1,74 @@
+====================
+Linux section ranges
+====================
+
+This documents Linux' use of section ranges, how you can use
+them and how they work.
+
+About section ranges
+====================
+
+Introduction
+------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Introduction
+
+Section range module support
+----------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range module support
+
+Section range helpers
+=====================
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range helpers
+
+SECTION_RANGE_START
+-------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_START
+
+SECTION_RANGE_END
+-----------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_END
+
+SECTION_RANGE_SIZE
+------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_SIZE
+
+SECTION_RANGE_EMPTY
+-------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_EMPTY
+
+SECTION_RANGE_ADDR_WITHIN
+-------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_ADDR_WITHIN
+
+SECTION_RANGE_ALIGNMENT
+-------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_ALIGNMENT
+
+DECLARE_SECTION_RANGE
+---------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DECLARE_SECTION_RANGE
+
+DEFINE_SECTION_RANGE
+--------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DEFINE_SECTION_RANGE
+
+__LINUX_RANGE
+-------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE
+
+__LINUX_RANGE_ORDER
+-------------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE_ORDER
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
index ac5815a0d9b3..1f613a6c7b78 100644
--- a/Documentation/sections/section-core.rst
+++ b/Documentation/sections/section-core.rst
@@ -114,6 +114,11 @@ Linux .ref\* sections
 .. kernel-doc:: include/asm-generic/section-core.h
    :doc: .ref.rodata
 
+Linux section ordering
+======================
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux section ordering
+
 Generic Linux kernel section helpers
 ====================================
 
diff --git a/MAINTAINERS b/MAINTAINERS
index ae86136f4b9a..c96ca032c276 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5424,6 +5424,16 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTION RANGES
+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
+S:	Supported
+F:	include/asm-generic/ranges.h
+F:	include/linux/ranges.h
+F:	Documentation/sections/ranges.rst
+
 GENERIC SECTIONS
 M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
 M:	Josh Poimboeuf <jpoimboe@redhat.com>
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index 5422827f1585..e44c896b91c4 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 7b2cb3dea5fc..a374b7f83888 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -52,3 +52,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 9b69a22a9ae1..0d47f98ccbc0 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -42,3 +42,4 @@ generic-y += unaligned.h
 generated-y += mach-types.h
 generated-y += unistd-nr.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 00ace5e826f1..e9939cbd9067 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index f2c3b656a0e7..edc176348d7c 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -23,3 +23,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index bf20541bcf21..3428415b1996 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 38127ce747be..cede2a950fbf 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 385cd88a9d9e..fb8bb4112773 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 46d7c599d9b8..5191fec655d7 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 1ec04ec1c82b..7929a992566c 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -76,3 +76,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index 37d7bfae7619..af17ee334788 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 672c6d5da18c..d8f226b35a0a 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 6111e1523750..1c6504d29312 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1277b45bf4f9..006e2863ad37 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index b1011375cd7a..4a8471434a3e 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -56,3 +56,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index c6c2cf6edc98..63c083a1f8da 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 7a932b4a5531..e844d6058248 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index f8145bc85835..656af7b69940 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index c9c7cb82b00f..c55880659d67 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 86175e701869..7d6a704b808c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -72,3 +72,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 18a9d4c5ead7..f11d1249738f 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 4322d9746cdb..60d8349241a7 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 7394b770ae1f..fcfc9d102348 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -107,6 +107,7 @@ SECTIONS
 #endif
 		/* careful! __ftr_alt_* sections need to be close to .text */
 		*(.text .fixup __ftr_alt_* .ref.text)
+		*(SORT(.text.rng.*))
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 63a1c2924b91..c1b85a361e5d 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index f089a264cd38..f0cdb2cbca4d 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -15,3 +15,4 @@ generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 7b0356dca562..c9bb7932a3d1 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 438f86573dc5..28280887ac79 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index fb6b831c1fba..33f7069763ae 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 580bd5ff828f..b952dcb3e216 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -27,3 +27,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 8578702d4998..93abbfdab543 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += ranges.h
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index af975f21eeee..f672f2fc181d 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index 73eb7fd4aec4..f96fa2ddf7c9 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -68,6 +68,8 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
 	"__end_rodata|"
 	"__initramfs_start|"
 	"(jiffies|jiffies_64)|"
+	".rodata..rng.*|"
+	".init.text..rng.*|"
 #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 7879c31e66a7..2b7fe48c0225 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -33,3 +33,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/include/asm-generic/ranges.h b/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..75c196864f45
--- /dev/null
+++ b/include/asm-generic/ranges.h
@@ -0,0 +1,93 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  any, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       any, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   any, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(#section "..rng.name.any")))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using
+ * 	binutils SORT(), the number is sorted as a string, as such be
+ * 	sure to fill with zeroes any empty digits. For instance if you are
+ * 	using 3 levels of digits for order levels, use 001 for the first entry,
+ * 	0002 for the second, 999 for the last entry. You can use however many
+ * 	digits you need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(#section "..rng.name." #level)))
+
+#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/section-core.h b/include/asm-generic/section-core.h
index bb16befc4251..65fb076765f8 100644
--- a/include/asm-generic/section-core.h
+++ b/include/asm-generic/section-core.h
@@ -183,6 +183,47 @@
  * or data structures part of the init sections.
  */
 
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections alpha numerically. Linux has historically used 'SORT()' in
+ * ``include/asm-generic/vmlinux.lds.h``, its a well established practice. If
+ * 'SORT()' is used on a section one can provide ordering using a postfix on
+ * each section entry added. For instance if a linker script uses::
+ *
+ *    SORT(.foo.*)
+ *
+ * one can then add entries with explicit ordering using numeric postfixes for
+ * each entry, we refer to these as 'order levels'. Since 'SORT()' sorts alpha
+ * numerically a specific series set of digits must be agreed a-priori which
+ * would give also an idea of the max expected number of entries added to a
+ * section. For instance, if you expect a maximum of 999 entries you can use
+ * 3 digits for a section order level. If you wanted an entry to be ordered
+ * first you could use the postfix '000', if you wanted an entry to follow this
+ * you could use '001', and so on. We could for instance have::
+ *
+ *    .foo.000
+ *    .foo.001
+ *    .foo.002
+ *
+ * Often times one may want the option to specify no order is required for
+ * certain elements added to a section which does use 'SORT()' on the linker
+ * script. You can use any arbitrary string value to to specify no order is
+ * used, so long as its used consistantly. For instance, one possibility is to
+ * use the 'any' postfix.  All entries on the section would then have no
+ * specific ordering::
+ *
+ *    .foo.any
+ *    .foo.any
+ *    .foo.any
+ *
+ * To help establish a convention we reserve the special name 'any' for this
+ * purpose. Developers can use and expect the 'any' postfix string on sections
+ * as a helper to annotate section ordering at link time is not relevant
+ * for entries on a section.
+ */
+
 /* Can be used on foo.S for instance */
 #ifndef __set_section_core_type
 # define __set_section_core_type(___section, ___core, ___name,		\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 483f60c451f9..71bfd3b3c719 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -56,6 +56,7 @@
 
 #include <linux/export.h>
 #include <asm/section-core.h>
+#include <asm/ranges.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
@@ -205,6 +206,7 @@
  */
 #define DATA_DATA							\
 	*(.data .data.[0-9a-zA-Z_]*)					\
+	*(SORT(.data..rng.*))						\
 	*(.ref.data)							\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -273,7 +275,9 @@
 	. = ALIGN((align));						\
 	.rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {		\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
-		*(.rodata) *(.rodata.*)					\
+		*(.rodata)						\
+		*(SORT(.rodata..rng.*))					\
+		*(.rodata.*)						\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		KEEP(*(__vermagic))	/* Kernel version magic */	\
 		. = ALIGN(8);						\
@@ -446,7 +450,9 @@
  * conflicting section names, and must pull in .text.[0-9a-zA-Z_]* */
 #define TEXT_TEXT							\
 		ALIGN_FUNCTION();					\
-		*(.text.hot .text .text.fixup .text.unlikely)		\
+		*(.text.hot .text)					\
+		*(SORT(.text..rng.*))					\
+		*(.text.fixup .text.unlikely)				\
 		*(.ref.text)						\
 	MEM_KEEP(init.text)						\
 	MEM_KEEP(exit.text)						\
@@ -549,6 +555,7 @@
 #define INIT_DATA							\
 	KEEP(*(SORT(___kentry+*)))					\
 	*(.init.data)							\
+	*(SORT(.init.data..rng.*))					\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -572,6 +579,7 @@
 
 #define INIT_TEXT							\
 	*(.init.text)							\
+	*(SORT(.init.text..rng.*))					\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/ranges.h b/include/linux/ranges.h
new file mode 100644
index 000000000000..1e64674f6d7d
--- /dev/null
+++ b/include/linux/ranges.h
@@ -0,0 +1,183 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * SECTION_RANGE_START - get address of start of section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the start address of the section range.
+ * This should give you the address of the first entry.
+ *
+ */
+#define SECTION_RANGE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * SECTION_RANGE_END - get address of end of the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define SECTION_RANGE_END(name)		LINUX_SECTION_END(name)
+
+/**
+ * SECTION_RANGE_SIZE - get number of entries in the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the number of entries in the section range.
+ * Example usage:
+ *
+ *   unsigned int num_ents = LINKTABLE_SIZE(some_fns);
+ */
+#define SECTION_RANGE_SIZE(name)					\
+	((SECTION_RANGE_END(name)) - (SECTION_RANGE_START(name)))
+
+/**
+ * SECTION_RANGE_EMPTY - check if section range has no entries
+ *
+ * @name: name of the section range
+ *
+ * Returns true if the section range is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(some_fns);
+ */
+#define SECTION_RANGE_EMPTY(name)	(SECTION_RANGE_SIZE(name) == 0)
+
+/**
+ * SECTION_RANGE_ADDR_WITHIN - returns true if address is in the section range
+ *
+ * @name: name of the section range
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_RANGE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) SECTION_RANGE_START(name) &&		\
+          addr < (unsigned long) SECTION_RANGE_END(name))
+
+/**
+ * SECTION_RANGE_ALIGNMENT - get the alignment of the section range
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the section range.
+ */
+#define SECTION_RANGE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.")))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.~")))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) SECTION_RANGE_START(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) SECTION_RANGE_END(name)[0] = {}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
-- 
2.11.0


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 03/14] ranges.h: add helpers to build and identify Linux section ranges
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

Section ranges are on one of the types of custom sections
types used in Linux. This provides a series of helpers for
defining them and using them. Most importantly this also
enables us to avoid modifying the linker script when we
add a new section range.

It turns out a lot of custom sections are actually section ranges,
and these are typically spelled out in their architecture specific
asm/sections.h file -- we enable architectures to override what asm
is used for section ranges but start by default trusting the
asm-generic version all around.

Although typically you will not want to have section ranges ordered
we must use SORT() on vmlinux.lds.S for section ranges to enable us
to extend a section range without modifying the linker script. To
accomplish this we use a special order string for the first element
of a section range -- the empty string "" (refer to __SECTION_RANGE_BEGIN()),
then "~" for the last element (refer to __SECTION_RANGE_BEGIN()). If
you use the "any" order for elements in between and use SORT() you end
up keeping any added element in betweeen and a reference to the
beginning and end of the section range without requiring custom linker
script modifications. Specific order annotations are also supported
to help construct synthetic functions, a demo for which will be provided
later.

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

o Extend commit log to justify SORT() and explain why and how we use
  specific special strings for the beginning, end elements of a section
  range and the "any" order for elements in between.

o Drop SECTION_RNG_ALL() -- we no longer need this on linker scripts

o To make this easier to read, as per Nicholas Piggin, add our own
  SECTION_RANGE_START(), SECTION_RANGE_END(). After reviewing the
  changes affected by this it seemed clearer and better then to also
  use our own specific SECTION_RANGE_SIZE(), and SECTION_RANGE_EMPTY(),
  and SECTION_RANGE_ALIGNMENT() as well.

o We were using LINUX_SECTION_START() and LINUX_SECTION_END() in some places
  but in some other places VMLINUX_SYMBOL(name), VMLINUX_SYMBOL(name##__end).
  Since we are adding SECTION_RANGE_START() and SECTION_RANGE_END() just
  use those consistently.

o Move the linker table *(SORT(.data.rng.*)) to be present before
  the recently added *(.data.[0-9a-zA-Z_]*) to ensure we keep sort order
  on the section range.

o Adds the "Linux section ordering" documentation, as its much more
  relevant after this patch, in particular when treating the "any"
  order level.

o Fix powerpc .text use: -- it does not use TEXT_TEXT so we must
  add our *(SORT(.text.rng.*)) to its linker script manually.

v4:

o tons of documentation love
o fix arch/x86/tools/relocs.c typo - which caused compilation issues
  on old toolchains
o port to new shiny sphinx documentation
o sprinkle a few more needed VMLINUX_SYMBOL() - fixes
  compilation on blackfin
o name changes as suggested 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
- rebrand DECLARE_SECTION_RNG() as DEFINE_SECTION_RANGE() - this is
  the asm version of the respective C version, this will have a
  userspace C demo added later.
o move __LINUX_RANGE() and __LINUX_RANGE_ORDER() - fixes builds
  on sparc
o adds section ranges to linker script
o rename SECTION_RANGE_ALL()
o use default alignment, fixes builds on powerpc and arm for both
  __LINUX_RANGE() and __LINUX_RANGE_ORDER()
o expand documentation to document modules support
o add maintainers
o use generic-y

v3: new in this series, uses copyleft-next

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst        |   1 +
 Documentation/sections/ranges.rst       |  74 +++++++++++++
 Documentation/sections/section-core.rst |   5 +
 MAINTAINERS                             |  10 ++
 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/Kbuild             |   1 +
 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/powerpc/kernel/vmlinux.lds.S       |   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            |  93 ++++++++++++++++
 include/asm-generic/section-core.h      |  41 +++++++
 include/asm-generic/vmlinux.lds.h       |  12 ++-
 include/linux/ranges.h                  | 183 ++++++++++++++++++++++++++++++++
 41 files changed, 451 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/linux/ranges.h

diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
index f37511ef05e7..4a1df389fa91 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -15,3 +15,4 @@ common a set of Linux helpers for ELF sections are also documented.
 
    background
    section-core
+   ranges
diff --git a/Documentation/sections/ranges.rst b/Documentation/sections/ranges.rst
new file mode 100644
index 000000000000..d9d3af4e52cb
--- /dev/null
+++ b/Documentation/sections/ranges.rst
@@ -0,0 +1,74 @@
+====================
+Linux section ranges
+====================
+
+This documents Linux' use of section ranges, how you can use
+them and how they work.
+
+About section ranges
+====================
+
+Introduction
+------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Introduction
+
+Section range module support
+----------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range module support
+
+Section range helpers
+=====================
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range helpers
+
+SECTION_RANGE_START
+-------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_START
+
+SECTION_RANGE_END
+-----------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_END
+
+SECTION_RANGE_SIZE
+------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_SIZE
+
+SECTION_RANGE_EMPTY
+-------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_EMPTY
+
+SECTION_RANGE_ADDR_WITHIN
+-------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_ADDR_WITHIN
+
+SECTION_RANGE_ALIGNMENT
+-------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_ALIGNMENT
+
+DECLARE_SECTION_RANGE
+---------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DECLARE_SECTION_RANGE
+
+DEFINE_SECTION_RANGE
+--------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DEFINE_SECTION_RANGE
+
+__LINUX_RANGE
+-------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE
+
+__LINUX_RANGE_ORDER
+-------------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE_ORDER
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
index ac5815a0d9b3..1f613a6c7b78 100644
--- a/Documentation/sections/section-core.rst
+++ b/Documentation/sections/section-core.rst
@@ -114,6 +114,11 @@ Linux .ref\* sections
 .. kernel-doc:: include/asm-generic/section-core.h
    :doc: .ref.rodata
 
+Linux section ordering
+======================
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux section ordering
+
 Generic Linux kernel section helpers
 ====================================
 
diff --git a/MAINTAINERS b/MAINTAINERS
index ae86136f4b9a..c96ca032c276 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5424,6 +5424,16 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTION RANGES
+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
+S:	Supported
+F:	include/asm-generic/ranges.h
+F:	include/linux/ranges.h
+F:	Documentation/sections/ranges.rst
+
 GENERIC SECTIONS
 M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
 M:	Josh Poimboeuf <jpoimboe@redhat.com>
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index 5422827f1585..e44c896b91c4 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 7b2cb3dea5fc..a374b7f83888 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -52,3 +52,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 9b69a22a9ae1..0d47f98ccbc0 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -42,3 +42,4 @@ generic-y += unaligned.h
 generated-y += mach-types.h
 generated-y += unistd-nr.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 00ace5e826f1..e9939cbd9067 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index f2c3b656a0e7..edc176348d7c 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -23,3 +23,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index bf20541bcf21..3428415b1996 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 38127ce747be..cede2a950fbf 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 385cd88a9d9e..fb8bb4112773 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 46d7c599d9b8..5191fec655d7 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 1ec04ec1c82b..7929a992566c 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -76,3 +76,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index 37d7bfae7619..af17ee334788 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 672c6d5da18c..d8f226b35a0a 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 6111e1523750..1c6504d29312 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1277b45bf4f9..006e2863ad37 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index b1011375cd7a..4a8471434a3e 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -56,3 +56,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index c6c2cf6edc98..63c083a1f8da 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 7a932b4a5531..e844d6058248 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index f8145bc85835..656af7b69940 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index c9c7cb82b00f..c55880659d67 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 86175e701869..7d6a704b808c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -72,3 +72,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 18a9d4c5ead7..f11d1249738f 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 4322d9746cdb..60d8349241a7 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 7394b770ae1f..fcfc9d102348 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -107,6 +107,7 @@ SECTIONS
 #endif
 		/* careful! __ftr_alt_* sections need to be close to .text */
 		*(.text .fixup __ftr_alt_* .ref.text)
+		*(SORT(.text.rng.*))
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 63a1c2924b91..c1b85a361e5d 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index f089a264cd38..f0cdb2cbca4d 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -15,3 +15,4 @@ generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 7b0356dca562..c9bb7932a3d1 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 438f86573dc5..28280887ac79 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index fb6b831c1fba..33f7069763ae 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 580bd5ff828f..b952dcb3e216 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -27,3 +27,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 8578702d4998..93abbfdab543 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += ranges.h
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index af975f21eeee..f672f2fc181d 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index 73eb7fd4aec4..f96fa2ddf7c9 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -68,6 +68,8 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
 	"__end_rodata|"
 	"__initramfs_start|"
 	"(jiffies|jiffies_64)|"
+	".rodata..rng.*|"
+	".init.text..rng.*|"
 #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 7879c31e66a7..2b7fe48c0225 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -33,3 +33,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/include/asm-generic/ranges.h b/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..75c196864f45
--- /dev/null
+++ b/include/asm-generic/ranges.h
@@ -0,0 +1,93 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  any, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       any, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   any, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(#section "..rng.name.any")))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using
+ * 	binutils SORT(), the number is sorted as a string, as such be
+ * 	sure to fill with zeroes any empty digits. For instance if you are
+ * 	using 3 levels of digits for order levels, use 001 for the first entry,
+ * 	0002 for the second, 999 for the last entry. You can use however many
+ * 	digits you need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(#section "..rng.name." #level)))
+
+#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/section-core.h b/include/asm-generic/section-core.h
index bb16befc4251..65fb076765f8 100644
--- a/include/asm-generic/section-core.h
+++ b/include/asm-generic/section-core.h
@@ -183,6 +183,47 @@
  * or data structures part of the init sections.
  */
 
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections alpha numerically. Linux has historically used 'SORT()' in
+ * ``include/asm-generic/vmlinux.lds.h``, its a well established practice. If
+ * 'SORT()' is used on a section one can provide ordering using a postfix on
+ * each section entry added. For instance if a linker script uses::
+ *
+ *    SORT(.foo.*)
+ *
+ * one can then add entries with explicit ordering using numeric postfixes for
+ * each entry, we refer to these as 'order levels'. Since 'SORT()' sorts alpha
+ * numerically a specific series set of digits must be agreed a-priori which
+ * would give also an idea of the max expected number of entries added to a
+ * section. For instance, if you expect a maximum of 999 entries you can use
+ * 3 digits for a section order level. If you wanted an entry to be ordered
+ * first you could use the postfix '000', if you wanted an entry to follow this
+ * you could use '001', and so on. We could for instance have::
+ *
+ *    .foo.000
+ *    .foo.001
+ *    .foo.002
+ *
+ * Often times one may want the option to specify no order is required for
+ * certain elements added to a section which does use 'SORT()' on the linker
+ * script. You can use any arbitrary string value to to specify no order is
+ * used, so long as its used consistantly. For instance, one possibility is to
+ * use the 'any' postfix.  All entries on the section would then have no
+ * specific ordering::
+ *
+ *    .foo.any
+ *    .foo.any
+ *    .foo.any
+ *
+ * To help establish a convention we reserve the special name 'any' for this
+ * purpose. Developers can use and expect the 'any' postfix string on sections
+ * as a helper to annotate section ordering at link time is not relevant
+ * for entries on a section.
+ */
+
 /* Can be used on foo.S for instance */
 #ifndef __set_section_core_type
 # define __set_section_core_type(___section, ___core, ___name,		\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 483f60c451f9..71bfd3b3c719 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -56,6 +56,7 @@
 
 #include <linux/export.h>
 #include <asm/section-core.h>
+#include <asm/ranges.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
@@ -205,6 +206,7 @@
  */
 #define DATA_DATA							\
 	*(.data .data.[0-9a-zA-Z_]*)					\
+	*(SORT(.data..rng.*))						\
 	*(.ref.data)							\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -273,7 +275,9 @@
 	. = ALIGN((align));						\
 	.rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {		\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
-		*(.rodata) *(.rodata.*)					\
+		*(.rodata)						\
+		*(SORT(.rodata..rng.*))					\
+		*(.rodata.*)						\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		KEEP(*(__vermagic))	/* Kernel version magic */	\
 		. = ALIGN(8);						\
@@ -446,7 +450,9 @@
  * conflicting section names, and must pull in .text.[0-9a-zA-Z_]* */
 #define TEXT_TEXT							\
 		ALIGN_FUNCTION();					\
-		*(.text.hot .text .text.fixup .text.unlikely)		\
+		*(.text.hot .text)					\
+		*(SORT(.text..rng.*))					\
+		*(.text.fixup .text.unlikely)				\
 		*(.ref.text)						\
 	MEM_KEEP(init.text)						\
 	MEM_KEEP(exit.text)						\
@@ -549,6 +555,7 @@
 #define INIT_DATA							\
 	KEEP(*(SORT(___kentry+*)))					\
 	*(.init.data)							\
+	*(SORT(.init.data..rng.*))					\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -572,6 +579,7 @@
 
 #define INIT_TEXT							\
 	*(.init.text)							\
+	*(SORT(.init.text..rng.*))					\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/ranges.h b/include/linux/ranges.h
new file mode 100644
index 000000000000..1e64674f6d7d
--- /dev/null
+++ b/include/linux/ranges.h
@@ -0,0 +1,183 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * SECTION_RANGE_START - get address of start of section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the start address of the section range.
+ * This should give you the address of the first entry.
+ *
+ */
+#define SECTION_RANGE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * SECTION_RANGE_END - get address of end of the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define SECTION_RANGE_END(name)		LINUX_SECTION_END(name)
+
+/**
+ * SECTION_RANGE_SIZE - get number of entries in the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the number of entries in the section range.
+ * Example usage:
+ *
+ *   unsigned int num_ents = LINKTABLE_SIZE(some_fns);
+ */
+#define SECTION_RANGE_SIZE(name)					\
+	((SECTION_RANGE_END(name)) - (SECTION_RANGE_START(name)))
+
+/**
+ * SECTION_RANGE_EMPTY - check if section range has no entries
+ *
+ * @name: name of the section range
+ *
+ * Returns true if the section range is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(some_fns);
+ */
+#define SECTION_RANGE_EMPTY(name)	(SECTION_RANGE_SIZE(name) == 0)
+
+/**
+ * SECTION_RANGE_ADDR_WITHIN - returns true if address is in the section range
+ *
+ * @name: name of the section range
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_RANGE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) SECTION_RANGE_START(name) &&		\
+          addr < (unsigned long) SECTION_RANGE_END(name))
+
+/**
+ * SECTION_RANGE_ALIGNMENT - get the alignment of the section range
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the section range.
+ */
+#define SECTION_RANGE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.")))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.~")))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) SECTION_RANGE_START(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) SECTION_RANGE_END(name)[0] = {}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 04/14] tables.h: add linker table support
  2017-01-09 14:58       ` Luis R. Rodriguez
  (?)
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt

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.

v6:

o rename tables macro as requested by Andy Shevchenko

v5:
o Use ..tbl.* instead of .tbl.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clashes with compiler generated
  sections.
o Replace section macros with section names
o Dropped SECTION_RNG_ALL()
o Fix documentation typos
o To make this easier to read, as per Nicholas Piggin, add our own
  LINKTABLE_START(), LINKTABLE_END(). After reviewing the changes
  affected by this it seemed clearer and better then to also
  use our own specific LINKTABLE_SIZE(), LINKTABLE_EMPTY() and
  LINKTABLE_ALIGNMENT() as well.
o Clarifies SECTION_TBL_RO needs to be kept since some toolchains
  are buggy, and so we also add SECTION_TBL_RO_STR.
o We were using LINUX_SECTION_START() and LINUX_SECTION_END() in some places
  but in some other places VMLINUX_SYMBOL(name), VMLINUX_SYMBOL(name##__end).
  Since we are adding LINKTABLE_START() and LINKTABLE_END() just use those
  consistently.
o Fix DEFINE_LINKTABLE_INIT() by making it use DECLARE_LINKTABLE_RO()
  which forces const.
o Fix powerpc .text use: it does not use TEXT_TEXT so we must
  add our *(SORT(.text.tbl.*)) to its linker script manually.

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@ipxe.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst         |   1 +
 Documentation/sections/linker-tables.rst | 212 +++++++++++
 MAINTAINERS                              |  10 +
 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/powerpc/kernel/vmlinux.lds.S        |   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/tables.h             |  48 +++
 include/asm-generic/vmlinux.lds.h        |   6 +
 include/linux/tables.h                   | 612 +++++++++++++++++++++++++++++++
 39 files changed, 948 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 4a1df389fa91..7c7c1adf955c 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -16,3 +16,4 @@ common a set of Linux helpers for ELF sections are also documented.
    background
    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..780a292d2d00
--- /dev/null
+++ b/Documentation/sections/linker-tables.rst
@@ -0,0 +1,212 @@
+=========+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_START
+---------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_START
+
+LINKTABLE_END
+-------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_END
+
+LINKTABLE_SIZE
+--------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_SIZE
+
+LINKTABLE_EMPTY
+---------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_EMPTY
+
+LINKTABLE_ADDR_WITHIN
+---------------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_ADDR_WITHIN
+
+LINKTABLE_ALIGNMENT
+-------------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_ALIGNMENT
+
+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 c96ca032c276..bbf519da3a78 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5407,6 +5407,16 @@ 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
+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
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 a374b7f83888..ccfa69ce2608 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -53,3 +53,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 0d47f98ccbc0..b70d4b78d577 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -43,3 +43,4 @@ generated-y += mach-types.h
 generated-y += unistd-nr.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 e9939cbd9067..0c1e781ab10b 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -47,3 +47,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 3428415b1996..9115b215fc7e 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -49,3 +49,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..90a0d3df35c8
--- /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@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 weak 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 */
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 006e2863ad37..c28bcdecc764 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -36,3 +36,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 4a8471434a3e..c836f7e2a5e7 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -57,3 +57,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 e844d6058248..db9dff9c1535 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -23,3 +23,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 f11d1249738f..aaae8a9f6099 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -30,3 +30,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 60d8349241a7..7c06627a0a0d 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -10,3 +10,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/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index fcfc9d102348..8cd940c72895 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -108,6 +108,7 @@ SECTIONS
 		/* careful! __ftr_alt_* sections need to be close to .text */
 		*(.text .fixup __ftr_alt_* .ref.text)
 		*(SORT(.text.rng.*))
+		*(SORT(.text..tbl.*))
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index c1b85a361e5d..96dd69931427 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 28280887ac79..23a2216f4146 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -23,3 +23,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 33f7069763ae..a599f6f4ee0a 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -42,3 +42,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 b952dcb3e216..d2867aa09e23 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -28,3 +28,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 93abbfdab543..6671a1f08ead 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -62,3 +62,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 f672f2fc181d..4cb511f1067c 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -14,3 +14,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 f96fa2ddf7c9..484a24c309fb 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 2b7fe48c0225..7b41f32a2ba0 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -34,3 +34,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/tables.h b/include/asm-generic/tables.h
new file mode 100644
index 000000000000..16ef40d145fb
--- /dev/null
+++ b/include/asm-generic/tables.h
@@ -0,0 +1,48 @@
+#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..tbl.name.level
+
+/* Some toolchains are buggy, let them override */
+#ifndef SECTION_TBL_RO
+# define SECTION_TBL_RO	.rodata
+#endif
+
+#define SECTION_TBL_RO_STR __stringify(SECTION_TBL_RO)
+
+#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, 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, 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 71bfd3b3c719..ce1e9a310ada 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)
@@ -207,6 +208,7 @@
 #define DATA_DATA							\
 	*(.data .data.[0-9a-zA-Z_]*)					\
 	*(SORT(.data..rng.*))						\
+	*(SORT(.data..tbl.*))						\
 	*(.ref.data)							\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -277,6 +279,7 @@
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
 		*(.rodata)						\
 		*(SORT(.rodata..rng.*))					\
+		*(SORT(.rodata..tbl.*))					\
 		*(.rodata.*)						\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		KEEP(*(__vermagic))	/* Kernel version magic */	\
@@ -452,6 +455,7 @@
 		ALIGN_FUNCTION();					\
 		*(.text.hot .text)					\
 		*(SORT(.text..rng.*))					\
+		*(SORT(.text..tbl.*))					\
 		*(.text.fixup .text.unlikely)				\
 		*(.ref.text)						\
 	MEM_KEEP(init.text)						\
@@ -556,6 +560,7 @@
 	KEEP(*(SORT(___kentry+*)))					\
 	*(.init.data)							\
 	*(SORT(.init.data..rng.*))					\
+	*(SORT(.init.data..tbl.*))					\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -580,6 +585,7 @@
 #define INIT_TEXT							\
 	*(.init.text)							\
 	*(SORT(.init.text..rng.*))					\
+	*(SORT(.init.text..tbl.*))					\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
new file mode 100644
index 000000000000..1a1838d51951
--- /dev/null
+++ b/include/linux/tables.h
@@ -0,0 +1,612 @@
+#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(.foo..tbl.*))
+ *
+ * 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_START - get address of start of linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the start address of the linker table.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINKTABLE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * LINKTABLE_END - get address of end of the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define LINKTABLE_END(name)	LINUX_SECTION_END(name)
+
+/**
+ * LINKTABLE_SIZE - get number of entries in the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the number of entries in the linker table.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINKTABLE_SIZE(frobnicator_fns);
+ */
+#define LINKTABLE_SIZE(name)					\
+	((LINKTABLE_END(name)) - (LINKTABLE_START(name)))
+
+/**
+ * LINKTABLE_EMPTY - check if linker table has no entries
+ *
+ * @name: name of linker table
+ *
+ * Returns true if the linker table is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(frobnicator_fns);
+ */
+#define LINKTABLE_EMPTY(name)	(LINKTABLE_SIZE(name) = 0)
+
+/**
+ * LINKTABLE_ADDR_WITHIN - returns true if address is in the linker table
+ *
+ * @name: name of the linker table
+ * @addr: address to query for
+ *
+ * Returns true if the address is part of the linker table.
+ */
+#define LINKTABLE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) LINKTABLE_START(name) &&		\
+          addr < (unsigned long) LINKTABLE_END(name))
+
+/**
+ * LINKTABLE_ALIGNMENT - get the alignment of the linker table
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the linker table.
+ */
+#define LINKTABLE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * 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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_TEXT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE_RO(name, ~) LINKTABLE_END(name)[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_RO(type, name);				\
+	LINKTABLE_INIT_WEAK(name,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT_DATA(name, ~) LINKTABLE_END(name)[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 = LINKTABLE_START(tbl);				\
+	     pointer < LINKTABLE_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 < LINKTABLE_SIZE(tbl); i++)			\
+		(LINKTABLE_START(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 < LINKTABLE_SIZE(tbl); i++)		\
+		err = (LINKTABLE_START(tbl)[i]).func (args);		\
+	err;								\
+})
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_LINKER_TABLES_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 04/14] tables.h: add linker table support
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt, ak

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.

v6:

o rename tables macro as requested by Andy Shevchenko

v5:
o Use ..tbl.* instead of .tbl.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clashes with compiler generated
  sections.
o Replace section macros with section names
o Dropped SECTION_RNG_ALL()
o Fix documentation typos
o To make this easier to read, as per Nicholas Piggin, add our own
  LINKTABLE_START(), LINKTABLE_END(). After reviewing the changes
  affected by this it seemed clearer and better then to also
  use our own specific LINKTABLE_SIZE(), LINKTABLE_EMPTY() and
  LINKTABLE_ALIGNMENT() as well.
o Clarifies SECTION_TBL_RO needs to be kept since some toolchains
  are buggy, and so we also add SECTION_TBL_RO_STR.
o We were using LINUX_SECTION_START() and LINUX_SECTION_END() in some places
  but in some other places VMLINUX_SYMBOL(name), VMLINUX_SYMBOL(name##__end).
  Since we are adding LINKTABLE_START() and LINKTABLE_END() just use those
  consistently.
o Fix DEFINE_LINKTABLE_INIT() by making it use DECLARE_LINKTABLE_RO()
  which forces const.
o Fix powerpc .text use: it does not use TEXT_TEXT so we must
  add our *(SORT(.text.tbl.*)) to its linker script manually.

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@ipxe.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst         |   1 +
 Documentation/sections/linker-tables.rst | 212 +++++++++++
 MAINTAINERS                              |  10 +
 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/powerpc/kernel/vmlinux.lds.S        |   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/tables.h             |  48 +++
 include/asm-generic/vmlinux.lds.h        |   6 +
 include/linux/tables.h                   | 612 +++++++++++++++++++++++++++++++
 39 files changed, 948 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 4a1df389fa91..7c7c1adf955c 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -16,3 +16,4 @@ common a set of Linux helpers for ELF sections are also documented.
    background
    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..780a292d2d00
--- /dev/null
+++ b/Documentation/sections/linker-tables.rst
@@ -0,0 +1,212 @@
+===================
+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_START
+---------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_START
+
+LINKTABLE_END
+-------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_END
+
+LINKTABLE_SIZE
+--------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_SIZE
+
+LINKTABLE_EMPTY
+---------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_EMPTY
+
+LINKTABLE_ADDR_WITHIN
+---------------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_ADDR_WITHIN
+
+LINKTABLE_ALIGNMENT
+-------------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_ALIGNMENT
+
+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 c96ca032c276..bbf519da3a78 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5407,6 +5407,16 @@ 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
+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
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 a374b7f83888..ccfa69ce2608 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -53,3 +53,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 0d47f98ccbc0..b70d4b78d577 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -43,3 +43,4 @@ generated-y += mach-types.h
 generated-y += unistd-nr.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 e9939cbd9067..0c1e781ab10b 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -47,3 +47,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 3428415b1996..9115b215fc7e 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -49,3 +49,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..90a0d3df35c8
--- /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@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 weak 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 */
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 006e2863ad37..c28bcdecc764 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -36,3 +36,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 4a8471434a3e..c836f7e2a5e7 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -57,3 +57,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 e844d6058248..db9dff9c1535 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -23,3 +23,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 f11d1249738f..aaae8a9f6099 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -30,3 +30,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 60d8349241a7..7c06627a0a0d 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -10,3 +10,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/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index fcfc9d102348..8cd940c72895 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -108,6 +108,7 @@ SECTIONS
 		/* careful! __ftr_alt_* sections need to be close to .text */
 		*(.text .fixup __ftr_alt_* .ref.text)
 		*(SORT(.text.rng.*))
+		*(SORT(.text..tbl.*))
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index c1b85a361e5d..96dd69931427 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 28280887ac79..23a2216f4146 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -23,3 +23,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 33f7069763ae..a599f6f4ee0a 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -42,3 +42,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 b952dcb3e216..d2867aa09e23 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -28,3 +28,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 93abbfdab543..6671a1f08ead 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -62,3 +62,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 f672f2fc181d..4cb511f1067c 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -14,3 +14,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 f96fa2ddf7c9..484a24c309fb 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 2b7fe48c0225..7b41f32a2ba0 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -34,3 +34,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/tables.h b/include/asm-generic/tables.h
new file mode 100644
index 000000000000..16ef40d145fb
--- /dev/null
+++ b/include/asm-generic/tables.h
@@ -0,0 +1,48 @@
+#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..tbl.name.level
+
+/* Some toolchains are buggy, let them override */
+#ifndef SECTION_TBL_RO
+# define SECTION_TBL_RO	.rodata
+#endif
+
+#define SECTION_TBL_RO_STR __stringify(SECTION_TBL_RO)
+
+#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, 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, 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 71bfd3b3c719..ce1e9a310ada 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)
@@ -207,6 +208,7 @@
 #define DATA_DATA							\
 	*(.data .data.[0-9a-zA-Z_]*)					\
 	*(SORT(.data..rng.*))						\
+	*(SORT(.data..tbl.*))						\
 	*(.ref.data)							\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -277,6 +279,7 @@
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
 		*(.rodata)						\
 		*(SORT(.rodata..rng.*))					\
+		*(SORT(.rodata..tbl.*))					\
 		*(.rodata.*)						\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		KEEP(*(__vermagic))	/* Kernel version magic */	\
@@ -452,6 +455,7 @@
 		ALIGN_FUNCTION();					\
 		*(.text.hot .text)					\
 		*(SORT(.text..rng.*))					\
+		*(SORT(.text..tbl.*))					\
 		*(.text.fixup .text.unlikely)				\
 		*(.ref.text)						\
 	MEM_KEEP(init.text)						\
@@ -556,6 +560,7 @@
 	KEEP(*(SORT(___kentry+*)))					\
 	*(.init.data)							\
 	*(SORT(.init.data..rng.*))					\
+	*(SORT(.init.data..tbl.*))					\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -580,6 +585,7 @@
 #define INIT_TEXT							\
 	*(.init.text)							\
 	*(SORT(.init.text..rng.*))					\
+	*(SORT(.init.text..tbl.*))					\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
new file mode 100644
index 000000000000..1a1838d51951
--- /dev/null
+++ b/include/linux/tables.h
@@ -0,0 +1,612 @@
+#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(.foo..tbl.*))
+ *
+ * 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_START - get address of start of linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the start address of the linker table.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINKTABLE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * LINKTABLE_END - get address of end of the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define LINKTABLE_END(name)	LINUX_SECTION_END(name)
+
+/**
+ * LINKTABLE_SIZE - get number of entries in the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the number of entries in the linker table.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINKTABLE_SIZE(frobnicator_fns);
+ */
+#define LINKTABLE_SIZE(name)					\
+	((LINKTABLE_END(name)) - (LINKTABLE_START(name)))
+
+/**
+ * LINKTABLE_EMPTY - check if linker table has no entries
+ *
+ * @name: name of linker table
+ *
+ * Returns true if the linker table is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(frobnicator_fns);
+ */
+#define LINKTABLE_EMPTY(name)	(LINKTABLE_SIZE(name) == 0)
+
+/**
+ * LINKTABLE_ADDR_WITHIN - returns true if address is in the linker table
+ *
+ * @name: name of the linker table
+ * @addr: address to query for
+ *
+ * Returns true if the address is part of the linker table.
+ */
+#define LINKTABLE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) LINKTABLE_START(name) &&		\
+          addr < (unsigned long) LINKTABLE_END(name))
+
+/**
+ * LINKTABLE_ALIGNMENT - get the alignment of the linker table
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the linker table.
+ */
+#define LINKTABLE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * 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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_TEXT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE_RO(name, ~) LINKTABLE_END(name)[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_RO(type, name);				\
+	LINKTABLE_INIT_WEAK(name,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT_DATA(name, ~) LINKTABLE_END(name)[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 = LINKTABLE_START(tbl);				\
+	     pointer < LINKTABLE_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 < LINKTABLE_SIZE(tbl); i++)			\
+		(LINKTABLE_START(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 < LINKTABLE_SIZE(tbl); i++)		\
+		err = (LINKTABLE_START(tbl)[i]).func (args);		\
+	err;								\
+})
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_LINKER_TABLES_H */
-- 
2.11.0


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 04/14] tables.h: add linker table support
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

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.

v6:

o rename tables macro as requested by Andy Shevchenko

v5:
o Use ..tbl.* instead of .tbl.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clashes with compiler generated
  sections.
o Replace section macros with section names
o Dropped SECTION_RNG_ALL()
o Fix documentation typos
o To make this easier to read, as per Nicholas Piggin, add our own
  LINKTABLE_START(), LINKTABLE_END(). After reviewing the changes
  affected by this it seemed clearer and better then to also
  use our own specific LINKTABLE_SIZE(), LINKTABLE_EMPTY() and
  LINKTABLE_ALIGNMENT() as well.
o Clarifies SECTION_TBL_RO needs to be kept since some toolchains
  are buggy, and so we also add SECTION_TBL_RO_STR.
o We were using LINUX_SECTION_START() and LINUX_SECTION_END() in some places
  but in some other places VMLINUX_SYMBOL(name), VMLINUX_SYMBOL(name##__end).
  Since we are adding LINKTABLE_START() and LINKTABLE_END() just use those
  consistently.
o Fix DEFINE_LINKTABLE_INIT() by making it use DECLARE_LINKTABLE_RO()
  which forces const.
o Fix powerpc .text use: it does not use TEXT_TEXT so we must
  add our *(SORT(.text.tbl.*)) to its linker script manually.

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@ipxe.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst         |   1 +
 Documentation/sections/linker-tables.rst | 212 +++++++++++
 MAINTAINERS                              |  10 +
 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/powerpc/kernel/vmlinux.lds.S        |   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/tables.h             |  48 +++
 include/asm-generic/vmlinux.lds.h        |   6 +
 include/linux/tables.h                   | 612 +++++++++++++++++++++++++++++++
 39 files changed, 948 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 4a1df389fa91..7c7c1adf955c 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -16,3 +16,4 @@ common a set of Linux helpers for ELF sections are also documented.
    background
    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..780a292d2d00
--- /dev/null
+++ b/Documentation/sections/linker-tables.rst
@@ -0,0 +1,212 @@
+===================
+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_START
+---------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_START
+
+LINKTABLE_END
+-------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_END
+
+LINKTABLE_SIZE
+--------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_SIZE
+
+LINKTABLE_EMPTY
+---------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_EMPTY
+
+LINKTABLE_ADDR_WITHIN
+---------------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_ADDR_WITHIN
+
+LINKTABLE_ALIGNMENT
+-------------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_ALIGNMENT
+
+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 c96ca032c276..bbf519da3a78 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5407,6 +5407,16 @@ 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
+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
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 a374b7f83888..ccfa69ce2608 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -53,3 +53,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 0d47f98ccbc0..b70d4b78d577 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -43,3 +43,4 @@ generated-y += mach-types.h
 generated-y += unistd-nr.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 e9939cbd9067..0c1e781ab10b 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -47,3 +47,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 3428415b1996..9115b215fc7e 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -49,3 +49,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..90a0d3df35c8
--- /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@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 weak 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 */
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 006e2863ad37..c28bcdecc764 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -36,3 +36,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 4a8471434a3e..c836f7e2a5e7 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -57,3 +57,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 e844d6058248..db9dff9c1535 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -23,3 +23,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 f11d1249738f..aaae8a9f6099 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -30,3 +30,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 60d8349241a7..7c06627a0a0d 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -10,3 +10,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/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index fcfc9d102348..8cd940c72895 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -108,6 +108,7 @@ SECTIONS
 		/* careful! __ftr_alt_* sections need to be close to .text */
 		*(.text .fixup __ftr_alt_* .ref.text)
 		*(SORT(.text.rng.*))
+		*(SORT(.text..tbl.*))
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index c1b85a361e5d..96dd69931427 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 28280887ac79..23a2216f4146 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -23,3 +23,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 33f7069763ae..a599f6f4ee0a 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -42,3 +42,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 b952dcb3e216..d2867aa09e23 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -28,3 +28,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 93abbfdab543..6671a1f08ead 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -62,3 +62,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 f672f2fc181d..4cb511f1067c 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -14,3 +14,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 f96fa2ddf7c9..484a24c309fb 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 2b7fe48c0225..7b41f32a2ba0 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -34,3 +34,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/tables.h b/include/asm-generic/tables.h
new file mode 100644
index 000000000000..16ef40d145fb
--- /dev/null
+++ b/include/asm-generic/tables.h
@@ -0,0 +1,48 @@
+#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..tbl.name.level
+
+/* Some toolchains are buggy, let them override */
+#ifndef SECTION_TBL_RO
+# define SECTION_TBL_RO	.rodata
+#endif
+
+#define SECTION_TBL_RO_STR __stringify(SECTION_TBL_RO)
+
+#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, 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, 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 71bfd3b3c719..ce1e9a310ada 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)
@@ -207,6 +208,7 @@
 #define DATA_DATA							\
 	*(.data .data.[0-9a-zA-Z_]*)					\
 	*(SORT(.data..rng.*))						\
+	*(SORT(.data..tbl.*))						\
 	*(.ref.data)							\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -277,6 +279,7 @@
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
 		*(.rodata)						\
 		*(SORT(.rodata..rng.*))					\
+		*(SORT(.rodata..tbl.*))					\
 		*(.rodata.*)						\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		KEEP(*(__vermagic))	/* Kernel version magic */	\
@@ -452,6 +455,7 @@
 		ALIGN_FUNCTION();					\
 		*(.text.hot .text)					\
 		*(SORT(.text..rng.*))					\
+		*(SORT(.text..tbl.*))					\
 		*(.text.fixup .text.unlikely)				\
 		*(.ref.text)						\
 	MEM_KEEP(init.text)						\
@@ -556,6 +560,7 @@
 	KEEP(*(SORT(___kentry+*)))					\
 	*(.init.data)							\
 	*(SORT(.init.data..rng.*))					\
+	*(SORT(.init.data..tbl.*))					\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -580,6 +585,7 @@
 #define INIT_TEXT							\
 	*(.init.text)							\
 	*(SORT(.init.text..rng.*))					\
+	*(SORT(.init.text..tbl.*))					\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
new file mode 100644
index 000000000000..1a1838d51951
--- /dev/null
+++ b/include/linux/tables.h
@@ -0,0 +1,612 @@
+#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(.foo..tbl.*))
+ *
+ * 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_START - get address of start of linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the start address of the linker table.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINKTABLE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * LINKTABLE_END - get address of end of the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define LINKTABLE_END(name)	LINUX_SECTION_END(name)
+
+/**
+ * LINKTABLE_SIZE - get number of entries in the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the number of entries in the linker table.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINKTABLE_SIZE(frobnicator_fns);
+ */
+#define LINKTABLE_SIZE(name)					\
+	((LINKTABLE_END(name)) - (LINKTABLE_START(name)))
+
+/**
+ * LINKTABLE_EMPTY - check if linker table has no entries
+ *
+ * @name: name of linker table
+ *
+ * Returns true if the linker table is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(frobnicator_fns);
+ */
+#define LINKTABLE_EMPTY(name)	(LINKTABLE_SIZE(name) == 0)
+
+/**
+ * LINKTABLE_ADDR_WITHIN - returns true if address is in the linker table
+ *
+ * @name: name of the linker table
+ * @addr: address to query for
+ *
+ * Returns true if the address is part of the linker table.
+ */
+#define LINKTABLE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) LINKTABLE_START(name) &&		\
+          addr < (unsigned long) LINKTABLE_END(name))
+
+/**
+ * LINKTABLE_ALIGNMENT - get the alignment of the linker table
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the linker table.
+ */
+#define LINKTABLE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * 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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_TEXT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE_RO(name, ~) LINKTABLE_END(name)[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_RO(type, name);				\
+	LINKTABLE_INIT_WEAK(name,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT_DATA(name, ~) LINKTABLE_END(name)[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 = LINKTABLE_START(tbl);				\
+	     pointer < LINKTABLE_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 < LINKTABLE_SIZE(tbl); i++)			\
+		(LINKTABLE_START(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 < LINKTABLE_SIZE(tbl); i++)		\
+		err = (LINKTABLE_START(tbl)[i]).func (args);		\
+	err;								\
+})
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_LINKER_TABLES_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 05/14] kbuild: enable option to force compile force-obj-y and force-lib-y
  2017-01-09 14:58       ` Luis R. Rodriguez
  (?)
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt

Linux provides a rich array of features, enabling each feature
however increases the size of the kernel and there are many
features which users often want disabled. The traditional
solution to this problem is for each feature to have its own
Kconfig symbol, followed by a series of #ifdef statements
in C code and header files, allowing the feature to be compiled
only when desirable. As the variability of Linux increases build
tests can and are often done with random kernel configurations,
allyesconfig, and allmodconfig to help find code issues. This
however doesn't catch all errors and as a consequence code that
is typically not enabled often can suffer from bit-rot over time.

An alternative approach for subsystems, which refer to as the 'build-all
link-selectively philosophy' is to keep the Kconfig symbols, replace
the #ifdef approach by having each feature implemented it its own C file,
and force compilation for all features to avoid the code bit-rot problem.
With this strategy only features that are enabled via Kconfig get
linked into the kernel, so the forced compilation has no size impact
on the kernel. The practice of having each feature implemented in its own
C file is already prevalent in many subsystems, however #ifdefs are still
typically required during feature initialization. For instance in:

  #ifdef CONFIG_FOO
  foo_init();
  #endif

We cannot remove the #ifdef and leave foo_init() as we'd either
need to always enable the feature or add a respective #ifdef in a
foo.h which makes foo_init() do nothing when CONFIG_FOO is disabled.

Linker tables enable lifting the requirement to use of #ifdefs during
initialization. With linker tables initialization sequences can instead
be aggregated into a custom ELF section at link time, during run time
the table can be iterated over and each init sequence enabled can be called.
A feature's init routine is only added to a table when its respective
Kconfig symbols has been enabled and therefore linked in. Linker tables
enable subsystems to completely do away with #ifdefs if one is comfortable
in accepting all subsystem's feature's structural size implications.

Subsystems which want to follow the 'build-all link-selectively
philosophy' still need a way to easily express and annotate that they
wish for all code to always be compiled to help avoid code bit rot,
as such two new targets force-obj-y and force-lib-y are provided to
help with this. Its not fair to require everyone to force compilation
of all features of a subsystem though, so as a compromise, the new
targets only force compilation when CONFIG_BUILD_AVOID_BITROT is
enabled.

Only built-in features are supported at the moment. Module support
is expected to be added after a generic solution to add linker
tables to modules more easily is developed.

v4: this patch was added to this series, it was split off from the
    linker tables addition due to the confusion over the code bit
    rot alternatives that are possible with linker tables.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/kbuild/makefiles.txt       | 36 ++++++++++++++++
 Documentation/sections/linker-tables.rst | 15 +++++++
 include/linux/tables.h                   | 71 ++++++++++++++++++++++++++++++++
 init/Kconfig                             | 22 ++++++++++
 scripts/Makefile.build                   |  7 ++--
 scripts/Makefile.clean                   |  2 +
 scripts/Makefile.lib                     | 11 +++++
 7 files changed, 161 insertions(+), 3 deletions(-)

diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 9b9c4797fc55..1af275cd4879 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -1090,6 +1090,42 @@ When kbuild executes, the following steps are followed (roughly):
 	In this example, extra-y is used to list object files that
 	shall be built, but shall not be linked as part of built-in.o.
 
+    force-obj-y force-lib-y
+
+	When CONFIG_BUILD_AVOID_BITROT is enabled using these targets for your
+	kconfig symbols forces compilation of the associated objects if the
+	kconfig's symbol's dependencies are met, the objects however are only
+	linked into to the kernel if and only if the kconfig symbol was
+	enabled. If CONFIG_BUILD_AVOID_BITROT is disabled the force-obj-y and
+	force-lib-y targets are functionally equilvalent to obj-y and lib-y
+	respectively.
+
+	Using force-obj-y and force-lib-y are part of a code architecture and
+	build philosophy further enabled by linker tables, for more details
+	refer to the documention in include/linux/tables.h, refer to the
+	sections:
+
+		o The code bit-rot problem
+		o The build-all selective-link philosophy
+		o Avoiding the code bit-rot problem with linker tables
+		o Linker table module support
+
+	Modules support is expected to be enhanced in the future, so for now
+	only built-in features are supported.
+
+	Example use:
+
+		force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	An alternative to using force-obj-y, is to use extra-y followed by the
+	respective obj-y:
+
+		extra-y += foo.o
+		obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	Using force-obj-y and force-lib-y can be used to help annotate the
+	targets follow the 'build-all selective-link philosophy' further
+	enabled by linker tables.
 
 --- 6.7 Commands useful for building a boot image
 
diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index 780a292d2d00..bc2d9f46cde6 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -30,6 +30,21 @@ How linker tables simplify initialization code
 .. kernel-doc:: include/linux/tables.h
    :doc: How linker tables simplify initialization code
 
+The code bit-rot problem
+------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The code bit-rot problem
+
+The build-all selective-link philosophy
+---------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The build-all selective-link philosophy
+
+Avoiding the code bit-rot problem with linker tables
+----------------------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: Avoiding the code bit-rot problem with linker tables
+
 Using linker tables in Linux
 ==============
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
index 1a1838d51951..70a41edfa127 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -169,6 +169,77 @@
  */
 
 /**
+ * DOC: The code bit-rot problem
+ *
+ * Linux provides a rich array of features, enabling each feature
+ * however increases the size of the kernel and there are many
+ * features which users often want disabled. The traditional
+ * solution to this problem is for each feature to have its own
+ * Kconfig symbol, followed by a series of #ifdef statements
+ * in C code and header files, allowing the feature to be compiled
+ * only when desirable. As the variability of Linux increases build
+ * tests can and are often done with random kernel configurations,
+ * allyesconfig, and allmodconfig to help find code issues. This
+ * however doesn't catch all errors and as a consequence code that
+ * is typically not enabled often can suffer from bit-rot over time.
+ */
+
+/**
+ * DOC: The build-all selective-link philosophy
+ *
+ * A code architecture philosophy to help avoid code bit-rot consists
+ * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
+ * by instead having each feature implemented it its own C file, and force
+ * compilation for all features. Only features that are enabled get linked in,
+ * the forced compilation therefore has no size impact on the final result of
+ * the kernel. The practice of having each feature implemented in its own C
+ * file is already prevalent in many subsystems, however #ifdefs are still
+ * typically required during feature initialization. For instance in::
+ *
+ *	#ifdef CONFIG_FOO
+ *	foo_init();
+ *	#endif
+ *
+ * We cannot remove the #ifdef and leave foo_init() as we'd either
+ * need to always enable the feature or add a respective #ifdef in a
+ * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem with linker tables
+ *
+ * Linker tables can be used to further help avoid the code bit-rot problem
+ * when embracing the 'build-all selective-link philosophy' by lifting the
+ * requirement to use of #ifdefs during initialization. With linker tables
+ * initialization sequences can be aggregated into a custom ELF section at
+ * link time, during run time the table can be iterated over and each init
+ * sequence enabled can be called. A feature's init routine is only added to a
+ * table when its respective Kconfig symbols has been enabled and therefore
+ * linked in. Linker tables enable subsystems to completely do away with
+ * #ifdefs if one is comfortable in accepting all subsystem's feature's
+ * structural size implications.
+ *
+ * To further help with this the Linux build system supports two special
+ * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
+ * follow the 'build-all selective-link philosophy' can use these targets for a
+ * feature's kconfig symbol. Using these targets will always require
+ * compilation of the kconfig's objects if the kconfig symbol's dependencies
+ * are met but only link the objects into the kernel, and therefore enable the
+ * feature, if and only if the kconfig symbol has been enabled.
+ *
+ * Not all users or build systems may want to opt-in to compile all objects
+ * following the 'build-all selective-link philosophy', as such the targets
+ * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
+ * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
+ * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
+ * ``obj-y`` and ``lib-y`` respectively.
+ *
+ * Example use::
+ *
+ * 	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+ */
+
+/**
  * DOC: Linker table module support
  *
  * Modules can use linker tables, however the linker table definition
diff --git a/init/Kconfig b/init/Kconfig
index d0caacb4bc14..ce934ea6a7f1 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -63,6 +63,28 @@ config CROSS_COMPILE
 	  need to set this unless you want the configured kernel build
 	  directory to select the cross-compiler automatically.
 
+config BUILD_AVOID_BITROT
+	bool "Enable force building of force-obj-y and force-lib-y"
+	default n
+	help
+	  When enabled objects under the force-obj-y and force-lib-y targets
+	  using a Kconfig symbol will be forced to compile if the Kconfig
+	  symbol's dependencies are met but only linked into the kernel if
+	  the Kconfig symbol is enabled. If a Kconfig symbol on a force-obj-y
+	  or force-lib-y target is disabled, it will be compiled but not linked
+	  into the kernel.
+
+	  The force-obj-y and force-lib-y targets can be used by subsystems
+	  which wish to want to follow the 'build-all selective-link philosophy'
+	  documented under include/linux/tables.h.
+
+	  Say Y if you have a decent build machine and would like to help test
+	  building code for more subsystems. Say N if you do you not have a
+	  good build machine or only want to compile what you've enabled for
+	  your kernel.
+
+	  Enabling this option never increases the size of your kernel.
+
 config COMPILE_TEST
 	bool "Compile also drivers which will not load"
 	depends on !UML
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index eadcd4d359d9..c34af839d47c 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -92,7 +92,8 @@ modorder-target := $(obj)/modules.order
 
 # We keep a list of all modules in $(MODVERDIR)
 
-__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
+__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y) \
+				$(force-obj-y)) \
 	 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
 	 $(subdir-ym) $(always)
 	@:
@@ -392,8 +393,8 @@ endif
 $(obj)/%.o: $(src)/%.S $(objtool_obj) FORCE
 	$(call if_changed_rule,as_o_S)
 
-targets += $(real-objs-y) $(real-objs-m) $(lib-y)
-targets += $(extra-y) $(MAKECMDGOALS) $(always)
+targets += $(real-objs-y) $(real-objs-m) $(lib-y) $(force-lib-y)
+targets += $(extra-y) $(force-obj-y) $(MAKECMDGOALS) $(always)
 
 # Linker scripts preprocessor (.lds.S -> .lds)
 # ---------------------------------------------------------------------------
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-) \
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 0a07f9014944..d1cb0cfdf1bf 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -12,6 +12,15 @@ export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y)
 # Figure out what we need to build from the various variables
 # ===================================== 
+ifeq ($(CONFIG_BUILD_AVOID_BITROT),y)
+extra-y += $(force-obj-) $(force-lib-)
+endif
+
+obj-m += $(force-obj-m)
+obj-y += $(force-obj-y)
+lib-m += $(force-lib-m)
+lib-y += $(force-lib-y)
+
 # When an object is listed to be built compiled-in and modular,
 # only build the compiled-in version
 
@@ -72,6 +81,8 @@ real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)
 # Add subdir path
 
 extra-y		:= $(addprefix $(obj)/,$(extra-y))
+force-obj-y		:= $(addprefix $(obj)/,$(force-obj-y))
+force-obj-m		:= $(addprefix $(obj)/,$(force-obj-m))
 always		:= $(addprefix $(obj)/,$(always))
 targets		:= $(addprefix $(obj)/,$(targets))
 modorder	:= $(addprefix $(obj)/,$(modorder))
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 05/14] kbuild: enable option to force compile force-obj-y and force-lib-y
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt, ak

Linux provides a rich array of features, enabling each feature
however increases the size of the kernel and there are many
features which users often want disabled. The traditional
solution to this problem is for each feature to have its own
Kconfig symbol, followed by a series of #ifdef statements
in C code and header files, allowing the feature to be compiled
only when desirable. As the variability of Linux increases build
tests can and are often done with random kernel configurations,
allyesconfig, and allmodconfig to help find code issues. This
however doesn't catch all errors and as a consequence code that
is typically not enabled often can suffer from bit-rot over time.

An alternative approach for subsystems, which refer to as the 'build-all
link-selectively philosophy' is to keep the Kconfig symbols, replace
the #ifdef approach by having each feature implemented it its own C file,
and force compilation for all features to avoid the code bit-rot problem.
With this strategy only features that are enabled via Kconfig get
linked into the kernel, so the forced compilation has no size impact
on the kernel. The practice of having each feature implemented in its own
C file is already prevalent in many subsystems, however #ifdefs are still
typically required during feature initialization. For instance in:

  #ifdef CONFIG_FOO
  foo_init();
  #endif

We cannot remove the #ifdef and leave foo_init() as we'd either
need to always enable the feature or add a respective #ifdef in a
foo.h which makes foo_init() do nothing when CONFIG_FOO is disabled.

Linker tables enable lifting the requirement to use of #ifdefs during
initialization. With linker tables initialization sequences can instead
be aggregated into a custom ELF section at link time, during run time
the table can be iterated over and each init sequence enabled can be called.
A feature's init routine is only added to a table when its respective
Kconfig symbols has been enabled and therefore linked in. Linker tables
enable subsystems to completely do away with #ifdefs if one is comfortable
in accepting all subsystem's feature's structural size implications.

Subsystems which want to follow the 'build-all link-selectively
philosophy' still need a way to easily express and annotate that they
wish for all code to always be compiled to help avoid code bit rot,
as such two new targets force-obj-y and force-lib-y are provided to
help with this. Its not fair to require everyone to force compilation
of all features of a subsystem though, so as a compromise, the new
targets only force compilation when CONFIG_BUILD_AVOID_BITROT is
enabled.

Only built-in features are supported at the moment. Module support
is expected to be added after a generic solution to add linker
tables to modules more easily is developed.

v4: this patch was added to this series, it was split off from the
    linker tables addition due to the confusion over the code bit
    rot alternatives that are possible with linker tables.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/kbuild/makefiles.txt       | 36 ++++++++++++++++
 Documentation/sections/linker-tables.rst | 15 +++++++
 include/linux/tables.h                   | 71 ++++++++++++++++++++++++++++++++
 init/Kconfig                             | 22 ++++++++++
 scripts/Makefile.build                   |  7 ++--
 scripts/Makefile.clean                   |  2 +
 scripts/Makefile.lib                     | 11 +++++
 7 files changed, 161 insertions(+), 3 deletions(-)

diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 9b9c4797fc55..1af275cd4879 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -1090,6 +1090,42 @@ When kbuild executes, the following steps are followed (roughly):
 	In this example, extra-y is used to list object files that
 	shall be built, but shall not be linked as part of built-in.o.
 
+    force-obj-y force-lib-y
+
+	When CONFIG_BUILD_AVOID_BITROT is enabled using these targets for your
+	kconfig symbols forces compilation of the associated objects if the
+	kconfig's symbol's dependencies are met, the objects however are only
+	linked into to the kernel if and only if the kconfig symbol was
+	enabled. If CONFIG_BUILD_AVOID_BITROT is disabled the force-obj-y and
+	force-lib-y targets are functionally equilvalent to obj-y and lib-y
+	respectively.
+
+	Using force-obj-y and force-lib-y are part of a code architecture and
+	build philosophy further enabled by linker tables, for more details
+	refer to the documention in include/linux/tables.h, refer to the
+	sections:
+
+		o The code bit-rot problem
+		o The build-all selective-link philosophy
+		o Avoiding the code bit-rot problem with linker tables
+		o Linker table module support
+
+	Modules support is expected to be enhanced in the future, so for now
+	only built-in features are supported.
+
+	Example use:
+
+		force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	An alternative to using force-obj-y, is to use extra-y followed by the
+	respective obj-y:
+
+		extra-y += foo.o
+		obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	Using force-obj-y and force-lib-y can be used to help annotate the
+	targets follow the 'build-all selective-link philosophy' further
+	enabled by linker tables.
 
 --- 6.7 Commands useful for building a boot image
 
diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index 780a292d2d00..bc2d9f46cde6 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -30,6 +30,21 @@ How linker tables simplify initialization code
 .. kernel-doc:: include/linux/tables.h
    :doc: How linker tables simplify initialization code
 
+The code bit-rot problem
+------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The code bit-rot problem
+
+The build-all selective-link philosophy
+---------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The build-all selective-link philosophy
+
+Avoiding the code bit-rot problem with linker tables
+----------------------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: Avoiding the code bit-rot problem with linker tables
+
 Using linker tables in Linux
 ============================
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
index 1a1838d51951..70a41edfa127 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -169,6 +169,77 @@
  */
 
 /**
+ * DOC: The code bit-rot problem
+ *
+ * Linux provides a rich array of features, enabling each feature
+ * however increases the size of the kernel and there are many
+ * features which users often want disabled. The traditional
+ * solution to this problem is for each feature to have its own
+ * Kconfig symbol, followed by a series of #ifdef statements
+ * in C code and header files, allowing the feature to be compiled
+ * only when desirable. As the variability of Linux increases build
+ * tests can and are often done with random kernel configurations,
+ * allyesconfig, and allmodconfig to help find code issues. This
+ * however doesn't catch all errors and as a consequence code that
+ * is typically not enabled often can suffer from bit-rot over time.
+ */
+
+/**
+ * DOC: The build-all selective-link philosophy
+ *
+ * A code architecture philosophy to help avoid code bit-rot consists
+ * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
+ * by instead having each feature implemented it its own C file, and force
+ * compilation for all features. Only features that are enabled get linked in,
+ * the forced compilation therefore has no size impact on the final result of
+ * the kernel. The practice of having each feature implemented in its own C
+ * file is already prevalent in many subsystems, however #ifdefs are still
+ * typically required during feature initialization. For instance in::
+ *
+ *	#ifdef CONFIG_FOO
+ *	foo_init();
+ *	#endif
+ *
+ * We cannot remove the #ifdef and leave foo_init() as we'd either
+ * need to always enable the feature or add a respective #ifdef in a
+ * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem with linker tables
+ *
+ * Linker tables can be used to further help avoid the code bit-rot problem
+ * when embracing the 'build-all selective-link philosophy' by lifting the
+ * requirement to use of #ifdefs during initialization. With linker tables
+ * initialization sequences can be aggregated into a custom ELF section at
+ * link time, during run time the table can be iterated over and each init
+ * sequence enabled can be called. A feature's init routine is only added to a
+ * table when its respective Kconfig symbols has been enabled and therefore
+ * linked in. Linker tables enable subsystems to completely do away with
+ * #ifdefs if one is comfortable in accepting all subsystem's feature's
+ * structural size implications.
+ *
+ * To further help with this the Linux build system supports two special
+ * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
+ * follow the 'build-all selective-link philosophy' can use these targets for a
+ * feature's kconfig symbol. Using these targets will always require
+ * compilation of the kconfig's objects if the kconfig symbol's dependencies
+ * are met but only link the objects into the kernel, and therefore enable the
+ * feature, if and only if the kconfig symbol has been enabled.
+ *
+ * Not all users or build systems may want to opt-in to compile all objects
+ * following the 'build-all selective-link philosophy', as such the targets
+ * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
+ * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
+ * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
+ * ``obj-y`` and ``lib-y`` respectively.
+ *
+ * Example use::
+ *
+ * 	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+ */
+
+/**
  * DOC: Linker table module support
  *
  * Modules can use linker tables, however the linker table definition
diff --git a/init/Kconfig b/init/Kconfig
index d0caacb4bc14..ce934ea6a7f1 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -63,6 +63,28 @@ config CROSS_COMPILE
 	  need to set this unless you want the configured kernel build
 	  directory to select the cross-compiler automatically.
 
+config BUILD_AVOID_BITROT
+	bool "Enable force building of force-obj-y and force-lib-y"
+	default n
+	help
+	  When enabled objects under the force-obj-y and force-lib-y targets
+	  using a Kconfig symbol will be forced to compile if the Kconfig
+	  symbol's dependencies are met but only linked into the kernel if
+	  the Kconfig symbol is enabled. If a Kconfig symbol on a force-obj-y
+	  or force-lib-y target is disabled, it will be compiled but not linked
+	  into the kernel.
+
+	  The force-obj-y and force-lib-y targets can be used by subsystems
+	  which wish to want to follow the 'build-all selective-link philosophy'
+	  documented under include/linux/tables.h.
+
+	  Say Y if you have a decent build machine and would like to help test
+	  building code for more subsystems. Say N if you do you not have a
+	  good build machine or only want to compile what you've enabled for
+	  your kernel.
+
+	  Enabling this option never increases the size of your kernel.
+
 config COMPILE_TEST
 	bool "Compile also drivers which will not load"
 	depends on !UML
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index eadcd4d359d9..c34af839d47c 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -92,7 +92,8 @@ modorder-target := $(obj)/modules.order
 
 # We keep a list of all modules in $(MODVERDIR)
 
-__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
+__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y) \
+				$(force-obj-y)) \
 	 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
 	 $(subdir-ym) $(always)
 	@:
@@ -392,8 +393,8 @@ endif
 $(obj)/%.o: $(src)/%.S $(objtool_obj) FORCE
 	$(call if_changed_rule,as_o_S)
 
-targets += $(real-objs-y) $(real-objs-m) $(lib-y)
-targets += $(extra-y) $(MAKECMDGOALS) $(always)
+targets += $(real-objs-y) $(real-objs-m) $(lib-y) $(force-lib-y)
+targets += $(extra-y) $(force-obj-y) $(MAKECMDGOALS) $(always)
 
 # Linker scripts preprocessor (.lds.S -> .lds)
 # ---------------------------------------------------------------------------
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-) \
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 0a07f9014944..d1cb0cfdf1bf 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -12,6 +12,15 @@ export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y)
 # Figure out what we need to build from the various variables
 # ===========================================================================
 
+ifeq ($(CONFIG_BUILD_AVOID_BITROT),y)
+extra-y += $(force-obj-) $(force-lib-)
+endif
+
+obj-m += $(force-obj-m)
+obj-y += $(force-obj-y)
+lib-m += $(force-lib-m)
+lib-y += $(force-lib-y)
+
 # When an object is listed to be built compiled-in and modular,
 # only build the compiled-in version
 
@@ -72,6 +81,8 @@ real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)
 # Add subdir path
 
 extra-y		:= $(addprefix $(obj)/,$(extra-y))
+force-obj-y		:= $(addprefix $(obj)/,$(force-obj-y))
+force-obj-m		:= $(addprefix $(obj)/,$(force-obj-m))
 always		:= $(addprefix $(obj)/,$(always))
 targets		:= $(addprefix $(obj)/,$(targets))
 modorder	:= $(addprefix $(obj)/,$(modorder))
-- 
2.11.0


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 05/14] kbuild: enable option to force compile force-obj-y and force-lib-y
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

Linux provides a rich array of features, enabling each feature
however increases the size of the kernel and there are many
features which users often want disabled. The traditional
solution to this problem is for each feature to have its own
Kconfig symbol, followed by a series of #ifdef statements
in C code and header files, allowing the feature to be compiled
only when desirable. As the variability of Linux increases build
tests can and are often done with random kernel configurations,
allyesconfig, and allmodconfig to help find code issues. This
however doesn't catch all errors and as a consequence code that
is typically not enabled often can suffer from bit-rot over time.

An alternative approach for subsystems, which refer to as the 'build-all
link-selectively philosophy' is to keep the Kconfig symbols, replace
the #ifdef approach by having each feature implemented it its own C file,
and force compilation for all features to avoid the code bit-rot problem.
With this strategy only features that are enabled via Kconfig get
linked into the kernel, so the forced compilation has no size impact
on the kernel. The practice of having each feature implemented in its own
C file is already prevalent in many subsystems, however #ifdefs are still
typically required during feature initialization. For instance in:

  #ifdef CONFIG_FOO
  foo_init();
  #endif

We cannot remove the #ifdef and leave foo_init() as we'd either
need to always enable the feature or add a respective #ifdef in a
foo.h which makes foo_init() do nothing when CONFIG_FOO is disabled.

Linker tables enable lifting the requirement to use of #ifdefs during
initialization. With linker tables initialization sequences can instead
be aggregated into a custom ELF section at link time, during run time
the table can be iterated over and each init sequence enabled can be called.
A feature's init routine is only added to a table when its respective
Kconfig symbols has been enabled and therefore linked in. Linker tables
enable subsystems to completely do away with #ifdefs if one is comfortable
in accepting all subsystem's feature's structural size implications.

Subsystems which want to follow the 'build-all link-selectively
philosophy' still need a way to easily express and annotate that they
wish for all code to always be compiled to help avoid code bit rot,
as such two new targets force-obj-y and force-lib-y are provided to
help with this. Its not fair to require everyone to force compilation
of all features of a subsystem though, so as a compromise, the new
targets only force compilation when CONFIG_BUILD_AVOID_BITROT is
enabled.

Only built-in features are supported at the moment. Module support
is expected to be added after a generic solution to add linker
tables to modules more easily is developed.

v4: this patch was added to this series, it was split off from the
    linker tables addition due to the confusion over the code bit
    rot alternatives that are possible with linker tables.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/kbuild/makefiles.txt       | 36 ++++++++++++++++
 Documentation/sections/linker-tables.rst | 15 +++++++
 include/linux/tables.h                   | 71 ++++++++++++++++++++++++++++++++
 init/Kconfig                             | 22 ++++++++++
 scripts/Makefile.build                   |  7 ++--
 scripts/Makefile.clean                   |  2 +
 scripts/Makefile.lib                     | 11 +++++
 7 files changed, 161 insertions(+), 3 deletions(-)

diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 9b9c4797fc55..1af275cd4879 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -1090,6 +1090,42 @@ When kbuild executes, the following steps are followed (roughly):
 	In this example, extra-y is used to list object files that
 	shall be built, but shall not be linked as part of built-in.o.
 
+    force-obj-y force-lib-y
+
+	When CONFIG_BUILD_AVOID_BITROT is enabled using these targets for your
+	kconfig symbols forces compilation of the associated objects if the
+	kconfig's symbol's dependencies are met, the objects however are only
+	linked into to the kernel if and only if the kconfig symbol was
+	enabled. If CONFIG_BUILD_AVOID_BITROT is disabled the force-obj-y and
+	force-lib-y targets are functionally equilvalent to obj-y and lib-y
+	respectively.
+
+	Using force-obj-y and force-lib-y are part of a code architecture and
+	build philosophy further enabled by linker tables, for more details
+	refer to the documention in include/linux/tables.h, refer to the
+	sections:
+
+		o The code bit-rot problem
+		o The build-all selective-link philosophy
+		o Avoiding the code bit-rot problem with linker tables
+		o Linker table module support
+
+	Modules support is expected to be enhanced in the future, so for now
+	only built-in features are supported.
+
+	Example use:
+
+		force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	An alternative to using force-obj-y, is to use extra-y followed by the
+	respective obj-y:
+
+		extra-y += foo.o
+		obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	Using force-obj-y and force-lib-y can be used to help annotate the
+	targets follow the 'build-all selective-link philosophy' further
+	enabled by linker tables.
 
 --- 6.7 Commands useful for building a boot image
 
diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index 780a292d2d00..bc2d9f46cde6 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -30,6 +30,21 @@ How linker tables simplify initialization code
 .. kernel-doc:: include/linux/tables.h
    :doc: How linker tables simplify initialization code
 
+The code bit-rot problem
+------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The code bit-rot problem
+
+The build-all selective-link philosophy
+---------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The build-all selective-link philosophy
+
+Avoiding the code bit-rot problem with linker tables
+----------------------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: Avoiding the code bit-rot problem with linker tables
+
 Using linker tables in Linux
 ============================
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
index 1a1838d51951..70a41edfa127 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -169,6 +169,77 @@
  */
 
 /**
+ * DOC: The code bit-rot problem
+ *
+ * Linux provides a rich array of features, enabling each feature
+ * however increases the size of the kernel and there are many
+ * features which users often want disabled. The traditional
+ * solution to this problem is for each feature to have its own
+ * Kconfig symbol, followed by a series of #ifdef statements
+ * in C code and header files, allowing the feature to be compiled
+ * only when desirable. As the variability of Linux increases build
+ * tests can and are often done with random kernel configurations,
+ * allyesconfig, and allmodconfig to help find code issues. This
+ * however doesn't catch all errors and as a consequence code that
+ * is typically not enabled often can suffer from bit-rot over time.
+ */
+
+/**
+ * DOC: The build-all selective-link philosophy
+ *
+ * A code architecture philosophy to help avoid code bit-rot consists
+ * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
+ * by instead having each feature implemented it its own C file, and force
+ * compilation for all features. Only features that are enabled get linked in,
+ * the forced compilation therefore has no size impact on the final result of
+ * the kernel. The practice of having each feature implemented in its own C
+ * file is already prevalent in many subsystems, however #ifdefs are still
+ * typically required during feature initialization. For instance in::
+ *
+ *	#ifdef CONFIG_FOO
+ *	foo_init();
+ *	#endif
+ *
+ * We cannot remove the #ifdef and leave foo_init() as we'd either
+ * need to always enable the feature or add a respective #ifdef in a
+ * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem with linker tables
+ *
+ * Linker tables can be used to further help avoid the code bit-rot problem
+ * when embracing the 'build-all selective-link philosophy' by lifting the
+ * requirement to use of #ifdefs during initialization. With linker tables
+ * initialization sequences can be aggregated into a custom ELF section at
+ * link time, during run time the table can be iterated over and each init
+ * sequence enabled can be called. A feature's init routine is only added to a
+ * table when its respective Kconfig symbols has been enabled and therefore
+ * linked in. Linker tables enable subsystems to completely do away with
+ * #ifdefs if one is comfortable in accepting all subsystem's feature's
+ * structural size implications.
+ *
+ * To further help with this the Linux build system supports two special
+ * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
+ * follow the 'build-all selective-link philosophy' can use these targets for a
+ * feature's kconfig symbol. Using these targets will always require
+ * compilation of the kconfig's objects if the kconfig symbol's dependencies
+ * are met but only link the objects into the kernel, and therefore enable the
+ * feature, if and only if the kconfig symbol has been enabled.
+ *
+ * Not all users or build systems may want to opt-in to compile all objects
+ * following the 'build-all selective-link philosophy', as such the targets
+ * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
+ * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
+ * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
+ * ``obj-y`` and ``lib-y`` respectively.
+ *
+ * Example use::
+ *
+ * 	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+ */
+
+/**
  * DOC: Linker table module support
  *
  * Modules can use linker tables, however the linker table definition
diff --git a/init/Kconfig b/init/Kconfig
index d0caacb4bc14..ce934ea6a7f1 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -63,6 +63,28 @@ config CROSS_COMPILE
 	  need to set this unless you want the configured kernel build
 	  directory to select the cross-compiler automatically.
 
+config BUILD_AVOID_BITROT
+	bool "Enable force building of force-obj-y and force-lib-y"
+	default n
+	help
+	  When enabled objects under the force-obj-y and force-lib-y targets
+	  using a Kconfig symbol will be forced to compile if the Kconfig
+	  symbol's dependencies are met but only linked into the kernel if
+	  the Kconfig symbol is enabled. If a Kconfig symbol on a force-obj-y
+	  or force-lib-y target is disabled, it will be compiled but not linked
+	  into the kernel.
+
+	  The force-obj-y and force-lib-y targets can be used by subsystems
+	  which wish to want to follow the 'build-all selective-link philosophy'
+	  documented under include/linux/tables.h.
+
+	  Say Y if you have a decent build machine and would like to help test
+	  building code for more subsystems. Say N if you do you not have a
+	  good build machine or only want to compile what you've enabled for
+	  your kernel.
+
+	  Enabling this option never increases the size of your kernel.
+
 config COMPILE_TEST
 	bool "Compile also drivers which will not load"
 	depends on !UML
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index eadcd4d359d9..c34af839d47c 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -92,7 +92,8 @@ modorder-target := $(obj)/modules.order
 
 # We keep a list of all modules in $(MODVERDIR)
 
-__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
+__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y) \
+				$(force-obj-y)) \
 	 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
 	 $(subdir-ym) $(always)
 	@:
@@ -392,8 +393,8 @@ endif
 $(obj)/%.o: $(src)/%.S $(objtool_obj) FORCE
 	$(call if_changed_rule,as_o_S)
 
-targets += $(real-objs-y) $(real-objs-m) $(lib-y)
-targets += $(extra-y) $(MAKECMDGOALS) $(always)
+targets += $(real-objs-y) $(real-objs-m) $(lib-y) $(force-lib-y)
+targets += $(extra-y) $(force-obj-y) $(MAKECMDGOALS) $(always)
 
 # Linker scripts preprocessor (.lds.S -> .lds)
 # ---------------------------------------------------------------------------
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-) \
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 0a07f9014944..d1cb0cfdf1bf 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -12,6 +12,15 @@ export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y)
 # Figure out what we need to build from the various variables
 # ===========================================================================
 
+ifeq ($(CONFIG_BUILD_AVOID_BITROT),y)
+extra-y += $(force-obj-) $(force-lib-)
+endif
+
+obj-m += $(force-obj-m)
+obj-y += $(force-obj-y)
+lib-m += $(force-lib-m)
+lib-y += $(force-lib-y)
+
 # When an object is listed to be built compiled-in and modular,
 # only build the compiled-in version
 
@@ -72,6 +81,8 @@ real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)
 # Add subdir path
 
 extra-y		:= $(addprefix $(obj)/,$(extra-y))
+force-obj-y		:= $(addprefix $(obj)/,$(force-obj-y))
+force-obj-m		:= $(addprefix $(obj)/,$(force-obj-m))
 always		:= $(addprefix $(obj)/,$(always))
 targets		:= $(addprefix $(obj)/,$(targets))
 modorder	:= $(addprefix $(obj)/,$(modorder))
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 06/14] firmware/Makefile: force recompilation if makefile changes
  2017-01-09 14:58       ` Luis R. Rodriguez
  (?)
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt

If you modify the target asm we currently do not force the
recompilation of the firmware files. The target asm is in
the firmware/Makefile, peg this file as a dependency to
require re-compilation of firmware targets when the asm
changes.

v3: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 firmware/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/firmware/Makefile b/firmware/Makefile
index e297e1b52636..fa3e81c2a97b 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -176,7 +176,8 @@ quiet_cmd_fwbin = MK_FW   $@
 wordsize_deps := $(wildcard include/config/64bit.h include/config/32bit.h \
 		include/config/ppc32.h include/config/ppc64.h \
 		include/config/superh32.h include/config/superh64.h \
-		include/config/x86_32.h include/config/x86_64.h)
+		include/config/x86_32.h include/config/x86_64.h \
+		firmware/Makefile)
 
 $(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)): %: $(wordsize_deps)
 	$(call cmd,fwbin,$(patsubst %.gen.S,%,$@))
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 06/14] firmware/Makefile: force recompilation if makefile changes
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt, ak

If you modify the target asm we currently do not force the
recompilation of the firmware files. The target asm is in
the firmware/Makefile, peg this file as a dependency to
require re-compilation of firmware targets when the asm
changes.

v3: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 firmware/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/firmware/Makefile b/firmware/Makefile
index e297e1b52636..fa3e81c2a97b 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -176,7 +176,8 @@ quiet_cmd_fwbin = MK_FW   $@
 wordsize_deps := $(wildcard include/config/64bit.h include/config/32bit.h \
 		include/config/ppc32.h include/config/ppc64.h \
 		include/config/superh32.h include/config/superh64.h \
-		include/config/x86_32.h include/config/x86_64.h)
+		include/config/x86_32.h include/config/x86_64.h \
+		firmware/Makefile)
 
 $(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)): %: $(wordsize_deps)
 	$(call cmd,fwbin,$(patsubst %.gen.S,%,$@))
-- 
2.11.0


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 06/14] firmware/Makefile: force recompilation if makefile changes
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

If you modify the target asm we currently do not force the
recompilation of the firmware files. The target asm is in
the firmware/Makefile, peg this file as a dependency to
require re-compilation of firmware targets when the asm
changes.

v3: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 firmware/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/firmware/Makefile b/firmware/Makefile
index e297e1b52636..fa3e81c2a97b 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -176,7 +176,8 @@ quiet_cmd_fwbin = MK_FW   $@
 wordsize_deps := $(wildcard include/config/64bit.h include/config/32bit.h \
 		include/config/ppc32.h include/config/ppc64.h \
 		include/config/superh32.h include/config/superh64.h \
-		include/config/x86_32.h include/config/x86_64.h)
+		include/config/x86_32.h include/config/x86_64.h \
+		firmware/Makefile)
 
 $(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)): %: $(wordsize_deps)
 	$(call cmd,fwbin,$(patsubst %.gen.S,%,$@))
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 07/14] firmware: port built-in section to linker table
  2017-01-09 14:58       ` Luis R. Rodriguez
  (?)
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, Michael Matz, Barry Song, mchehab,
	linux-arch, markus.heiser, xen-devel, msalter, linux-sh, mpe,
	joro, x86, fontana, dsahern, linux-arm-kernel, catalin.marinas,
	dvhart, dwmw2, linux, linux-xtensa, pali.rohar, Mike Frysinger,
	keescook

This ports built-in firmware to use linker tables,
this replaces the custom section solution with a
generic solution.

This also demos the use of the .rodata linker table.

Tested with 0 built-in firmware, 1 and 2 built-in
firmwares successfully.

v6: rename table macro as suggested by Andy Shevchenko

v5:

o since we dropped SECTION_ORDER_ANY, use 'any' order level explicitly

v4:

o work around c6x toolchain bug by using SECTION_TBL_RO

o fix compilation on blackfin

v3:
o explicitly include tables.h as we no longer include
  tables.h from sections.h

o use new section_tbl_asmtype() helper on firmware/Makefile
  to enable having to unfold things on our own.

v2: introduced this file in this version of the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/x86/kernel/cpu/microcode/core.c |  8 ++++----
 drivers/base/firmware_class.c        | 12 ++++++------
 firmware/Makefile                    |  3 ++-
 include/asm-generic/vmlinux.lds.h    |  7 -------
 4 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 2af69d27da62..2c5004343b45 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -31,6 +31,7 @@
 #include <linux/cpu.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/tables.h>
 
 #include <asm/microcode_intel.h>
 #include <asm/cpu_device_id.h>
@@ -110,15 +111,14 @@ static bool __init check_loader_disabled_bsp(void)
 	return *res;
 }
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DECLARE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 bool get_builtin_firmware(struct cpio_data *cd, const char *name)
 {
 #ifdef CONFIG_FW_LOADER
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	linktable_for_each(b_fw, builtin_fw) {
 		if (!strcmp(name, b_fw->name)) {
 			cd->size = b_fw->size;
 			cd->data = b_fw->data;
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 4497d263209f..b9ac348e8d33 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -31,6 +31,7 @@
 #include <linux/reboot.h>
 #include <linux/security.h>
 #include <linux/swait.h>
+#include <linux/tables.h>
 
 #include <generated/utsrelease.h>
 
@@ -44,15 +45,14 @@ MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_FW_LOADER
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DEFINE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 				    void *buf, size_t size)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	linktable_for_each(b_fw, builtin_fw) {
 		if (strcmp(name, b_fw->name) = 0) {
 			fw->size = b_fw->size;
 			fw->data = b_fw->data;
@@ -68,9 +68,9 @@ static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 
 static bool fw_is_builtin_firmware(const struct firmware *fw)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++)
+	linktable_for_each(b_fw, builtin_fw)
 		if (fw->data = b_fw->data)
 			return true;
 
diff --git a/firmware/Makefile b/firmware/Makefile
index fa3e81c2a97b..9c8cae144ede 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -155,6 +155,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  ASM_ALIGN=$(if $(CONFIG_64BIT),3,2);			     \
 		  PROGBITS=$(if $(CONFIG_ARM),%,@)progbits;		     \
 		  echo "/* Generated by firmware/Makefile */"		> $@;\
+		  echo "\#include <asm/tables.h>"			>>$@;\
 		  echo "    .section .rodata"				>>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_bin:"				>>$@;\
@@ -164,7 +165,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_name:"				>>$@;\
 		  echo "    .string \"$$FWNAME\""			>>$@;\
-		  echo "    .section .builtin_fw,\"a\",$${PROGBITS}"	>>$@;\
+		  echo "    set_section_tbl_type(SECTION_TBL_RO, builtin_fw, any, a,$${PROGBITS})" >>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_name"		>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_bin"		>>$@;\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index ce1e9a310ada..8a5325d75932 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -324,13 +324,6 @@
 		VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .;	\
 	}								\
 									\
-	/* Built-in firmware blobs */					\
-	.builtin_fw        : AT(ADDR(.builtin_fw) - LOAD_OFFSET) {	\
-		VMLINUX_SYMBOL(__start_builtin_fw) = .;			\
-		KEEP(*(.builtin_fw))					\
-		VMLINUX_SYMBOL(__end_builtin_fw) = .;			\
-	}								\
-									\
 	TRACEDATA							\
 									\
 	/* Kernel symbol table: Normal symbols */			\
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 07/14] firmware: port built-in section to linker table
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, Michael Matz, Barry Song, mchehab,
	linux-arch, markus.heiser, xen-devel, msalter, linux-sh, mpe,
	joro, x86, fontana, dsahern, linux-arm-kernel, catalin.marinas,
	dvhart, dwmw2, linux, linux-xtensa, pali.rohar, Mike Frysinger,
	keescook, arnd

This ports built-in firmware to use linker tables,
this replaces the custom section solution with a
generic solution.

This also demos the use of the .rodata linker table.

Tested with 0 built-in firmware, 1 and 2 built-in
firmwares successfully.

v6: rename table macro as suggested by Andy Shevchenko

v5:

o since we dropped SECTION_ORDER_ANY, use 'any' order level explicitly

v4:

o work around c6x toolchain bug by using SECTION_TBL_RO

o fix compilation on blackfin

v3:
o explicitly include tables.h as we no longer include
  tables.h from sections.h

o use new section_tbl_asmtype() helper on firmware/Makefile
  to enable having to unfold things on our own.

v2: introduced this file in this version of the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/x86/kernel/cpu/microcode/core.c |  8 ++++----
 drivers/base/firmware_class.c        | 12 ++++++------
 firmware/Makefile                    |  3 ++-
 include/asm-generic/vmlinux.lds.h    |  7 -------
 4 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 2af69d27da62..2c5004343b45 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -31,6 +31,7 @@
 #include <linux/cpu.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/tables.h>
 
 #include <asm/microcode_intel.h>
 #include <asm/cpu_device_id.h>
@@ -110,15 +111,14 @@ static bool __init check_loader_disabled_bsp(void)
 	return *res;
 }
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DECLARE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 bool get_builtin_firmware(struct cpio_data *cd, const char *name)
 {
 #ifdef CONFIG_FW_LOADER
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	linktable_for_each(b_fw, builtin_fw) {
 		if (!strcmp(name, b_fw->name)) {
 			cd->size = b_fw->size;
 			cd->data = b_fw->data;
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 4497d263209f..b9ac348e8d33 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -31,6 +31,7 @@
 #include <linux/reboot.h>
 #include <linux/security.h>
 #include <linux/swait.h>
+#include <linux/tables.h>
 
 #include <generated/utsrelease.h>
 
@@ -44,15 +45,14 @@ MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_FW_LOADER
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DEFINE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 				    void *buf, size_t size)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	linktable_for_each(b_fw, builtin_fw) {
 		if (strcmp(name, b_fw->name) == 0) {
 			fw->size = b_fw->size;
 			fw->data = b_fw->data;
@@ -68,9 +68,9 @@ static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 
 static bool fw_is_builtin_firmware(const struct firmware *fw)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++)
+	linktable_for_each(b_fw, builtin_fw)
 		if (fw->data == b_fw->data)
 			return true;
 
diff --git a/firmware/Makefile b/firmware/Makefile
index fa3e81c2a97b..9c8cae144ede 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -155,6 +155,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  ASM_ALIGN=$(if $(CONFIG_64BIT),3,2);			     \
 		  PROGBITS=$(if $(CONFIG_ARM),%,@)progbits;		     \
 		  echo "/* Generated by firmware/Makefile */"		> $@;\
+		  echo "\#include <asm/tables.h>"			>>$@;\
 		  echo "    .section .rodata"				>>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_bin:"				>>$@;\
@@ -164,7 +165,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_name:"				>>$@;\
 		  echo "    .string \"$$FWNAME\""			>>$@;\
-		  echo "    .section .builtin_fw,\"a\",$${PROGBITS}"	>>$@;\
+		  echo "    set_section_tbl_type(SECTION_TBL_RO, builtin_fw, any, a,$${PROGBITS})" >>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_name"		>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_bin"		>>$@;\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index ce1e9a310ada..8a5325d75932 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -324,13 +324,6 @@
 		VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .;	\
 	}								\
 									\
-	/* Built-in firmware blobs */					\
-	.builtin_fw        : AT(ADDR(.builtin_fw) - LOAD_OFFSET) {	\
-		VMLINUX_SYMBOL(__start_builtin_fw) = .;			\
-		KEEP(*(.builtin_fw))					\
-		VMLINUX_SYMBOL(__end_builtin_fw) = .;			\
-	}								\
-									\
 	TRACEDATA							\
 									\
 	/* Kernel symbol table: Normal symbols */			\
-- 
2.11.0


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 07/14] firmware: port built-in section to linker table
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez, Barry Song, Mike Frysinger, Michael Matz,
	Fengguang Wu

This ports built-in firmware to use linker tables,
this replaces the custom section solution with a
generic solution.

This also demos the use of the .rodata linker table.

Tested with 0 built-in firmware, 1 and 2 built-in
firmwares successfully.

v6: rename table macro as suggested by Andy Shevchenko

v5:

o since we dropped SECTION_ORDER_ANY, use 'any' order level explicitly

v4:

o work around c6x toolchain bug by using SECTION_TBL_RO

o fix compilation on blackfin

v3:
o explicitly include tables.h as we no longer include
  tables.h from sections.h

o use new section_tbl_asmtype() helper on firmware/Makefile
  to enable having to unfold things on our own.

v2: introduced this file in this version of the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/x86/kernel/cpu/microcode/core.c |  8 ++++----
 drivers/base/firmware_class.c        | 12 ++++++------
 firmware/Makefile                    |  3 ++-
 include/asm-generic/vmlinux.lds.h    |  7 -------
 4 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 2af69d27da62..2c5004343b45 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -31,6 +31,7 @@
 #include <linux/cpu.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/tables.h>
 
 #include <asm/microcode_intel.h>
 #include <asm/cpu_device_id.h>
@@ -110,15 +111,14 @@ static bool __init check_loader_disabled_bsp(void)
 	return *res;
 }
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DECLARE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 bool get_builtin_firmware(struct cpio_data *cd, const char *name)
 {
 #ifdef CONFIG_FW_LOADER
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	linktable_for_each(b_fw, builtin_fw) {
 		if (!strcmp(name, b_fw->name)) {
 			cd->size = b_fw->size;
 			cd->data = b_fw->data;
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 4497d263209f..b9ac348e8d33 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -31,6 +31,7 @@
 #include <linux/reboot.h>
 #include <linux/security.h>
 #include <linux/swait.h>
+#include <linux/tables.h>
 
 #include <generated/utsrelease.h>
 
@@ -44,15 +45,14 @@ MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_FW_LOADER
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DEFINE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 				    void *buf, size_t size)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	linktable_for_each(b_fw, builtin_fw) {
 		if (strcmp(name, b_fw->name) == 0) {
 			fw->size = b_fw->size;
 			fw->data = b_fw->data;
@@ -68,9 +68,9 @@ static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 
 static bool fw_is_builtin_firmware(const struct firmware *fw)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++)
+	linktable_for_each(b_fw, builtin_fw)
 		if (fw->data == b_fw->data)
 			return true;
 
diff --git a/firmware/Makefile b/firmware/Makefile
index fa3e81c2a97b..9c8cae144ede 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -155,6 +155,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  ASM_ALIGN=$(if $(CONFIG_64BIT),3,2);			     \
 		  PROGBITS=$(if $(CONFIG_ARM),%,@)progbits;		     \
 		  echo "/* Generated by firmware/Makefile */"		> $@;\
+		  echo "\#include <asm/tables.h>"			>>$@;\
 		  echo "    .section .rodata"				>>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_bin:"				>>$@;\
@@ -164,7 +165,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_name:"				>>$@;\
 		  echo "    .string \"$$FWNAME\""			>>$@;\
-		  echo "    .section .builtin_fw,\"a\",$${PROGBITS}"	>>$@;\
+		  echo "    set_section_tbl_type(SECTION_TBL_RO, builtin_fw, any, a,$${PROGBITS})" >>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_name"		>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_bin"		>>$@;\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index ce1e9a310ada..8a5325d75932 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -324,13 +324,6 @@
 		VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .;	\
 	}								\
 									\
-	/* Built-in firmware blobs */					\
-	.builtin_fw        : AT(ADDR(.builtin_fw) - LOAD_OFFSET) {	\
-		VMLINUX_SYMBOL(__start_builtin_fw) = .;			\
-		KEEP(*(.builtin_fw))					\
-		VMLINUX_SYMBOL(__end_builtin_fw) = .;			\
-	}								\
-									\
 	TRACEDATA							\
 									\
 	/* Kernel symbol table: Normal symbols */			\
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 08/14] jump_label: move guard #endif down where it belongs
  2017-01-09 14:58       ` Luis R. Rodriguez
  (?)
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt

The ending header guard is misplaced. This has no
functional change, this is just an eye-sore.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/linux/jump_label.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index a0547c571800..b63d6b7b0db0 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -402,6 +402,6 @@ extern bool ____wrong_branch_error(void);
 #define static_branch_enable(x)		static_key_enable(&(x)->key)
 #define static_branch_disable(x)	static_key_disable(&(x)->key)
 
-#endif	/* _LINUX_JUMP_LABEL_H */
-
 #endif /* __ASSEMBLY__ */
+
+#endif	/* _LINUX_JUMP_LABEL_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 08/14] jump_label: move guard #endif down where it belongs
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt, ak

The ending header guard is misplaced. This has no
functional change, this is just an eye-sore.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/linux/jump_label.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index a0547c571800..b63d6b7b0db0 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -402,6 +402,6 @@ extern bool ____wrong_branch_error(void);
 #define static_branch_enable(x)		static_key_enable(&(x)->key)
 #define static_branch_disable(x)	static_key_disable(&(x)->key)
 
-#endif	/* _LINUX_JUMP_LABEL_H */
-
 #endif /* __ASSEMBLY__ */
+
+#endif	/* _LINUX_JUMP_LABEL_H */
-- 
2.11.0


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 08/14] jump_label: move guard #endif down where it belongs
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

The ending header guard is misplaced. This has no
functional change, this is just an eye-sore.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/linux/jump_label.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index a0547c571800..b63d6b7b0db0 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -402,6 +402,6 @@ extern bool ____wrong_branch_error(void);
 #define static_branch_enable(x)		static_key_enable(&(x)->key)
 #define static_branch_disable(x)	static_key_disable(&(x)->key)
 
-#endif	/* _LINUX_JUMP_LABEL_H */
-
 #endif /* __ASSEMBLY__ */
+
+#endif	/* _LINUX_JUMP_LABEL_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 09/14] jump_label: port __jump_table to linker tables
  2017-01-09 14:58       ` Luis R. Rodriguez
  (?)
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt

Move the __jump_table from the a custom section solution
to a generic solution, this avoiding extra vmlinux.lds.h
customizations.

This also demos the use of the .data linker table and of
the shared asm call push_section_tbl().

Built-in kernel functionality was tested with CONFIG_STATIC_KEYS_SELFTEST.
Moduler  kernel functionality was tested with CONFIG_TEST_STATIC_KEYS.
Both work as expected.

Since __jump_table sections are also supported per
module this also required expanding module-common.lds.S
to capture and fold all .data.tlb.__jump_table.* onto
the the section __jump_table -- in this case for modules
need to keep a reference in place, given the alternative
is to use DEFINE_LINKTABLE(struct jump_entry, __jump_table)
per module -- and later through macro hacks instantiate
the jump entries per module upon init. This is doable but
we'd loose out on the sorting of the table using the
linker, to sort we'd always still need to expand the
module common linker script. An alternative mechanism
is possible which would make these custom module sections
extensions dynamic without requiring manual changes, this
however is best done later through a separate evolution
once linker tables are in place.

A careful reviewer may note that some architectures use
"\n\t" to separate asm code, while others just use a new line.
Upon review last time it was deemed reasonable to for all
architectures to just use "\n", this is defined as ASM_CMD_SEP,
and if an architecture needs to override they can do so on their
architecture sections.h prior to including asm-generic/sections.h

v6: rename table macro as suggested by Andy Shevchenko

v5:

o Use ..tbl instead of .tbl as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

o Use LINKTABLE_START() and LINKTABLE_END()

o fixed tile jump label port -- tile got jump label support as of commit
  65a792e84f25d1 ("tile/jump_label: add jump label support for TILE-Gx"),
  as such we just needed to adjust the asm to account for the new
  linker table API use. This commit was merged as of v4.5-rc1.

v4:

o Some architectures allow linker scripts to follow including header
  files, some others do not, so if you need a helper on a linker script
  you need to explicitly include it. So for instance although
  scripts/module-common.lds.S includes <asm/tables.h> and this file
  includes <asm/section-core.h>, you still need to explicitly
  include it on the linker script. This issue is present on ARM.

o as per Josh Poimboeuf open code the section table name instead
  of including the kernel section headers, the simplicity and
  independence from the kernel is preferred.

v3:

o More elaborate tests performed
o first modular support use case, module tested was
  CONFIG_TEST_STATIC_KEYS (lib/test_static_keys.ko), this
  required us to extend module-common.lds.S
o use generic push_section_tbl_any() for all architectures
o Makes use of ASM_CMD_SEP to enable architectures to override later
  if needed
o guard tables.h inclusion and table definition with __KERNEL__

v2: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arm/include/asm/jump_label.h     |  6 ++++--
 arch/arm64/include/asm/jump_label.h   |  6 ++++--
 arch/mips/include/asm/jump_label.h    |  6 ++++--
 arch/powerpc/include/asm/jump_label.h |  8 +++++---
 arch/s390/include/asm/jump_label.h    |  6 ++++--
 arch/sparc/include/asm/jump_label.h   |  6 ++++--
 arch/tile/include/asm/jump_label.h    |  5 +++--
 arch/x86/include/asm/jump_label.h     | 10 ++++++----
 include/asm-generic/vmlinux.lds.h     |  5 -----
 include/linux/jump_label.h            |  4 ++--
 kernel/jump_label.c                   | 17 ++++++++++-------
 scripts/module-common.lds             |  1 +
 tools/objtool/special.c               |  2 +-
 13 files changed, 48 insertions(+), 34 deletions(-)

diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h
index 34f7b6980d21..609e0592a942 100644
--- a/arch/arm/include/asm/jump_label.h
+++ b/arch/arm/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_ARM_JUMP_LABEL_H
 #define _ASM_ARM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(nop) "\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
@@ -26,7 +28,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(b) " %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
diff --git a/arch/arm64/include/asm/jump_label.h b/arch/arm64/include/asm/jump_label.h
index 1b5e0e843c3a..bb56ac4fafb5 100644
--- a/arch/arm64/include/asm/jump_label.h
+++ b/arch/arm64/include/asm/jump_label.h
@@ -19,6 +19,8 @@
 #ifndef __ASM_JUMP_LABEL_H
 #define __ASM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -29,7 +31,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm goto("1: nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
@@ -43,7 +45,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm goto("1: b %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
diff --git a/arch/mips/include/asm/jump_label.h b/arch/mips/include/asm/jump_label.h
index e77672539e8e..07289a1b1bcd 100644
--- a/arch/mips/include/asm/jump_label.h
+++ b/arch/mips/include/asm/jump_label.h
@@ -8,6 +8,8 @@
 #ifndef _ASM_MIPS_JUMP_LABEL_H
 #define _ASM_MIPS_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -30,7 +32,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\t" NOP_INSN "\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -44,7 +46,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\tj %l[l_yes]\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
index 9a287e0ac8b1..7a75623740d0 100644
--- a/arch/powerpc/include/asm/jump_label.h
+++ b/arch/powerpc/include/asm/jump_label.h
@@ -10,6 +10,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
 
@@ -23,7 +25,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 "nop # arch_static_branch\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -37,7 +39,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes] # arch_static_branch_jump\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -62,7 +64,7 @@ struct jump_entry {
 #else
 #define ARCH_STATIC_BRANCH(LABEL, KEY)		\
 1098:	nop;					\
-	.pushsection __jump_table, "aw";	\
+	push_section_tbl_any(.data, __jump_table, aw); \
 	FTR_ENTRY_LONG 1098b, LABEL, KEY;	\
 	.popsection
 #endif
diff --git a/arch/s390/include/asm/jump_label.h b/arch/s390/include/asm/jump_label.h
index 9be198f5ee79..58e53af49e7e 100644
--- a/arch/s390/include/asm/jump_label.h
+++ b/arch/s390/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_S390_JUMP_LABEL_H
 #define _ASM_S390_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -16,7 +18,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 0,"__stringify(JUMP_LABEL_NOP_OFFSET)"\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
@@ -30,7 +32,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 15, %l[label]\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
diff --git a/arch/sparc/include/asm/jump_label.h b/arch/sparc/include/asm/jump_label.h
index 62d0354d1727..35d3e5d31821 100644
--- a/arch/sparc/include/asm/jump_label.h
+++ b/arch/sparc/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_SPARC_JUMP_LABEL_H
 #define _ASM_SPARC_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 	asm_volatile_goto("1:\n\t"
 		 "nop\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
@@ -28,7 +30,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes]\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
diff --git a/arch/tile/include/asm/jump_label.h b/arch/tile/include/asm/jump_label.h
index cde7573f397b..9bd989daad4a 100644
--- a/arch/tile/include/asm/jump_label.h
+++ b/arch/tile/include/asm/jump_label.h
@@ -16,6 +16,7 @@
 #define _ASM_TILE_JUMP_LABEL_H
 
 #include <arch/opcode.h>
+#include <asm/tables.h>
 
 #define JUMP_LABEL_NOP_SIZE	TILE_BUNDLE_SIZE_IN_BYTES
 
@@ -24,7 +25,7 @@ static __always_inline bool arch_static_branch(struct static_key *key,
 {
 	asm_volatile_goto("1:\n\t"
 		"nop" "\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".quad 1b, %l[l_yes], %0 + %1 \n\t"
 		".popsection\n\t"
 		: :  "i" (key), "i" (branch) : : l_yes);
@@ -38,7 +39,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key,
 {
 	asm_volatile_goto("1:\n\t"
 		"j %l[l_yes]" "\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".quad 1b, %l[l_yes], %0 + %1 \n\t"
 		".popsection\n\t"
 		: :  "i" (key), "i" (branch) : : l_yes);
diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h
index adc54c12cbd1..627df4752db0 100644
--- a/arch/x86/include/asm/jump_label.h
+++ b/arch/x86/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_JUMP_LABEL_H
 #define _ASM_X86_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef HAVE_JUMP_LABEL
 /*
  * For better or for worse, if jump labels (the gcc extension) are missing,
@@ -34,7 +36,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:"
 		".byte " __stringify(STATIC_KEY_INIT_NOP) "\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -50,7 +52,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:"
 		".byte 0xe9\n\t .long %l[l_yes] - 2f\n\t"
 		"2:\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -85,7 +87,7 @@ struct jump_entry {
 	.else
 	.byte		STATIC_KEY_INIT_NOP
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(.data, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key
 	.popsection
@@ -101,7 +103,7 @@ struct jump_entry {
 	.long		\target - .Lstatic_jump_after_\@
 .Lstatic_jump_after_\@:
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(.data, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key + 1
 	.popsection
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 8a5325d75932..887d844f0406 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -216,11 +216,6 @@
 	*(.data.unlikely)						\
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
-	/* implement dynamic printk debug */				\
-	. = ALIGN(8);                                                   \
-	VMLINUX_SYMBOL(__start___jump_table) = .;                       \
-	KEEP(*(__jump_table))                                           \
-	VMLINUX_SYMBOL(__stop___jump_table) = .;                        \
 	. = ALIGN(8);							\
 	VMLINUX_SYMBOL(__start___verbose) = .;                          \
 	KEEP(*(__verbose))                                              \
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index b63d6b7b0db0..e6277888b558 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -117,6 +117,7 @@ enum jump_label_type {
 struct module;
 
 #ifdef HAVE_JUMP_LABEL
+#include <linux/tables.h>
 
 #define JUMP_TYPE_FALSE	0UL
 #define JUMP_TYPE_TRUE	1UL
@@ -132,8 +133,7 @@ static __always_inline bool static_key_true(struct static_key *key)
 	return !arch_static_branch(key, true);
 }
 
-extern struct jump_entry __start___jump_table[];
-extern struct jump_entry __stop___jump_table[];
+DECLARE_LINKTABLE(struct jump_entry, __jump_table);
 
 extern void jump_label_init(void);
 extern void jump_label_lock(void);
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 93ad6c1fb9b6..4252f17eaeb5 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -15,9 +15,12 @@
 #include <linux/static_key.h>
 #include <linux/jump_label_ratelimit.h>
 #include <linux/bug.h>
+#include <linux/tables.h>
 
 #ifdef HAVE_JUMP_LABEL
 
+DEFINE_LINKTABLE(struct jump_entry, __jump_table);
+
 /* mutex to protect coming/going of the the jump_label table */
 static DEFINE_MUTEX(jump_label_mutex);
 
@@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
 
 void __init jump_label_init(void)
 {
-	struct jump_entry *iter_start = __start___jump_table;
-	struct jump_entry *iter_stop = __stop___jump_table;
 	struct static_key *key = NULL;
 	struct jump_entry *iter;
 
@@ -292,9 +293,10 @@ void __init jump_label_init(void)
 		return;
 
 	jump_label_lock();
-	jump_label_sort_entries(iter_start, iter_stop);
+	jump_label_sort_entries(LINKTABLE_START(__jump_table),
+				LINKTABLE_END(__jump_table));
 
-	for (iter = iter_start; iter < iter_stop; iter++) {
+	linktable_for_each(iter, __jump_table) {
 		struct static_key *iterk;
 
 		/* rewrite NOPs */
@@ -539,8 +541,9 @@ early_initcall(jump_label_init_module);
  */
 int jump_label_text_reserved(void *start, void *end)
 {
-	int ret = __jump_label_text_reserved(__start___jump_table,
-			__stop___jump_table, start, end);
+	int ret = __jump_label_text_reserved(LINKTABLE_START(__jump_table),
+					     LINKTABLE_END(__jump_table),
+					     start, end);
 
 	if (ret)
 		return ret;
@@ -553,7 +556,7 @@ int jump_label_text_reserved(void *start, void *end)
 
 static void jump_label_update(struct static_key *key)
 {
-	struct jump_entry *stop = __stop___jump_table;
+	struct jump_entry *stop = LINKTABLE_END(__jump_table);
 	struct jump_entry *entry = static_key_entries(key);
 #ifdef CONFIG_MODULES
 	struct module *mod;
diff --git a/scripts/module-common.lds b/scripts/module-common.lds
index 73a2c7da0e55..db0e724556c5 100644
--- a/scripts/module-common.lds
+++ b/scripts/module-common.lds
@@ -16,6 +16,7 @@ SECTIONS {
 	__kcrctab_unused	0 : { *(SORT(___kcrctab_unused+*)) }
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
+	__jump_table		0 : { *(SORT(.data..tbl.__jump_table.*)) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
diff --git a/tools/objtool/special.c b/tools/objtool/special.c
index bff8abb3a4aa..79968e118294 100644
--- a/tools/objtool/special.c
+++ b/tools/objtool/special.c
@@ -63,7 +63,7 @@ struct special_entry entries[] = {
 		.feature = ALT_FEATURE_OFFSET,
 	},
 	{
-		.sec = "__jump_table",
+		.sec = ".data..tbl.__jump_table.any",
 		.jump_or_nop = true,
 		.size = JUMP_ENTRY_SIZE,
 		.orig = JUMP_ORIG_OFFSET,
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 09/14] jump_label: port __jump_table to linker tables
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt, ak

Move the __jump_table from the a custom section solution
to a generic solution, this avoiding extra vmlinux.lds.h
customizations.

This also demos the use of the .data linker table and of
the shared asm call push_section_tbl().

Built-in kernel functionality was tested with CONFIG_STATIC_KEYS_SELFTEST.
Moduler  kernel functionality was tested with CONFIG_TEST_STATIC_KEYS.
Both work as expected.

Since __jump_table sections are also supported per
module this also required expanding module-common.lds.S
to capture and fold all .data.tlb.__jump_table.* onto
the the section __jump_table -- in this case for modules
need to keep a reference in place, given the alternative
is to use DEFINE_LINKTABLE(struct jump_entry, __jump_table)
per module -- and later through macro hacks instantiate
the jump entries per module upon init. This is doable but
we'd loose out on the sorting of the table using the
linker, to sort we'd always still need to expand the
module common linker script. An alternative mechanism
is possible which would make these custom module sections
extensions dynamic without requiring manual changes, this
however is best done later through a separate evolution
once linker tables are in place.

A careful reviewer may note that some architectures use
"\n\t" to separate asm code, while others just use a new line.
Upon review last time it was deemed reasonable to for all
architectures to just use "\n", this is defined as ASM_CMD_SEP,
and if an architecture needs to override they can do so on their
architecture sections.h prior to including asm-generic/sections.h

v6: rename table macro as suggested by Andy Shevchenko

v5:

o Use ..tbl instead of .tbl as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

o Use LINKTABLE_START() and LINKTABLE_END()

o fixed tile jump label port -- tile got jump label support as of commit
  65a792e84f25d1 ("tile/jump_label: add jump label support for TILE-Gx"),
  as such we just needed to adjust the asm to account for the new
  linker table API use. This commit was merged as of v4.5-rc1.

v4:

o Some architectures allow linker scripts to follow including header
  files, some others do not, so if you need a helper on a linker script
  you need to explicitly include it. So for instance although
  scripts/module-common.lds.S includes <asm/tables.h> and this file
  includes <asm/section-core.h>, you still need to explicitly
  include it on the linker script. This issue is present on ARM.

o as per Josh Poimboeuf open code the section table name instead
  of including the kernel section headers, the simplicity and
  independence from the kernel is preferred.

v3:

o More elaborate tests performed
o first modular support use case, module tested was
  CONFIG_TEST_STATIC_KEYS (lib/test_static_keys.ko), this
  required us to extend module-common.lds.S
o use generic push_section_tbl_any() for all architectures
o Makes use of ASM_CMD_SEP to enable architectures to override later
  if needed
o guard tables.h inclusion and table definition with __KERNEL__

v2: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arm/include/asm/jump_label.h     |  6 ++++--
 arch/arm64/include/asm/jump_label.h   |  6 ++++--
 arch/mips/include/asm/jump_label.h    |  6 ++++--
 arch/powerpc/include/asm/jump_label.h |  8 +++++---
 arch/s390/include/asm/jump_label.h    |  6 ++++--
 arch/sparc/include/asm/jump_label.h   |  6 ++++--
 arch/tile/include/asm/jump_label.h    |  5 +++--
 arch/x86/include/asm/jump_label.h     | 10 ++++++----
 include/asm-generic/vmlinux.lds.h     |  5 -----
 include/linux/jump_label.h            |  4 ++--
 kernel/jump_label.c                   | 17 ++++++++++-------
 scripts/module-common.lds             |  1 +
 tools/objtool/special.c               |  2 +-
 13 files changed, 48 insertions(+), 34 deletions(-)

diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h
index 34f7b6980d21..609e0592a942 100644
--- a/arch/arm/include/asm/jump_label.h
+++ b/arch/arm/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_ARM_JUMP_LABEL_H
 #define _ASM_ARM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(nop) "\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
@@ -26,7 +28,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(b) " %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
diff --git a/arch/arm64/include/asm/jump_label.h b/arch/arm64/include/asm/jump_label.h
index 1b5e0e843c3a..bb56ac4fafb5 100644
--- a/arch/arm64/include/asm/jump_label.h
+++ b/arch/arm64/include/asm/jump_label.h
@@ -19,6 +19,8 @@
 #ifndef __ASM_JUMP_LABEL_H
 #define __ASM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -29,7 +31,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm goto("1: nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
@@ -43,7 +45,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm goto("1: b %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
diff --git a/arch/mips/include/asm/jump_label.h b/arch/mips/include/asm/jump_label.h
index e77672539e8e..07289a1b1bcd 100644
--- a/arch/mips/include/asm/jump_label.h
+++ b/arch/mips/include/asm/jump_label.h
@@ -8,6 +8,8 @@
 #ifndef _ASM_MIPS_JUMP_LABEL_H
 #define _ASM_MIPS_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -30,7 +32,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\t" NOP_INSN "\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -44,7 +46,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\tj %l[l_yes]\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
index 9a287e0ac8b1..7a75623740d0 100644
--- a/arch/powerpc/include/asm/jump_label.h
+++ b/arch/powerpc/include/asm/jump_label.h
@@ -10,6 +10,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
 
@@ -23,7 +25,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 "nop # arch_static_branch\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -37,7 +39,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes] # arch_static_branch_jump\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -62,7 +64,7 @@ struct jump_entry {
 #else
 #define ARCH_STATIC_BRANCH(LABEL, KEY)		\
 1098:	nop;					\
-	.pushsection __jump_table, "aw";	\
+	push_section_tbl_any(.data, __jump_table, aw); \
 	FTR_ENTRY_LONG 1098b, LABEL, KEY;	\
 	.popsection
 #endif
diff --git a/arch/s390/include/asm/jump_label.h b/arch/s390/include/asm/jump_label.h
index 9be198f5ee79..58e53af49e7e 100644
--- a/arch/s390/include/asm/jump_label.h
+++ b/arch/s390/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_S390_JUMP_LABEL_H
 #define _ASM_S390_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -16,7 +18,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 0,"__stringify(JUMP_LABEL_NOP_OFFSET)"\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
@@ -30,7 +32,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 15, %l[label]\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
diff --git a/arch/sparc/include/asm/jump_label.h b/arch/sparc/include/asm/jump_label.h
index 62d0354d1727..35d3e5d31821 100644
--- a/arch/sparc/include/asm/jump_label.h
+++ b/arch/sparc/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_SPARC_JUMP_LABEL_H
 #define _ASM_SPARC_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 	asm_volatile_goto("1:\n\t"
 		 "nop\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
@@ -28,7 +30,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes]\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
diff --git a/arch/tile/include/asm/jump_label.h b/arch/tile/include/asm/jump_label.h
index cde7573f397b..9bd989daad4a 100644
--- a/arch/tile/include/asm/jump_label.h
+++ b/arch/tile/include/asm/jump_label.h
@@ -16,6 +16,7 @@
 #define _ASM_TILE_JUMP_LABEL_H
 
 #include <arch/opcode.h>
+#include <asm/tables.h>
 
 #define JUMP_LABEL_NOP_SIZE	TILE_BUNDLE_SIZE_IN_BYTES
 
@@ -24,7 +25,7 @@ static __always_inline bool arch_static_branch(struct static_key *key,
 {
 	asm_volatile_goto("1:\n\t"
 		"nop" "\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".quad 1b, %l[l_yes], %0 + %1 \n\t"
 		".popsection\n\t"
 		: :  "i" (key), "i" (branch) : : l_yes);
@@ -38,7 +39,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key,
 {
 	asm_volatile_goto("1:\n\t"
 		"j %l[l_yes]" "\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".quad 1b, %l[l_yes], %0 + %1 \n\t"
 		".popsection\n\t"
 		: :  "i" (key), "i" (branch) : : l_yes);
diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h
index adc54c12cbd1..627df4752db0 100644
--- a/arch/x86/include/asm/jump_label.h
+++ b/arch/x86/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_JUMP_LABEL_H
 #define _ASM_X86_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef HAVE_JUMP_LABEL
 /*
  * For better or for worse, if jump labels (the gcc extension) are missing,
@@ -34,7 +36,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:"
 		".byte " __stringify(STATIC_KEY_INIT_NOP) "\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -50,7 +52,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:"
 		".byte 0xe9\n\t .long %l[l_yes] - 2f\n\t"
 		"2:\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -85,7 +87,7 @@ struct jump_entry {
 	.else
 	.byte		STATIC_KEY_INIT_NOP
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(.data, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key
 	.popsection
@@ -101,7 +103,7 @@ struct jump_entry {
 	.long		\target - .Lstatic_jump_after_\@
 .Lstatic_jump_after_\@:
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(.data, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key + 1
 	.popsection
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 8a5325d75932..887d844f0406 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -216,11 +216,6 @@
 	*(.data.unlikely)						\
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
-	/* implement dynamic printk debug */				\
-	. = ALIGN(8);                                                   \
-	VMLINUX_SYMBOL(__start___jump_table) = .;                       \
-	KEEP(*(__jump_table))                                           \
-	VMLINUX_SYMBOL(__stop___jump_table) = .;                        \
 	. = ALIGN(8);							\
 	VMLINUX_SYMBOL(__start___verbose) = .;                          \
 	KEEP(*(__verbose))                                              \
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index b63d6b7b0db0..e6277888b558 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -117,6 +117,7 @@ enum jump_label_type {
 struct module;
 
 #ifdef HAVE_JUMP_LABEL
+#include <linux/tables.h>
 
 #define JUMP_TYPE_FALSE	0UL
 #define JUMP_TYPE_TRUE	1UL
@@ -132,8 +133,7 @@ static __always_inline bool static_key_true(struct static_key *key)
 	return !arch_static_branch(key, true);
 }
 
-extern struct jump_entry __start___jump_table[];
-extern struct jump_entry __stop___jump_table[];
+DECLARE_LINKTABLE(struct jump_entry, __jump_table);
 
 extern void jump_label_init(void);
 extern void jump_label_lock(void);
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 93ad6c1fb9b6..4252f17eaeb5 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -15,9 +15,12 @@
 #include <linux/static_key.h>
 #include <linux/jump_label_ratelimit.h>
 #include <linux/bug.h>
+#include <linux/tables.h>
 
 #ifdef HAVE_JUMP_LABEL
 
+DEFINE_LINKTABLE(struct jump_entry, __jump_table);
+
 /* mutex to protect coming/going of the the jump_label table */
 static DEFINE_MUTEX(jump_label_mutex);
 
@@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
 
 void __init jump_label_init(void)
 {
-	struct jump_entry *iter_start = __start___jump_table;
-	struct jump_entry *iter_stop = __stop___jump_table;
 	struct static_key *key = NULL;
 	struct jump_entry *iter;
 
@@ -292,9 +293,10 @@ void __init jump_label_init(void)
 		return;
 
 	jump_label_lock();
-	jump_label_sort_entries(iter_start, iter_stop);
+	jump_label_sort_entries(LINKTABLE_START(__jump_table),
+				LINKTABLE_END(__jump_table));
 
-	for (iter = iter_start; iter < iter_stop; iter++) {
+	linktable_for_each(iter, __jump_table) {
 		struct static_key *iterk;
 
 		/* rewrite NOPs */
@@ -539,8 +541,9 @@ early_initcall(jump_label_init_module);
  */
 int jump_label_text_reserved(void *start, void *end)
 {
-	int ret = __jump_label_text_reserved(__start___jump_table,
-			__stop___jump_table, start, end);
+	int ret = __jump_label_text_reserved(LINKTABLE_START(__jump_table),
+					     LINKTABLE_END(__jump_table),
+					     start, end);
 
 	if (ret)
 		return ret;
@@ -553,7 +556,7 @@ int jump_label_text_reserved(void *start, void *end)
 
 static void jump_label_update(struct static_key *key)
 {
-	struct jump_entry *stop = __stop___jump_table;
+	struct jump_entry *stop = LINKTABLE_END(__jump_table);
 	struct jump_entry *entry = static_key_entries(key);
 #ifdef CONFIG_MODULES
 	struct module *mod;
diff --git a/scripts/module-common.lds b/scripts/module-common.lds
index 73a2c7da0e55..db0e724556c5 100644
--- a/scripts/module-common.lds
+++ b/scripts/module-common.lds
@@ -16,6 +16,7 @@ SECTIONS {
 	__kcrctab_unused	0 : { *(SORT(___kcrctab_unused+*)) }
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
+	__jump_table		0 : { *(SORT(.data..tbl.__jump_table.*)) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
diff --git a/tools/objtool/special.c b/tools/objtool/special.c
index bff8abb3a4aa..79968e118294 100644
--- a/tools/objtool/special.c
+++ b/tools/objtool/special.c
@@ -63,7 +63,7 @@ struct special_entry entries[] = {
 		.feature = ALT_FEATURE_OFFSET,
 	},
 	{
-		.sec = "__jump_table",
+		.sec = ".data..tbl.__jump_table.any",
 		.jump_or_nop = true,
 		.size = JUMP_ENTRY_SIZE,
 		.orig = JUMP_ORIG_OFFSET,
-- 
2.11.0


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 09/14] jump_label: port __jump_table to linker tables
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

Move the __jump_table from the a custom section solution
to a generic solution, this avoiding extra vmlinux.lds.h
customizations.

This also demos the use of the .data linker table and of
the shared asm call push_section_tbl().

Built-in kernel functionality was tested with CONFIG_STATIC_KEYS_SELFTEST.
Moduler  kernel functionality was tested with CONFIG_TEST_STATIC_KEYS.
Both work as expected.

Since __jump_table sections are also supported per
module this also required expanding module-common.lds.S
to capture and fold all .data.tlb.__jump_table.* onto
the the section __jump_table -- in this case for modules
need to keep a reference in place, given the alternative
is to use DEFINE_LINKTABLE(struct jump_entry, __jump_table)
per module -- and later through macro hacks instantiate
the jump entries per module upon init. This is doable but
we'd loose out on the sorting of the table using the
linker, to sort we'd always still need to expand the
module common linker script. An alternative mechanism
is possible which would make these custom module sections
extensions dynamic without requiring manual changes, this
however is best done later through a separate evolution
once linker tables are in place.

A careful reviewer may note that some architectures use
"\n\t" to separate asm code, while others just use a new line.
Upon review last time it was deemed reasonable to for all
architectures to just use "\n", this is defined as ASM_CMD_SEP,
and if an architecture needs to override they can do so on their
architecture sections.h prior to including asm-generic/sections.h

v6: rename table macro as suggested by Andy Shevchenko

v5:

o Use ..tbl instead of .tbl as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

o Use LINKTABLE_START() and LINKTABLE_END()

o fixed tile jump label port -- tile got jump label support as of commit
  65a792e84f25d1 ("tile/jump_label: add jump label support for TILE-Gx"),
  as such we just needed to adjust the asm to account for the new
  linker table API use. This commit was merged as of v4.5-rc1.

v4:

o Some architectures allow linker scripts to follow including header
  files, some others do not, so if you need a helper on a linker script
  you need to explicitly include it. So for instance although
  scripts/module-common.lds.S includes <asm/tables.h> and this file
  includes <asm/section-core.h>, you still need to explicitly
  include it on the linker script. This issue is present on ARM.

o as per Josh Poimboeuf open code the section table name instead
  of including the kernel section headers, the simplicity and
  independence from the kernel is preferred.

v3:

o More elaborate tests performed
o first modular support use case, module tested was
  CONFIG_TEST_STATIC_KEYS (lib/test_static_keys.ko), this
  required us to extend module-common.lds.S
o use generic push_section_tbl_any() for all architectures
o Makes use of ASM_CMD_SEP to enable architectures to override later
  if needed
o guard tables.h inclusion and table definition with __KERNEL__

v2: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arm/include/asm/jump_label.h     |  6 ++++--
 arch/arm64/include/asm/jump_label.h   |  6 ++++--
 arch/mips/include/asm/jump_label.h    |  6 ++++--
 arch/powerpc/include/asm/jump_label.h |  8 +++++---
 arch/s390/include/asm/jump_label.h    |  6 ++++--
 arch/sparc/include/asm/jump_label.h   |  6 ++++--
 arch/tile/include/asm/jump_label.h    |  5 +++--
 arch/x86/include/asm/jump_label.h     | 10 ++++++----
 include/asm-generic/vmlinux.lds.h     |  5 -----
 include/linux/jump_label.h            |  4 ++--
 kernel/jump_label.c                   | 17 ++++++++++-------
 scripts/module-common.lds             |  1 +
 tools/objtool/special.c               |  2 +-
 13 files changed, 48 insertions(+), 34 deletions(-)

diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h
index 34f7b6980d21..609e0592a942 100644
--- a/arch/arm/include/asm/jump_label.h
+++ b/arch/arm/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_ARM_JUMP_LABEL_H
 #define _ASM_ARM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(nop) "\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
@@ -26,7 +28,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(b) " %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
diff --git a/arch/arm64/include/asm/jump_label.h b/arch/arm64/include/asm/jump_label.h
index 1b5e0e843c3a..bb56ac4fafb5 100644
--- a/arch/arm64/include/asm/jump_label.h
+++ b/arch/arm64/include/asm/jump_label.h
@@ -19,6 +19,8 @@
 #ifndef __ASM_JUMP_LABEL_H
 #define __ASM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -29,7 +31,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm goto("1: nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
@@ -43,7 +45,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm goto("1: b %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
diff --git a/arch/mips/include/asm/jump_label.h b/arch/mips/include/asm/jump_label.h
index e77672539e8e..07289a1b1bcd 100644
--- a/arch/mips/include/asm/jump_label.h
+++ b/arch/mips/include/asm/jump_label.h
@@ -8,6 +8,8 @@
 #ifndef _ASM_MIPS_JUMP_LABEL_H
 #define _ASM_MIPS_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -30,7 +32,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\t" NOP_INSN "\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -44,7 +46,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\tj %l[l_yes]\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
index 9a287e0ac8b1..7a75623740d0 100644
--- a/arch/powerpc/include/asm/jump_label.h
+++ b/arch/powerpc/include/asm/jump_label.h
@@ -10,6 +10,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
 
@@ -23,7 +25,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 "nop # arch_static_branch\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -37,7 +39,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes] # arch_static_branch_jump\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -62,7 +64,7 @@ struct jump_entry {
 #else
 #define ARCH_STATIC_BRANCH(LABEL, KEY)		\
 1098:	nop;					\
-	.pushsection __jump_table, "aw";	\
+	push_section_tbl_any(.data, __jump_table, aw); \
 	FTR_ENTRY_LONG 1098b, LABEL, KEY;	\
 	.popsection
 #endif
diff --git a/arch/s390/include/asm/jump_label.h b/arch/s390/include/asm/jump_label.h
index 9be198f5ee79..58e53af49e7e 100644
--- a/arch/s390/include/asm/jump_label.h
+++ b/arch/s390/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_S390_JUMP_LABEL_H
 #define _ASM_S390_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -16,7 +18,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 0,"__stringify(JUMP_LABEL_NOP_OFFSET)"\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
@@ -30,7 +32,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 15, %l[label]\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
diff --git a/arch/sparc/include/asm/jump_label.h b/arch/sparc/include/asm/jump_label.h
index 62d0354d1727..35d3e5d31821 100644
--- a/arch/sparc/include/asm/jump_label.h
+++ b/arch/sparc/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_SPARC_JUMP_LABEL_H
 #define _ASM_SPARC_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 	asm_volatile_goto("1:\n\t"
 		 "nop\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
@@ -28,7 +30,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes]\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
diff --git a/arch/tile/include/asm/jump_label.h b/arch/tile/include/asm/jump_label.h
index cde7573f397b..9bd989daad4a 100644
--- a/arch/tile/include/asm/jump_label.h
+++ b/arch/tile/include/asm/jump_label.h
@@ -16,6 +16,7 @@
 #define _ASM_TILE_JUMP_LABEL_H
 
 #include <arch/opcode.h>
+#include <asm/tables.h>
 
 #define JUMP_LABEL_NOP_SIZE	TILE_BUNDLE_SIZE_IN_BYTES
 
@@ -24,7 +25,7 @@ static __always_inline bool arch_static_branch(struct static_key *key,
 {
 	asm_volatile_goto("1:\n\t"
 		"nop" "\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".quad 1b, %l[l_yes], %0 + %1 \n\t"
 		".popsection\n\t"
 		: :  "i" (key), "i" (branch) : : l_yes);
@@ -38,7 +39,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key,
 {
 	asm_volatile_goto("1:\n\t"
 		"j %l[l_yes]" "\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".quad 1b, %l[l_yes], %0 + %1 \n\t"
 		".popsection\n\t"
 		: :  "i" (key), "i" (branch) : : l_yes);
diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h
index adc54c12cbd1..627df4752db0 100644
--- a/arch/x86/include/asm/jump_label.h
+++ b/arch/x86/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_JUMP_LABEL_H
 #define _ASM_X86_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef HAVE_JUMP_LABEL
 /*
  * For better or for worse, if jump labels (the gcc extension) are missing,
@@ -34,7 +36,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:"
 		".byte " __stringify(STATIC_KEY_INIT_NOP) "\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -50,7 +52,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:"
 		".byte 0xe9\n\t .long %l[l_yes] - 2f\n\t"
 		"2:\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -85,7 +87,7 @@ struct jump_entry {
 	.else
 	.byte		STATIC_KEY_INIT_NOP
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(.data, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key
 	.popsection
@@ -101,7 +103,7 @@ struct jump_entry {
 	.long		\target - .Lstatic_jump_after_\@
 .Lstatic_jump_after_\@:
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(.data, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key + 1
 	.popsection
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 8a5325d75932..887d844f0406 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -216,11 +216,6 @@
 	*(.data.unlikely)						\
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
-	/* implement dynamic printk debug */				\
-	. = ALIGN(8);                                                   \
-	VMLINUX_SYMBOL(__start___jump_table) = .;                       \
-	KEEP(*(__jump_table))                                           \
-	VMLINUX_SYMBOL(__stop___jump_table) = .;                        \
 	. = ALIGN(8);							\
 	VMLINUX_SYMBOL(__start___verbose) = .;                          \
 	KEEP(*(__verbose))                                              \
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index b63d6b7b0db0..e6277888b558 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -117,6 +117,7 @@ enum jump_label_type {
 struct module;
 
 #ifdef HAVE_JUMP_LABEL
+#include <linux/tables.h>
 
 #define JUMP_TYPE_FALSE	0UL
 #define JUMP_TYPE_TRUE	1UL
@@ -132,8 +133,7 @@ static __always_inline bool static_key_true(struct static_key *key)
 	return !arch_static_branch(key, true);
 }
 
-extern struct jump_entry __start___jump_table[];
-extern struct jump_entry __stop___jump_table[];
+DECLARE_LINKTABLE(struct jump_entry, __jump_table);
 
 extern void jump_label_init(void);
 extern void jump_label_lock(void);
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 93ad6c1fb9b6..4252f17eaeb5 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -15,9 +15,12 @@
 #include <linux/static_key.h>
 #include <linux/jump_label_ratelimit.h>
 #include <linux/bug.h>
+#include <linux/tables.h>
 
 #ifdef HAVE_JUMP_LABEL
 
+DEFINE_LINKTABLE(struct jump_entry, __jump_table);
+
 /* mutex to protect coming/going of the the jump_label table */
 static DEFINE_MUTEX(jump_label_mutex);
 
@@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
 
 void __init jump_label_init(void)
 {
-	struct jump_entry *iter_start = __start___jump_table;
-	struct jump_entry *iter_stop = __stop___jump_table;
 	struct static_key *key = NULL;
 	struct jump_entry *iter;
 
@@ -292,9 +293,10 @@ void __init jump_label_init(void)
 		return;
 
 	jump_label_lock();
-	jump_label_sort_entries(iter_start, iter_stop);
+	jump_label_sort_entries(LINKTABLE_START(__jump_table),
+				LINKTABLE_END(__jump_table));
 
-	for (iter = iter_start; iter < iter_stop; iter++) {
+	linktable_for_each(iter, __jump_table) {
 		struct static_key *iterk;
 
 		/* rewrite NOPs */
@@ -539,8 +541,9 @@ early_initcall(jump_label_init_module);
  */
 int jump_label_text_reserved(void *start, void *end)
 {
-	int ret = __jump_label_text_reserved(__start___jump_table,
-			__stop___jump_table, start, end);
+	int ret = __jump_label_text_reserved(LINKTABLE_START(__jump_table),
+					     LINKTABLE_END(__jump_table),
+					     start, end);
 
 	if (ret)
 		return ret;
@@ -553,7 +556,7 @@ int jump_label_text_reserved(void *start, void *end)
 
 static void jump_label_update(struct static_key *key)
 {
-	struct jump_entry *stop = __stop___jump_table;
+	struct jump_entry *stop = LINKTABLE_END(__jump_table);
 	struct jump_entry *entry = static_key_entries(key);
 #ifdef CONFIG_MODULES
 	struct module *mod;
diff --git a/scripts/module-common.lds b/scripts/module-common.lds
index 73a2c7da0e55..db0e724556c5 100644
--- a/scripts/module-common.lds
+++ b/scripts/module-common.lds
@@ -16,6 +16,7 @@ SECTIONS {
 	__kcrctab_unused	0 : { *(SORT(___kcrctab_unused+*)) }
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
+	__jump_table		0 : { *(SORT(.data..tbl.__jump_table.*)) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
diff --git a/tools/objtool/special.c b/tools/objtool/special.c
index bff8abb3a4aa..79968e118294 100644
--- a/tools/objtool/special.c
+++ b/tools/objtool/special.c
@@ -63,7 +63,7 @@ struct special_entry entries[] = {
 		.feature = ALT_FEATURE_OFFSET,
 	},
 	{
-		.sec = "__jump_table",
+		.sec = ".data..tbl.__jump_table.any",
 		.jump_or_nop = true,
 		.size = JUMP_ENTRY_SIZE,
 		.orig = JUMP_ORIG_OFFSET,
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 10/14] dynamic_debug: port to use linker tables
  2017-01-09 14:58       ` Luis R. Rodriguez
  (?)
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, Michael Matz, Barry Song, mchehab,
	linux-arch, markus.heiser, xen-devel, msalter, linux-sh, mpe,
	joro, x86, fontana, dsahern, linux-arm-kernel, catalin.marinas,
	dvhart, dwmw2, linux, linux-xtensa, pali.rohar, Mike Frysinger,
	keescook

This removes the custom vmlinux.lds.h hacks and uses
the generalized solution for .data entries.

There is much more potential for further fine tuning here
in the future though. For instance, linker tables enable
an extra postfix for order level annotations, this could
easily be used as the KBUILD_MODNAME and with a bit of
linker table changes we may be able to get a direct O(1)
count of the entries for that KBUILD_MODNAME: it would
just be a count on the number of entries for the given
order level. This should help make dynamic_debug_init()
cleaner and also reduce the amount of time it takes at
boot time. Instead of iterating over each print until we
have all for a KBUILD_MODNAME, we'd instead directly
operate on each KBUILD_MODNAME directly. We can work on
this later to make this change easier to review.

Tested dynamic debug with dyndbg query and debugfs control
and it works as expected, for both built-in code and modules.

v6: rename table macro as suggested by Andy Shevchenko

v5:

o Use ..tbl instead of .tbl as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names,
  use LINKTABLE_EMPTY(), LINKTABLE_START()

v4: fix compilation on blackfin
v3: added modular support
v2: introduced this patch into the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/asm-generic/vmlinux.lds.h |  4 ----
 include/linux/dynamic_debug.h     |  5 +++--
 lib/dynamic_debug.c               | 13 ++++++-------
 scripts/module-common.lds         |  1 +
 4 files changed, 10 insertions(+), 13 deletions(-)

diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 887d844f0406..37b99537d5a9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -216,10 +216,6 @@
 	*(.data.unlikely)						\
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
-	. = ALIGN(8);							\
-	VMLINUX_SYMBOL(__start___verbose) = .;                          \
-	KEEP(*(__verbose))                                              \
-	VMLINUX_SYMBOL(__stop___verbose) = .;				\
 	LIKELY_PROFILE()		       				\
 	BRANCH_PROFILE()						\
 	TRACE_PRINTKS()							\
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 546d68057e3b..a52618a77b09 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -4,6 +4,7 @@
 #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
 #include <linux/jump_label.h>
 #endif
+#include <linux/tables.h>
 
 /*
  * An instance of this structure is created in a special
@@ -50,6 +51,7 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
 				const char *modname);
 
 #if defined(CONFIG_DYNAMIC_DEBUG)
+DECLARE_LINKTABLE(struct _ddebug, __verbose);
 extern int ddebug_remove_module(const char *mod_name);
 extern __printf(2, 3)
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
@@ -71,8 +73,7 @@ void __dynamic_netdev_dbg(struct _ddebug *descriptor,
 			  const char *fmt, ...);
 
 #define DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, key, init)	\
-	static struct _ddebug  __aligned(8)			\
-	__attribute__((section("__verbose"))) name = {		\
+	static LINKTABLE(__verbose, SECTION_ORDER_ANY) name = {	\
 		.modname = KBUILD_MODNAME,			\
 		.function = __func__,				\
 		.filename = __FILE__,				\
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index da796e2dc4f5..27a335e3b1f3 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -37,8 +37,7 @@
 #include <linux/device.h>
 #include <linux/netdevice.h>
 
-extern struct _ddebug __start___verbose[];
-extern struct _ddebug __stop___verbose[];
+DEFINE_LINKTABLE(struct _ddebug, __verbose);
 
 struct ddebug_table {
 	struct list_head link;
@@ -978,14 +977,14 @@ static int __init dynamic_debug_init(void)
 	int n = 0, entries = 0, modct = 0;
 	int verbose_bytes = 0;
 
-	if (__start___verbose = __stop___verbose) {
-		pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
+	if (LINKTABLE_EMPTY(__verbose)) {
+		pr_warn("dynamic debug linker table empty on CONFIG_DYNAMIC_DEBUG build\n");
 		return 1;
 	}
-	iter = __start___verbose;
+	iter = LINKTABLE_START(__verbose);
 	modname = iter->modname;
 	iter_start = iter;
-	for (; iter < __stop___verbose; iter++) {
+	linktable_for_each(iter, __verbose) {
 		entries++;
 		verbose_bytes += strlen(iter->modname) + strlen(iter->function)
 			+ strlen(iter->filename) + strlen(iter->format);
@@ -1008,7 +1007,7 @@ static int __init dynamic_debug_init(void)
 	ddebug_init_success = 1;
 	vpr_info("%d modules, %d entries and %d bytes in ddebug tables, %d bytes in (readonly) verbose section\n",
 		 modct, entries, (int)(modct * sizeof(struct ddebug_table)),
-		 verbose_bytes + (int)(__stop___verbose - __start___verbose));
+		 verbose_bytes + (int)(LINKTABLE_SIZE(__verbose)));
 
 	/* apply ddebug_query boot param, dont unload tables on err */
 	if (ddebug_setup_string[0] != '\0') {
diff --git a/scripts/module-common.lds b/scripts/module-common.lds
index db0e724556c5..25755d458f09 100644
--- a/scripts/module-common.lds
+++ b/scripts/module-common.lds
@@ -17,6 +17,7 @@ SECTIONS {
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
 	__jump_table		0 : { *(SORT(.data..tbl.__jump_table.*)) }
+	__verbose		0 : { *(SORT(.data..tbl.__verbose.*)) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 10/14] dynamic_debug: port to use linker tables
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, Michael Matz, Barry Song, mchehab,
	linux-arch, markus.heiser, xen-devel, msalter, linux-sh, mpe,
	joro, x86, fontana, dsahern, linux-arm-kernel, catalin.marinas,
	dvhart, dwmw2, linux, linux-xtensa, pali.rohar, Mike Frysinger,
	keescook, arnd

This removes the custom vmlinux.lds.h hacks and uses
the generalized solution for .data entries.

There is much more potential for further fine tuning here
in the future though. For instance, linker tables enable
an extra postfix for order level annotations, this could
easily be used as the KBUILD_MODNAME and with a bit of
linker table changes we may be able to get a direct O(1)
count of the entries for that KBUILD_MODNAME: it would
just be a count on the number of entries for the given
order level. This should help make dynamic_debug_init()
cleaner and also reduce the amount of time it takes at
boot time. Instead of iterating over each print until we
have all for a KBUILD_MODNAME, we'd instead directly
operate on each KBUILD_MODNAME directly. We can work on
this later to make this change easier to review.

Tested dynamic debug with dyndbg query and debugfs control
and it works as expected, for both built-in code and modules.

v6: rename table macro as suggested by Andy Shevchenko

v5:

o Use ..tbl instead of .tbl as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names,
  use LINKTABLE_EMPTY(), LINKTABLE_START()

v4: fix compilation on blackfin
v3: added modular support
v2: introduced this patch into the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/asm-generic/vmlinux.lds.h |  4 ----
 include/linux/dynamic_debug.h     |  5 +++--
 lib/dynamic_debug.c               | 13 ++++++-------
 scripts/module-common.lds         |  1 +
 4 files changed, 10 insertions(+), 13 deletions(-)

diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 887d844f0406..37b99537d5a9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -216,10 +216,6 @@
 	*(.data.unlikely)						\
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
-	. = ALIGN(8);							\
-	VMLINUX_SYMBOL(__start___verbose) = .;                          \
-	KEEP(*(__verbose))                                              \
-	VMLINUX_SYMBOL(__stop___verbose) = .;				\
 	LIKELY_PROFILE()		       				\
 	BRANCH_PROFILE()						\
 	TRACE_PRINTKS()							\
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 546d68057e3b..a52618a77b09 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -4,6 +4,7 @@
 #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
 #include <linux/jump_label.h>
 #endif
+#include <linux/tables.h>
 
 /*
  * An instance of this structure is created in a special
@@ -50,6 +51,7 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
 				const char *modname);
 
 #if defined(CONFIG_DYNAMIC_DEBUG)
+DECLARE_LINKTABLE(struct _ddebug, __verbose);
 extern int ddebug_remove_module(const char *mod_name);
 extern __printf(2, 3)
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
@@ -71,8 +73,7 @@ void __dynamic_netdev_dbg(struct _ddebug *descriptor,
 			  const char *fmt, ...);
 
 #define DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, key, init)	\
-	static struct _ddebug  __aligned(8)			\
-	__attribute__((section("__verbose"))) name = {		\
+	static LINKTABLE(__verbose, SECTION_ORDER_ANY) name = {	\
 		.modname = KBUILD_MODNAME,			\
 		.function = __func__,				\
 		.filename = __FILE__,				\
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index da796e2dc4f5..27a335e3b1f3 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -37,8 +37,7 @@
 #include <linux/device.h>
 #include <linux/netdevice.h>
 
-extern struct _ddebug __start___verbose[];
-extern struct _ddebug __stop___verbose[];
+DEFINE_LINKTABLE(struct _ddebug, __verbose);
 
 struct ddebug_table {
 	struct list_head link;
@@ -978,14 +977,14 @@ static int __init dynamic_debug_init(void)
 	int n = 0, entries = 0, modct = 0;
 	int verbose_bytes = 0;
 
-	if (__start___verbose == __stop___verbose) {
-		pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
+	if (LINKTABLE_EMPTY(__verbose)) {
+		pr_warn("dynamic debug linker table empty on CONFIG_DYNAMIC_DEBUG build\n");
 		return 1;
 	}
-	iter = __start___verbose;
+	iter = LINKTABLE_START(__verbose);
 	modname = iter->modname;
 	iter_start = iter;
-	for (; iter < __stop___verbose; iter++) {
+	linktable_for_each(iter, __verbose) {
 		entries++;
 		verbose_bytes += strlen(iter->modname) + strlen(iter->function)
 			+ strlen(iter->filename) + strlen(iter->format);
@@ -1008,7 +1007,7 @@ static int __init dynamic_debug_init(void)
 	ddebug_init_success = 1;
 	vpr_info("%d modules, %d entries and %d bytes in ddebug tables, %d bytes in (readonly) verbose section\n",
 		 modct, entries, (int)(modct * sizeof(struct ddebug_table)),
-		 verbose_bytes + (int)(__stop___verbose - __start___verbose));
+		 verbose_bytes + (int)(LINKTABLE_SIZE(__verbose)));
 
 	/* apply ddebug_query boot param, dont unload tables on err */
 	if (ddebug_setup_string[0] != '\0') {
diff --git a/scripts/module-common.lds b/scripts/module-common.lds
index db0e724556c5..25755d458f09 100644
--- a/scripts/module-common.lds
+++ b/scripts/module-common.lds
@@ -17,6 +17,7 @@ SECTIONS {
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
 	__jump_table		0 : { *(SORT(.data..tbl.__jump_table.*)) }
+	__verbose		0 : { *(SORT(.data..tbl.__verbose.*)) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
-- 
2.11.0


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 10/14] dynamic_debug: port to use linker tables
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez, Barry Song, Mike Frysinger, Michael Matz,
	Fengguang Wu

This removes the custom vmlinux.lds.h hacks and uses
the generalized solution for .data entries.

There is much more potential for further fine tuning here
in the future though. For instance, linker tables enable
an extra postfix for order level annotations, this could
easily be used as the KBUILD_MODNAME and with a bit of
linker table changes we may be able to get a direct O(1)
count of the entries for that KBUILD_MODNAME: it would
just be a count on the number of entries for the given
order level. This should help make dynamic_debug_init()
cleaner and also reduce the amount of time it takes at
boot time. Instead of iterating over each print until we
have all for a KBUILD_MODNAME, we'd instead directly
operate on each KBUILD_MODNAME directly. We can work on
this later to make this change easier to review.

Tested dynamic debug with dyndbg query and debugfs control
and it works as expected, for both built-in code and modules.

v6: rename table macro as suggested by Andy Shevchenko

v5:

o Use ..tbl instead of .tbl as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names,
  use LINKTABLE_EMPTY(), LINKTABLE_START()

v4: fix compilation on blackfin
v3: added modular support
v2: introduced this patch into the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/asm-generic/vmlinux.lds.h |  4 ----
 include/linux/dynamic_debug.h     |  5 +++--
 lib/dynamic_debug.c               | 13 ++++++-------
 scripts/module-common.lds         |  1 +
 4 files changed, 10 insertions(+), 13 deletions(-)

diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 887d844f0406..37b99537d5a9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -216,10 +216,6 @@
 	*(.data.unlikely)						\
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
-	. = ALIGN(8);							\
-	VMLINUX_SYMBOL(__start___verbose) = .;                          \
-	KEEP(*(__verbose))                                              \
-	VMLINUX_SYMBOL(__stop___verbose) = .;				\
 	LIKELY_PROFILE()		       				\
 	BRANCH_PROFILE()						\
 	TRACE_PRINTKS()							\
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 546d68057e3b..a52618a77b09 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -4,6 +4,7 @@
 #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
 #include <linux/jump_label.h>
 #endif
+#include <linux/tables.h>
 
 /*
  * An instance of this structure is created in a special
@@ -50,6 +51,7 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
 				const char *modname);
 
 #if defined(CONFIG_DYNAMIC_DEBUG)
+DECLARE_LINKTABLE(struct _ddebug, __verbose);
 extern int ddebug_remove_module(const char *mod_name);
 extern __printf(2, 3)
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
@@ -71,8 +73,7 @@ void __dynamic_netdev_dbg(struct _ddebug *descriptor,
 			  const char *fmt, ...);
 
 #define DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, key, init)	\
-	static struct _ddebug  __aligned(8)			\
-	__attribute__((section("__verbose"))) name = {		\
+	static LINKTABLE(__verbose, SECTION_ORDER_ANY) name = {	\
 		.modname = KBUILD_MODNAME,			\
 		.function = __func__,				\
 		.filename = __FILE__,				\
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index da796e2dc4f5..27a335e3b1f3 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -37,8 +37,7 @@
 #include <linux/device.h>
 #include <linux/netdevice.h>
 
-extern struct _ddebug __start___verbose[];
-extern struct _ddebug __stop___verbose[];
+DEFINE_LINKTABLE(struct _ddebug, __verbose);
 
 struct ddebug_table {
 	struct list_head link;
@@ -978,14 +977,14 @@ static int __init dynamic_debug_init(void)
 	int n = 0, entries = 0, modct = 0;
 	int verbose_bytes = 0;
 
-	if (__start___verbose == __stop___verbose) {
-		pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
+	if (LINKTABLE_EMPTY(__verbose)) {
+		pr_warn("dynamic debug linker table empty on CONFIG_DYNAMIC_DEBUG build\n");
 		return 1;
 	}
-	iter = __start___verbose;
+	iter = LINKTABLE_START(__verbose);
 	modname = iter->modname;
 	iter_start = iter;
-	for (; iter < __stop___verbose; iter++) {
+	linktable_for_each(iter, __verbose) {
 		entries++;
 		verbose_bytes += strlen(iter->modname) + strlen(iter->function)
 			+ strlen(iter->filename) + strlen(iter->format);
@@ -1008,7 +1007,7 @@ static int __init dynamic_debug_init(void)
 	ddebug_init_success = 1;
 	vpr_info("%d modules, %d entries and %d bytes in ddebug tables, %d bytes in (readonly) verbose section\n",
 		 modct, entries, (int)(modct * sizeof(struct ddebug_table)),
-		 verbose_bytes + (int)(__stop___verbose - __start___verbose));
+		 verbose_bytes + (int)(LINKTABLE_SIZE(__verbose)));
 
 	/* apply ddebug_query boot param, dont unload tables on err */
 	if (ddebug_setup_string[0] != '\0') {
diff --git a/scripts/module-common.lds b/scripts/module-common.lds
index db0e724556c5..25755d458f09 100644
--- a/scripts/module-common.lds
+++ b/scripts/module-common.lds
@@ -17,6 +17,7 @@ SECTIONS {
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
 	__jump_table		0 : { *(SORT(.data..tbl.__jump_table.*)) }
+	__verbose		0 : { *(SORT(.data..tbl.__verbose.*)) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 11/14] kprobes: move kprobe declarations to asm-generic/kprobes.h
  2017-01-09 14:58       ` Luis R. Rodriguez
  (?)
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt

Often all is needed is these small helpers, instead of compiler.h
or a full kprobes.h. This is important for asm helpers, in fact even
some asm/kprobes.h make use of these helpers... instead just keep a
generic asm file with helpers useful for asm code with the least amount
of clutter as possible.

Likewise we need now to also address what to do about this file for both
when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
for when architectures have CONFIG_HAVE_KPROBES but have disabled
CONFIG_KPROBES.

Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
this means most architecture code cannot include asm/kprobes.h safely.
Correct this and add guards for architectures missing them. Additionally
provide architectures that not have kprobes support with the default
asm-generic solution. This lets us force asm/kprobes.h on the header
include/linux/kprobes.h always, but most importantly we can now safely
include just asm/kprobes.h on architecture code without bringing
the full kitchen sink of header files.

Two architectures already provided a guard against CONFIG_KPROBES on
its kprobes.h: sh, arch. The rest of the architectures needed gaurds
added. We avoid including any not-needed headers on asm/kprobes.h
unless kprobes have been enabled.

In a subsequent atomic change we can try now to remove compiler.h from
include/linux/kprobes.h.

During this sweep I've also identified a few architectures defining
a common macro needed for both kprobes and ftrace, that of the
definition of the breakput instruction up. Some refer to this as
BREAKPOINT_INSTRUCTION. This must be kept outside of the #ifdef
CONFIG_KPROBES guard.

v5:

o fix BREAKPOINT_INSTRUCTION dependency with kernel architecture
  ftrace implementations:  Although its correct to #ifdef CONFIG_KPROBES
  on the architecture arch/$(ARCH)/include/asm/kprobes.h when
  architectures support ftrace they will rely on the
  BREAKPOINT_INSTRUCTION definition, this needs to be kept out from
  CONFIG_KPROBES as ftrace can be enabled without kprobes. This
  fixes compilation on x86 where kprobes is disabled but ftrace is
  left enabled.

o include <asm/kprobes.h> on arch/arm64/kernel/probes/decode-insn.h

v4: introduced this patch into the series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/alpha/include/asm/Kbuild          |  1 +
 arch/arc/include/asm/kprobes.h         |  6 ++++--
 arch/arm/include/asm/kprobes.h         |  4 ++++
 arch/arm/probes/decode.h               |  1 +
 arch/arm64/include/asm/kprobes.h       |  4 ++++
 arch/arm64/kernel/insn.c               |  1 +
 arch/arm64/kernel/probes/decode-insn.h |  2 ++
 arch/avr32/include/asm/kprobes.h       |  7 ++++++-
 arch/blackfin/include/asm/Kbuild       |  1 +
 arch/c6x/include/asm/Kbuild            |  1 +
 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/kprobes.h        | 12 +++++++++---
 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/kprobes.h        |  6 +++++-
 arch/mn10300/include/asm/kprobes.h     |  7 ++++++-
 arch/nios2/include/asm/Kbuild          |  1 +
 arch/openrisc/include/asm/Kbuild       |  1 +
 arch/parisc/include/asm/Kbuild         |  1 +
 arch/powerpc/include/asm/kprobes.h     |  3 +++
 arch/s390/include/asm/kprobes.h        |  7 ++++++-
 arch/score/include/asm/Kbuild          |  1 +
 arch/sh/include/asm/kprobes.h          |  5 ++++-
 arch/sparc/include/asm/kprobes.h       | 10 ++++++++--
 arch/tile/include/asm/kprobes.h        |  6 +++++-
 arch/um/include/asm/Kbuild             |  1 +
 arch/unicore32/include/asm/Kbuild      |  1 +
 arch/x86/include/asm/kprobes.h         |  9 ++++++++-
 arch/xtensa/include/asm/Kbuild         |  1 +
 include/asm-generic/kprobes.h          | 25 +++++++++++++++++++++++++
 include/linux/compiler.h               |  8 --------
 include/linux/kprobes.h                | 19 +++----------------
 37 files changed, 122 insertions(+), 38 deletions(-)
 create mode 100644 include/asm-generic/kprobes.h

diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index f3bdc31d3c97..54d388fd026f 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += trace_clock.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/arc/include/asm/kprobes.h b/arch/arc/include/asm/kprobes.h
index 944dbedb38b5..00bdbe167615 100644
--- a/arch/arc/include/asm/kprobes.h
+++ b/arch/arc/include/asm/kprobes.h
@@ -9,6 +9,8 @@
 #ifndef _ARC_KPROBES_H
 #define _ARC_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
 #ifdef CONFIG_KPROBES
 
 typedef u16 kprobe_opcode_t;
@@ -55,6 +57,6 @@ void trap_is_kprobe(unsigned long address, struct pt_regs *regs);
 static void trap_is_kprobe(unsigned long address, struct pt_regs *regs)
 {
 }
-#endif
+#endif /* CONFIG_KPROBES */
 
-#endif
+#endif /* _ARC_KPROBES_H */
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index 3ea9be559726..59655459da59 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/notifier.h>
@@ -83,4 +86,5 @@ struct arch_optimized_insn {
 	 */
 };
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm/probes/decode.h b/arch/arm/probes/decode.h
index f9b08ba7fe73..548d622a3159 100644
--- a/arch/arm/probes/decode.h
+++ b/arch/arm/probes/decode.h
@@ -22,6 +22,7 @@
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <asm/probes.h>
+#include <asm/kprobes.h>
 
 void __init arm_probes_decode_init(void);
 
diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
index 1737aecfcc5e..6deb8d726041 100644
--- a/arch/arm64/include/asm/kprobes.h
+++ b/arch/arm64/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -57,4 +60,5 @@ int kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr);
 void kretprobe_trampoline(void);
 void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 94b62c1fa4df..ae912304ed84 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -31,6 +31,7 @@
 #include <asm/debug-monitors.h>
 #include <asm/fixmap.h>
 #include <asm/insn.h>
+#include <asm/kprobes.h>
 
 #define AARCH64_INSN_SF_BIT	BIT(31)
 #define AARCH64_INSN_N_BIT	BIT(22)
diff --git a/arch/arm64/kernel/probes/decode-insn.h b/arch/arm64/kernel/probes/decode-insn.h
index 76d3f315407f..192ab007bacb 100644
--- a/arch/arm64/kernel/probes/decode-insn.h
+++ b/arch/arm64/kernel/probes/decode-insn.h
@@ -16,6 +16,8 @@
 #ifndef _ARM_KERNEL_KPROBES_ARM64_H
 #define _ARM_KERNEL_KPROBES_ARM64_H
 
+#include <asm/kprobes.h>
+
 /*
  * ARM strongly recommends a limit of 128 bytes between LoadExcl and
  * StoreExcl instructions in a single thread of execution. So keep the
diff --git a/arch/avr32/include/asm/kprobes.h b/arch/avr32/include/asm/kprobes.h
index 45f563ed73fd..28dfc61ad384 100644
--- a/arch/avr32/include/asm/kprobes.h
+++ b/arch/avr32/include/asm/kprobes.h
@@ -11,10 +11,14 @@
 #ifndef __ASM_AVR32_KPROBES_H
 #define __ASM_AVR32_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xd673	/* breakpoint */
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 
 typedef u16	kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xd673	/* breakpoint */
 #define MAX_INSN_SIZE		2
 #define MAX_STACK_SIZE		64	/* 32 would probably be OK */
 
@@ -46,4 +50,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif /* __ASM_AVR32_KPROBES_H */
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 9115b215fc7e..52351d3fd36e 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -50,3 +50,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index cede2a950fbf..c54f7cc1f63e 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
+generic-y += kprobes.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 7062c1be7913..051d355feae3 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 4a59cbda5091..b58b9fc49383 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index d79968d93c12..cfca7de52b37 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -78,3 +78,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index d59ac1c1858b..d7cc35451f30 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/ia64/include/asm/kprobes.h b/arch/ia64/include/asm/kprobes.h
index d5505d6f2382..0302b3664789 100644
--- a/arch/ia64/include/asm/kprobes.h
+++ b/arch/ia64/include/asm/kprobes.h
@@ -23,14 +23,19 @@
  * 2005-Apr     Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
  *              <anil.s.keshavamurthy@intel.com> adapted from i386
  */
+#include <asm-generic/kprobes.h>
+#include <asm/break.h>
+
+#define BREAK_INST	(long)(__IA64_BREAK_KPROBE << 6)
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
-#include <asm/break.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
 #define MAX_INSN_SIZE   2	/* last half is for kprobe-booster */
-#define BREAK_INST	(long)(__IA64_BREAK_KPROBE << 6)
 #define NOP_M_INST	(long)(1<<27)
 #define BRL_INST(i1, i2) ((long)((0xcL << 37) |	/* brl */ \
 				(0x1L << 12) |	/* many */ \
@@ -124,4 +129,5 @@ extern void invalidate_stacked_regs(void);
 extern void flush_register_stack(void);
 extern void arch_remove_kprobe(struct kprobe *p);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 24088f3c733c..198ad591ab41 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index c28bcdecc764..412dd23ab946 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -37,3 +37,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index c836f7e2a5e7..8371cc9b1b3c 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -58,3 +58,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index 01afb1b420f5..865ce3d96443 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/mips/include/asm/kprobes.h b/arch/mips/include/asm/kprobes.h
index daba1f9a4f79..291846d9ba83 100644
--- a/arch/mips/include/asm/kprobes.h
+++ b/arch/mips/include/asm/kprobes.h
@@ -22,6 +22,9 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/ptrace.h>
 #include <linux/types.h>
 
@@ -94,4 +97,5 @@ struct kprobe_ctlblk {
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/mn10300/include/asm/kprobes.h b/arch/mn10300/include/asm/kprobes.h
index c800b590183a..7abea0bdb549 100644
--- a/arch/mn10300/include/asm/kprobes.h
+++ b/arch/mn10300/include/asm/kprobes.h
@@ -21,13 +21,17 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xff
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 
 struct kprobe;
 
 typedef unsigned char kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xff
 #define MAX_INSN_SIZE 8
 #define MAX_STACK_SIZE 128
 
@@ -47,4 +51,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 extern void arch_remove_kprobe(struct kprobe *p);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_KPROBES_H */
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index ee6220dac1e8..d6ce7edee7e0 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -66,3 +66,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index ceafe458e295..1bf89a67317c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -74,3 +74,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index aaae8a9f6099..19d5b7e12ecf 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -31,3 +31,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h
index 97b8c1f83453..c7ee3fcbd6e2 100644
--- a/arch/powerpc/include/asm/kprobes.h
+++ b/arch/powerpc/include/asm/kprobes.h
@@ -1,5 +1,8 @@
 #ifndef _ASM_POWERPC_KPROBES_H
 #define _ASM_POWERPC_KPROBES_H
+
+#include <asm-generic/kprobes.h>
+
 #ifdef __KERNEL__
 /*
  *  Kernel Probes (KProbes)
diff --git a/arch/s390/include/asm/kprobes.h b/arch/s390/include/asm/kprobes.h
index 591e5a5279b0..84c0f9086483 100644
--- a/arch/s390/include/asm/kprobes.h
+++ b/arch/s390/include/asm/kprobes.h
@@ -27,6 +27,11 @@
  * 2005-Dec	Used as a template for s390 by Mike Grundy
  *		<grundym@us.ibm.com>
  */
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0x0002
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -37,7 +42,6 @@ struct pt_regs;
 struct kprobe;
 
 typedef u16 kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0x0002
 
 /* Maximum instruction size is 3 (16bit) halfwords: */
 #define MAX_INSN_SIZE		0x0003
@@ -91,4 +95,5 @@ int probe_is_insn_relative_long(u16 *insn);
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif	/* _ASM_S390_KPROBES_H */
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index 16ea15a3e432..6ac8a7f5c768 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -17,3 +17,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h
index 134f3980e44a..f0986f9b3844 100644
--- a/arch/sh/include/asm/kprobes.h
+++ b/arch/sh/include/asm/kprobes.h
@@ -1,13 +1,16 @@
 #ifndef __ASM_SH_KPROBES_H
 #define __ASM_SH_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xc33a
+
 #ifdef CONFIG_KPROBES
 
 #include <linux/types.h>
 #include <linux/ptrace.h>
 
 typedef insn_size_t kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xc33a
 
 #define MAX_INSN_SIZE 16
 #define MAX_STACK_SIZE 64
diff --git a/arch/sparc/include/asm/kprobes.h b/arch/sparc/include/asm/kprobes.h
index a145d798e112..49f8402035d7 100644
--- a/arch/sparc/include/asm/kprobes.h
+++ b/arch/sparc/include/asm/kprobes.h
@@ -1,13 +1,17 @@
 #ifndef _SPARC64_KPROBES_H
 #define _SPARC64_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION   0x91d02070 /* ta 0x70 */
+#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/percpu.h>
 
 typedef u32 kprobe_opcode_t;
 
-#define BREAKPOINT_INSTRUCTION   0x91d02070 /* ta 0x70 */
-#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
 #define MAX_INSN_SIZE 2
 
 #define kretprobe_blacklist_size 0
@@ -48,4 +52,6 @@ int kprobe_exceptions_notify(struct notifier_block *self,
 int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
 				      struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _SPARC64_KPROBES_H */
diff --git a/arch/tile/include/asm/kprobes.h b/arch/tile/include/asm/kprobes.h
index d8f9a83943b1..4a8b1cadca24 100644
--- a/arch/tile/include/asm/kprobes.h
+++ b/arch/tile/include/asm/kprobes.h
@@ -17,10 +17,13 @@
 #ifndef _ASM_TILE_KPROBES_H
 #define _ASM_TILE_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
-
 #include <arch/opcode.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
@@ -76,4 +79,5 @@ void arch_remove_kprobe(struct kprobe *);
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 			     unsigned long val, void *data);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_TILE_KPROBES_H */
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index d2867aa09e23..ccc5ffeaeef5 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 6671a1f08ead..5aacafb6d385 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h
index d1d1e5094c28..200581691c6e 100644
--- a/arch/x86/include/asm/kprobes.h
+++ b/arch/x86/include/asm/kprobes.h
@@ -21,6 +21,12 @@
  *
  * See arch/x86/kernel/kprobes.c for x86 kprobes history.
  */
+
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xcc
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -32,7 +38,6 @@ struct pt_regs;
 struct kprobe;
 
 typedef u8 kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xcc
 #define RELATIVEJUMP_OPCODE 0xe9
 #define RELATIVEJUMP_SIZE 5
 #define RELATIVECALL_OPCODE 0xe8
@@ -116,4 +121,6 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 extern int kprobe_int3_handler(struct pt_regs *regs);
 extern int kprobe_debug_handler(struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_X86_KPROBES_H */
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index 7b41f32a2ba0..20f524ded00e 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
new file mode 100644
index 000000000000..57af9f21d148
--- /dev/null
+++ b/include/asm-generic/kprobes.h
@@ -0,0 +1,25 @@
+#ifndef _ASM_GENERIC_KPROBES_H
+#define _ASM_GENERIC_KPROBES_H
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#ifdef CONFIG_KPROBES
+/*
+ * Blacklist ganerating macro. Specify functions which is not probed
+ * by using this macro.
+ */
+# define __NOKPROBE_SYMBOL(fname)				\
+static unsigned long __used					\
+	__attribute__((__section__("_kprobe_blacklist")))	\
+	_kbl_addr_##fname = (unsigned long)fname;
+# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
+/* Use this to forbid a kprobes attach on very low level functions */
+# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define nokprobe_inline	__always_inline
+#else
+# define NOKPROBE_SYMBOL(fname)
+# define __kprobes
+# define nokprobe_inline	inline
+#endif
+#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
+
+#endif /* _ASM_GENERIC_KPROBES_H */
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index cf0fa5d86059..dca49b4099da 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -566,12 +566,4 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 	(_________p1); \
 })
 
-/* Ignore/forbid kprobes attach on very low level functions marked by this attribute: */
-#ifdef CONFIG_KPROBES
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
-# define nokprobe_inline	__always_inline
-#else
-# define __kprobes
-# define nokprobe_inline	inline
-#endif
 #endif /* __LINUX_COMPILER_H */
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 8f6849084248..985ed79ef431 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -29,7 +29,7 @@
  *		<jkenisto@us.ibm.com>  and Prasanna S Panchamukhi
  *		<prasanna@in.ibm.com> added function-return probes.
  */
-#include <linux/compiler.h>	/* for __kprobes */
+#include <linux/compiler.h>
 #include <linux/linkage.h>
 #include <linux/list.h>
 #include <linux/notifier.h>
@@ -40,9 +40,9 @@
 #include <linux/rcupdate.h>
 #include <linux/mutex.h>
 #include <linux/ftrace.h>
+#include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
-#include <asm/kprobes.h>
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
@@ -51,6 +51,7 @@
 #define KPROBE_HIT_SSDONE	0x00000008
 
 #else /* CONFIG_KPROBES */
+#include <asm-generic/kprobes.h>
 typedef int kprobe_opcode_t;
 struct arch_specific_insn {
 	int dummy;
@@ -481,18 +482,4 @@ static inline int enable_jprobe(struct jprobe *jp)
 	return enable_kprobe(&jp->kp);
 }
 
-#ifdef CONFIG_KPROBES
-/*
- * Blacklist ganerating macro. Specify functions which is not probed
- * by using this macro.
- */
-#define __NOKPROBE_SYMBOL(fname)			\
-static unsigned long __used				\
-	__attribute__((section("_kprobe_blacklist")))	\
-	_kbl_addr_##fname = (unsigned long)fname;
-#define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
-#else
-#define NOKPROBE_SYMBOL(fname)
-#endif
-
 #endif /* _LINUX_KPROBES_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 11/14] kprobes: move kprobe declarations to asm-generic/kprobes.h
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt, ak

Often all is needed is these small helpers, instead of compiler.h
or a full kprobes.h. This is important for asm helpers, in fact even
some asm/kprobes.h make use of these helpers... instead just keep a
generic asm file with helpers useful for asm code with the least amount
of clutter as possible.

Likewise we need now to also address what to do about this file for both
when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
for when architectures have CONFIG_HAVE_KPROBES but have disabled
CONFIG_KPROBES.

Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
this means most architecture code cannot include asm/kprobes.h safely.
Correct this and add guards for architectures missing them. Additionally
provide architectures that not have kprobes support with the default
asm-generic solution. This lets us force asm/kprobes.h on the header
include/linux/kprobes.h always, but most importantly we can now safely
include just asm/kprobes.h on architecture code without bringing
the full kitchen sink of header files.

Two architectures already provided a guard against CONFIG_KPROBES on
its kprobes.h: sh, arch. The rest of the architectures needed gaurds
added. We avoid including any not-needed headers on asm/kprobes.h
unless kprobes have been enabled.

In a subsequent atomic change we can try now to remove compiler.h from
include/linux/kprobes.h.

During this sweep I've also identified a few architectures defining
a common macro needed for both kprobes and ftrace, that of the
definition of the breakput instruction up. Some refer to this as
BREAKPOINT_INSTRUCTION. This must be kept outside of the #ifdef
CONFIG_KPROBES guard.

v5:

o fix BREAKPOINT_INSTRUCTION dependency with kernel architecture
  ftrace implementations:  Although its correct to #ifdef CONFIG_KPROBES
  on the architecture arch/$(ARCH)/include/asm/kprobes.h when
  architectures support ftrace they will rely on the
  BREAKPOINT_INSTRUCTION definition, this needs to be kept out from
  CONFIG_KPROBES as ftrace can be enabled without kprobes. This
  fixes compilation on x86 where kprobes is disabled but ftrace is
  left enabled.

o include <asm/kprobes.h> on arch/arm64/kernel/probes/decode-insn.h

v4: introduced this patch into the series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/alpha/include/asm/Kbuild          |  1 +
 arch/arc/include/asm/kprobes.h         |  6 ++++--
 arch/arm/include/asm/kprobes.h         |  4 ++++
 arch/arm/probes/decode.h               |  1 +
 arch/arm64/include/asm/kprobes.h       |  4 ++++
 arch/arm64/kernel/insn.c               |  1 +
 arch/arm64/kernel/probes/decode-insn.h |  2 ++
 arch/avr32/include/asm/kprobes.h       |  7 ++++++-
 arch/blackfin/include/asm/Kbuild       |  1 +
 arch/c6x/include/asm/Kbuild            |  1 +
 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/kprobes.h        | 12 +++++++++---
 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/kprobes.h        |  6 +++++-
 arch/mn10300/include/asm/kprobes.h     |  7 ++++++-
 arch/nios2/include/asm/Kbuild          |  1 +
 arch/openrisc/include/asm/Kbuild       |  1 +
 arch/parisc/include/asm/Kbuild         |  1 +
 arch/powerpc/include/asm/kprobes.h     |  3 +++
 arch/s390/include/asm/kprobes.h        |  7 ++++++-
 arch/score/include/asm/Kbuild          |  1 +
 arch/sh/include/asm/kprobes.h          |  5 ++++-
 arch/sparc/include/asm/kprobes.h       | 10 ++++++++--
 arch/tile/include/asm/kprobes.h        |  6 +++++-
 arch/um/include/asm/Kbuild             |  1 +
 arch/unicore32/include/asm/Kbuild      |  1 +
 arch/x86/include/asm/kprobes.h         |  9 ++++++++-
 arch/xtensa/include/asm/Kbuild         |  1 +
 include/asm-generic/kprobes.h          | 25 +++++++++++++++++++++++++
 include/linux/compiler.h               |  8 --------
 include/linux/kprobes.h                | 19 +++----------------
 37 files changed, 122 insertions(+), 38 deletions(-)
 create mode 100644 include/asm-generic/kprobes.h

diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index f3bdc31d3c97..54d388fd026f 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += trace_clock.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/arc/include/asm/kprobes.h b/arch/arc/include/asm/kprobes.h
index 944dbedb38b5..00bdbe167615 100644
--- a/arch/arc/include/asm/kprobes.h
+++ b/arch/arc/include/asm/kprobes.h
@@ -9,6 +9,8 @@
 #ifndef _ARC_KPROBES_H
 #define _ARC_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
 #ifdef CONFIG_KPROBES
 
 typedef u16 kprobe_opcode_t;
@@ -55,6 +57,6 @@ void trap_is_kprobe(unsigned long address, struct pt_regs *regs);
 static void trap_is_kprobe(unsigned long address, struct pt_regs *regs)
 {
 }
-#endif
+#endif /* CONFIG_KPROBES */
 
-#endif
+#endif /* _ARC_KPROBES_H */
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index 3ea9be559726..59655459da59 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/notifier.h>
@@ -83,4 +86,5 @@ struct arch_optimized_insn {
 	 */
 };
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm/probes/decode.h b/arch/arm/probes/decode.h
index f9b08ba7fe73..548d622a3159 100644
--- a/arch/arm/probes/decode.h
+++ b/arch/arm/probes/decode.h
@@ -22,6 +22,7 @@
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <asm/probes.h>
+#include <asm/kprobes.h>
 
 void __init arm_probes_decode_init(void);
 
diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
index 1737aecfcc5e..6deb8d726041 100644
--- a/arch/arm64/include/asm/kprobes.h
+++ b/arch/arm64/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -57,4 +60,5 @@ int kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr);
 void kretprobe_trampoline(void);
 void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 94b62c1fa4df..ae912304ed84 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -31,6 +31,7 @@
 #include <asm/debug-monitors.h>
 #include <asm/fixmap.h>
 #include <asm/insn.h>
+#include <asm/kprobes.h>
 
 #define AARCH64_INSN_SF_BIT	BIT(31)
 #define AARCH64_INSN_N_BIT	BIT(22)
diff --git a/arch/arm64/kernel/probes/decode-insn.h b/arch/arm64/kernel/probes/decode-insn.h
index 76d3f315407f..192ab007bacb 100644
--- a/arch/arm64/kernel/probes/decode-insn.h
+++ b/arch/arm64/kernel/probes/decode-insn.h
@@ -16,6 +16,8 @@
 #ifndef _ARM_KERNEL_KPROBES_ARM64_H
 #define _ARM_KERNEL_KPROBES_ARM64_H
 
+#include <asm/kprobes.h>
+
 /*
  * ARM strongly recommends a limit of 128 bytes between LoadExcl and
  * StoreExcl instructions in a single thread of execution. So keep the
diff --git a/arch/avr32/include/asm/kprobes.h b/arch/avr32/include/asm/kprobes.h
index 45f563ed73fd..28dfc61ad384 100644
--- a/arch/avr32/include/asm/kprobes.h
+++ b/arch/avr32/include/asm/kprobes.h
@@ -11,10 +11,14 @@
 #ifndef __ASM_AVR32_KPROBES_H
 #define __ASM_AVR32_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xd673	/* breakpoint */
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 
 typedef u16	kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xd673	/* breakpoint */
 #define MAX_INSN_SIZE		2
 #define MAX_STACK_SIZE		64	/* 32 would probably be OK */
 
@@ -46,4 +50,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif /* __ASM_AVR32_KPROBES_H */
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 9115b215fc7e..52351d3fd36e 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -50,3 +50,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index cede2a950fbf..c54f7cc1f63e 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
+generic-y += kprobes.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 7062c1be7913..051d355feae3 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 4a59cbda5091..b58b9fc49383 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index d79968d93c12..cfca7de52b37 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -78,3 +78,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index d59ac1c1858b..d7cc35451f30 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/ia64/include/asm/kprobes.h b/arch/ia64/include/asm/kprobes.h
index d5505d6f2382..0302b3664789 100644
--- a/arch/ia64/include/asm/kprobes.h
+++ b/arch/ia64/include/asm/kprobes.h
@@ -23,14 +23,19 @@
  * 2005-Apr     Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
  *              <anil.s.keshavamurthy@intel.com> adapted from i386
  */
+#include <asm-generic/kprobes.h>
+#include <asm/break.h>
+
+#define BREAK_INST	(long)(__IA64_BREAK_KPROBE << 6)
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
-#include <asm/break.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
 #define MAX_INSN_SIZE   2	/* last half is for kprobe-booster */
-#define BREAK_INST	(long)(__IA64_BREAK_KPROBE << 6)
 #define NOP_M_INST	(long)(1<<27)
 #define BRL_INST(i1, i2) ((long)((0xcL << 37) |	/* brl */ \
 				(0x1L << 12) |	/* many */ \
@@ -124,4 +129,5 @@ extern void invalidate_stacked_regs(void);
 extern void flush_register_stack(void);
 extern void arch_remove_kprobe(struct kprobe *p);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 24088f3c733c..198ad591ab41 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index c28bcdecc764..412dd23ab946 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -37,3 +37,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index c836f7e2a5e7..8371cc9b1b3c 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -58,3 +58,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index 01afb1b420f5..865ce3d96443 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/mips/include/asm/kprobes.h b/arch/mips/include/asm/kprobes.h
index daba1f9a4f79..291846d9ba83 100644
--- a/arch/mips/include/asm/kprobes.h
+++ b/arch/mips/include/asm/kprobes.h
@@ -22,6 +22,9 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/ptrace.h>
 #include <linux/types.h>
 
@@ -94,4 +97,5 @@ struct kprobe_ctlblk {
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/mn10300/include/asm/kprobes.h b/arch/mn10300/include/asm/kprobes.h
index c800b590183a..7abea0bdb549 100644
--- a/arch/mn10300/include/asm/kprobes.h
+++ b/arch/mn10300/include/asm/kprobes.h
@@ -21,13 +21,17 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xff
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 
 struct kprobe;
 
 typedef unsigned char kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xff
 #define MAX_INSN_SIZE 8
 #define MAX_STACK_SIZE 128
 
@@ -47,4 +51,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 extern void arch_remove_kprobe(struct kprobe *p);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_KPROBES_H */
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index ee6220dac1e8..d6ce7edee7e0 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -66,3 +66,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index ceafe458e295..1bf89a67317c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -74,3 +74,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index aaae8a9f6099..19d5b7e12ecf 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -31,3 +31,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h
index 97b8c1f83453..c7ee3fcbd6e2 100644
--- a/arch/powerpc/include/asm/kprobes.h
+++ b/arch/powerpc/include/asm/kprobes.h
@@ -1,5 +1,8 @@
 #ifndef _ASM_POWERPC_KPROBES_H
 #define _ASM_POWERPC_KPROBES_H
+
+#include <asm-generic/kprobes.h>
+
 #ifdef __KERNEL__
 /*
  *  Kernel Probes (KProbes)
diff --git a/arch/s390/include/asm/kprobes.h b/arch/s390/include/asm/kprobes.h
index 591e5a5279b0..84c0f9086483 100644
--- a/arch/s390/include/asm/kprobes.h
+++ b/arch/s390/include/asm/kprobes.h
@@ -27,6 +27,11 @@
  * 2005-Dec	Used as a template for s390 by Mike Grundy
  *		<grundym@us.ibm.com>
  */
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0x0002
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -37,7 +42,6 @@ struct pt_regs;
 struct kprobe;
 
 typedef u16 kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0x0002
 
 /* Maximum instruction size is 3 (16bit) halfwords: */
 #define MAX_INSN_SIZE		0x0003
@@ -91,4 +95,5 @@ int probe_is_insn_relative_long(u16 *insn);
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif	/* _ASM_S390_KPROBES_H */
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index 16ea15a3e432..6ac8a7f5c768 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -17,3 +17,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h
index 134f3980e44a..f0986f9b3844 100644
--- a/arch/sh/include/asm/kprobes.h
+++ b/arch/sh/include/asm/kprobes.h
@@ -1,13 +1,16 @@
 #ifndef __ASM_SH_KPROBES_H
 #define __ASM_SH_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xc33a
+
 #ifdef CONFIG_KPROBES
 
 #include <linux/types.h>
 #include <linux/ptrace.h>
 
 typedef insn_size_t kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xc33a
 
 #define MAX_INSN_SIZE 16
 #define MAX_STACK_SIZE 64
diff --git a/arch/sparc/include/asm/kprobes.h b/arch/sparc/include/asm/kprobes.h
index a145d798e112..49f8402035d7 100644
--- a/arch/sparc/include/asm/kprobes.h
+++ b/arch/sparc/include/asm/kprobes.h
@@ -1,13 +1,17 @@
 #ifndef _SPARC64_KPROBES_H
 #define _SPARC64_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION   0x91d02070 /* ta 0x70 */
+#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/percpu.h>
 
 typedef u32 kprobe_opcode_t;
 
-#define BREAKPOINT_INSTRUCTION   0x91d02070 /* ta 0x70 */
-#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
 #define MAX_INSN_SIZE 2
 
 #define kretprobe_blacklist_size 0
@@ -48,4 +52,6 @@ int kprobe_exceptions_notify(struct notifier_block *self,
 int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
 				      struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _SPARC64_KPROBES_H */
diff --git a/arch/tile/include/asm/kprobes.h b/arch/tile/include/asm/kprobes.h
index d8f9a83943b1..4a8b1cadca24 100644
--- a/arch/tile/include/asm/kprobes.h
+++ b/arch/tile/include/asm/kprobes.h
@@ -17,10 +17,13 @@
 #ifndef _ASM_TILE_KPROBES_H
 #define _ASM_TILE_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
-
 #include <arch/opcode.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
@@ -76,4 +79,5 @@ void arch_remove_kprobe(struct kprobe *);
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 			     unsigned long val, void *data);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_TILE_KPROBES_H */
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index d2867aa09e23..ccc5ffeaeef5 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 6671a1f08ead..5aacafb6d385 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h
index d1d1e5094c28..200581691c6e 100644
--- a/arch/x86/include/asm/kprobes.h
+++ b/arch/x86/include/asm/kprobes.h
@@ -21,6 +21,12 @@
  *
  * See arch/x86/kernel/kprobes.c for x86 kprobes history.
  */
+
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xcc
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -32,7 +38,6 @@ struct pt_regs;
 struct kprobe;
 
 typedef u8 kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xcc
 #define RELATIVEJUMP_OPCODE 0xe9
 #define RELATIVEJUMP_SIZE 5
 #define RELATIVECALL_OPCODE 0xe8
@@ -116,4 +121,6 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 extern int kprobe_int3_handler(struct pt_regs *regs);
 extern int kprobe_debug_handler(struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_X86_KPROBES_H */
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index 7b41f32a2ba0..20f524ded00e 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
new file mode 100644
index 000000000000..57af9f21d148
--- /dev/null
+++ b/include/asm-generic/kprobes.h
@@ -0,0 +1,25 @@
+#ifndef _ASM_GENERIC_KPROBES_H
+#define _ASM_GENERIC_KPROBES_H
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#ifdef CONFIG_KPROBES
+/*
+ * Blacklist ganerating macro. Specify functions which is not probed
+ * by using this macro.
+ */
+# define __NOKPROBE_SYMBOL(fname)				\
+static unsigned long __used					\
+	__attribute__((__section__("_kprobe_blacklist")))	\
+	_kbl_addr_##fname = (unsigned long)fname;
+# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
+/* Use this to forbid a kprobes attach on very low level functions */
+# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define nokprobe_inline	__always_inline
+#else
+# define NOKPROBE_SYMBOL(fname)
+# define __kprobes
+# define nokprobe_inline	inline
+#endif
+#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
+
+#endif /* _ASM_GENERIC_KPROBES_H */
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index cf0fa5d86059..dca49b4099da 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -566,12 +566,4 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 	(_________p1); \
 })
 
-/* Ignore/forbid kprobes attach on very low level functions marked by this attribute: */
-#ifdef CONFIG_KPROBES
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
-# define nokprobe_inline	__always_inline
-#else
-# define __kprobes
-# define nokprobe_inline	inline
-#endif
 #endif /* __LINUX_COMPILER_H */
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 8f6849084248..985ed79ef431 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -29,7 +29,7 @@
  *		<jkenisto@us.ibm.com>  and Prasanna S Panchamukhi
  *		<prasanna@in.ibm.com> added function-return probes.
  */
-#include <linux/compiler.h>	/* for __kprobes */
+#include <linux/compiler.h>
 #include <linux/linkage.h>
 #include <linux/list.h>
 #include <linux/notifier.h>
@@ -40,9 +40,9 @@
 #include <linux/rcupdate.h>
 #include <linux/mutex.h>
 #include <linux/ftrace.h>
+#include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
-#include <asm/kprobes.h>
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
@@ -51,6 +51,7 @@
 #define KPROBE_HIT_SSDONE	0x00000008
 
 #else /* CONFIG_KPROBES */
+#include <asm-generic/kprobes.h>
 typedef int kprobe_opcode_t;
 struct arch_specific_insn {
 	int dummy;
@@ -481,18 +482,4 @@ static inline int enable_jprobe(struct jprobe *jp)
 	return enable_kprobe(&jp->kp);
 }
 
-#ifdef CONFIG_KPROBES
-/*
- * Blacklist ganerating macro. Specify functions which is not probed
- * by using this macro.
- */
-#define __NOKPROBE_SYMBOL(fname)			\
-static unsigned long __used				\
-	__attribute__((section("_kprobe_blacklist")))	\
-	_kbl_addr_##fname = (unsigned long)fname;
-#define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
-#else
-#define NOKPROBE_SYMBOL(fname)
-#endif
-
 #endif /* _LINUX_KPROBES_H */
-- 
2.11.0


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 11/14] kprobes: move kprobe declarations to asm-generic/kprobes.h
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

Often all is needed is these small helpers, instead of compiler.h
or a full kprobes.h. This is important for asm helpers, in fact even
some asm/kprobes.h make use of these helpers... instead just keep a
generic asm file with helpers useful for asm code with the least amount
of clutter as possible.

Likewise we need now to also address what to do about this file for both
when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
for when architectures have CONFIG_HAVE_KPROBES but have disabled
CONFIG_KPROBES.

Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
this means most architecture code cannot include asm/kprobes.h safely.
Correct this and add guards for architectures missing them. Additionally
provide architectures that not have kprobes support with the default
asm-generic solution. This lets us force asm/kprobes.h on the header
include/linux/kprobes.h always, but most importantly we can now safely
include just asm/kprobes.h on architecture code without bringing
the full kitchen sink of header files.

Two architectures already provided a guard against CONFIG_KPROBES on
its kprobes.h: sh, arch. The rest of the architectures needed gaurds
added. We avoid including any not-needed headers on asm/kprobes.h
unless kprobes have been enabled.

In a subsequent atomic change we can try now to remove compiler.h from
include/linux/kprobes.h.

During this sweep I've also identified a few architectures defining
a common macro needed for both kprobes and ftrace, that of the
definition of the breakput instruction up. Some refer to this as
BREAKPOINT_INSTRUCTION. This must be kept outside of the #ifdef
CONFIG_KPROBES guard.

v5:

o fix BREAKPOINT_INSTRUCTION dependency with kernel architecture
  ftrace implementations:  Although its correct to #ifdef CONFIG_KPROBES
  on the architecture arch/$(ARCH)/include/asm/kprobes.h when
  architectures support ftrace they will rely on the
  BREAKPOINT_INSTRUCTION definition, this needs to be kept out from
  CONFIG_KPROBES as ftrace can be enabled without kprobes. This
  fixes compilation on x86 where kprobes is disabled but ftrace is
  left enabled.

o include <asm/kprobes.h> on arch/arm64/kernel/probes/decode-insn.h

v4: introduced this patch into the series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/alpha/include/asm/Kbuild          |  1 +
 arch/arc/include/asm/kprobes.h         |  6 ++++--
 arch/arm/include/asm/kprobes.h         |  4 ++++
 arch/arm/probes/decode.h               |  1 +
 arch/arm64/include/asm/kprobes.h       |  4 ++++
 arch/arm64/kernel/insn.c               |  1 +
 arch/arm64/kernel/probes/decode-insn.h |  2 ++
 arch/avr32/include/asm/kprobes.h       |  7 ++++++-
 arch/blackfin/include/asm/Kbuild       |  1 +
 arch/c6x/include/asm/Kbuild            |  1 +
 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/kprobes.h        | 12 +++++++++---
 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/kprobes.h        |  6 +++++-
 arch/mn10300/include/asm/kprobes.h     |  7 ++++++-
 arch/nios2/include/asm/Kbuild          |  1 +
 arch/openrisc/include/asm/Kbuild       |  1 +
 arch/parisc/include/asm/Kbuild         |  1 +
 arch/powerpc/include/asm/kprobes.h     |  3 +++
 arch/s390/include/asm/kprobes.h        |  7 ++++++-
 arch/score/include/asm/Kbuild          |  1 +
 arch/sh/include/asm/kprobes.h          |  5 ++++-
 arch/sparc/include/asm/kprobes.h       | 10 ++++++++--
 arch/tile/include/asm/kprobes.h        |  6 +++++-
 arch/um/include/asm/Kbuild             |  1 +
 arch/unicore32/include/asm/Kbuild      |  1 +
 arch/x86/include/asm/kprobes.h         |  9 ++++++++-
 arch/xtensa/include/asm/Kbuild         |  1 +
 include/asm-generic/kprobes.h          | 25 +++++++++++++++++++++++++
 include/linux/compiler.h               |  8 --------
 include/linux/kprobes.h                | 19 +++----------------
 37 files changed, 122 insertions(+), 38 deletions(-)
 create mode 100644 include/asm-generic/kprobes.h

diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index f3bdc31d3c97..54d388fd026f 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += trace_clock.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/arc/include/asm/kprobes.h b/arch/arc/include/asm/kprobes.h
index 944dbedb38b5..00bdbe167615 100644
--- a/arch/arc/include/asm/kprobes.h
+++ b/arch/arc/include/asm/kprobes.h
@@ -9,6 +9,8 @@
 #ifndef _ARC_KPROBES_H
 #define _ARC_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
 #ifdef CONFIG_KPROBES
 
 typedef u16 kprobe_opcode_t;
@@ -55,6 +57,6 @@ void trap_is_kprobe(unsigned long address, struct pt_regs *regs);
 static void trap_is_kprobe(unsigned long address, struct pt_regs *regs)
 {
 }
-#endif
+#endif /* CONFIG_KPROBES */
 
-#endif
+#endif /* _ARC_KPROBES_H */
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index 3ea9be559726..59655459da59 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/notifier.h>
@@ -83,4 +86,5 @@ struct arch_optimized_insn {
 	 */
 };
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm/probes/decode.h b/arch/arm/probes/decode.h
index f9b08ba7fe73..548d622a3159 100644
--- a/arch/arm/probes/decode.h
+++ b/arch/arm/probes/decode.h
@@ -22,6 +22,7 @@
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <asm/probes.h>
+#include <asm/kprobes.h>
 
 void __init arm_probes_decode_init(void);
 
diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
index 1737aecfcc5e..6deb8d726041 100644
--- a/arch/arm64/include/asm/kprobes.h
+++ b/arch/arm64/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -57,4 +60,5 @@ int kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr);
 void kretprobe_trampoline(void);
 void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 94b62c1fa4df..ae912304ed84 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -31,6 +31,7 @@
 #include <asm/debug-monitors.h>
 #include <asm/fixmap.h>
 #include <asm/insn.h>
+#include <asm/kprobes.h>
 
 #define AARCH64_INSN_SF_BIT	BIT(31)
 #define AARCH64_INSN_N_BIT	BIT(22)
diff --git a/arch/arm64/kernel/probes/decode-insn.h b/arch/arm64/kernel/probes/decode-insn.h
index 76d3f315407f..192ab007bacb 100644
--- a/arch/arm64/kernel/probes/decode-insn.h
+++ b/arch/arm64/kernel/probes/decode-insn.h
@@ -16,6 +16,8 @@
 #ifndef _ARM_KERNEL_KPROBES_ARM64_H
 #define _ARM_KERNEL_KPROBES_ARM64_H
 
+#include <asm/kprobes.h>
+
 /*
  * ARM strongly recommends a limit of 128 bytes between LoadExcl and
  * StoreExcl instructions in a single thread of execution. So keep the
diff --git a/arch/avr32/include/asm/kprobes.h b/arch/avr32/include/asm/kprobes.h
index 45f563ed73fd..28dfc61ad384 100644
--- a/arch/avr32/include/asm/kprobes.h
+++ b/arch/avr32/include/asm/kprobes.h
@@ -11,10 +11,14 @@
 #ifndef __ASM_AVR32_KPROBES_H
 #define __ASM_AVR32_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xd673	/* breakpoint */
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 
 typedef u16	kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xd673	/* breakpoint */
 #define MAX_INSN_SIZE		2
 #define MAX_STACK_SIZE		64	/* 32 would probably be OK */
 
@@ -46,4 +50,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif /* __ASM_AVR32_KPROBES_H */
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 9115b215fc7e..52351d3fd36e 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -50,3 +50,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index cede2a950fbf..c54f7cc1f63e 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
+generic-y += kprobes.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 7062c1be7913..051d355feae3 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 4a59cbda5091..b58b9fc49383 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index d79968d93c12..cfca7de52b37 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -78,3 +78,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index d59ac1c1858b..d7cc35451f30 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/ia64/include/asm/kprobes.h b/arch/ia64/include/asm/kprobes.h
index d5505d6f2382..0302b3664789 100644
--- a/arch/ia64/include/asm/kprobes.h
+++ b/arch/ia64/include/asm/kprobes.h
@@ -23,14 +23,19 @@
  * 2005-Apr     Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
  *              <anil.s.keshavamurthy@intel.com> adapted from i386
  */
+#include <asm-generic/kprobes.h>
+#include <asm/break.h>
+
+#define BREAK_INST	(long)(__IA64_BREAK_KPROBE << 6)
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
-#include <asm/break.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
 #define MAX_INSN_SIZE   2	/* last half is for kprobe-booster */
-#define BREAK_INST	(long)(__IA64_BREAK_KPROBE << 6)
 #define NOP_M_INST	(long)(1<<27)
 #define BRL_INST(i1, i2) ((long)((0xcL << 37) |	/* brl */ \
 				(0x1L << 12) |	/* many */ \
@@ -124,4 +129,5 @@ extern void invalidate_stacked_regs(void);
 extern void flush_register_stack(void);
 extern void arch_remove_kprobe(struct kprobe *p);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 24088f3c733c..198ad591ab41 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index c28bcdecc764..412dd23ab946 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -37,3 +37,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index c836f7e2a5e7..8371cc9b1b3c 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -58,3 +58,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index 01afb1b420f5..865ce3d96443 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/mips/include/asm/kprobes.h b/arch/mips/include/asm/kprobes.h
index daba1f9a4f79..291846d9ba83 100644
--- a/arch/mips/include/asm/kprobes.h
+++ b/arch/mips/include/asm/kprobes.h
@@ -22,6 +22,9 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/ptrace.h>
 #include <linux/types.h>
 
@@ -94,4 +97,5 @@ struct kprobe_ctlblk {
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/mn10300/include/asm/kprobes.h b/arch/mn10300/include/asm/kprobes.h
index c800b590183a..7abea0bdb549 100644
--- a/arch/mn10300/include/asm/kprobes.h
+++ b/arch/mn10300/include/asm/kprobes.h
@@ -21,13 +21,17 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xff
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 
 struct kprobe;
 
 typedef unsigned char kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xff
 #define MAX_INSN_SIZE 8
 #define MAX_STACK_SIZE 128
 
@@ -47,4 +51,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 extern void arch_remove_kprobe(struct kprobe *p);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_KPROBES_H */
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index ee6220dac1e8..d6ce7edee7e0 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -66,3 +66,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index ceafe458e295..1bf89a67317c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -74,3 +74,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index aaae8a9f6099..19d5b7e12ecf 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -31,3 +31,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h
index 97b8c1f83453..c7ee3fcbd6e2 100644
--- a/arch/powerpc/include/asm/kprobes.h
+++ b/arch/powerpc/include/asm/kprobes.h
@@ -1,5 +1,8 @@
 #ifndef _ASM_POWERPC_KPROBES_H
 #define _ASM_POWERPC_KPROBES_H
+
+#include <asm-generic/kprobes.h>
+
 #ifdef __KERNEL__
 /*
  *  Kernel Probes (KProbes)
diff --git a/arch/s390/include/asm/kprobes.h b/arch/s390/include/asm/kprobes.h
index 591e5a5279b0..84c0f9086483 100644
--- a/arch/s390/include/asm/kprobes.h
+++ b/arch/s390/include/asm/kprobes.h
@@ -27,6 +27,11 @@
  * 2005-Dec	Used as a template for s390 by Mike Grundy
  *		<grundym@us.ibm.com>
  */
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0x0002
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -37,7 +42,6 @@ struct pt_regs;
 struct kprobe;
 
 typedef u16 kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0x0002
 
 /* Maximum instruction size is 3 (16bit) halfwords: */
 #define MAX_INSN_SIZE		0x0003
@@ -91,4 +95,5 @@ int probe_is_insn_relative_long(u16 *insn);
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif	/* _ASM_S390_KPROBES_H */
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index 16ea15a3e432..6ac8a7f5c768 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -17,3 +17,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h
index 134f3980e44a..f0986f9b3844 100644
--- a/arch/sh/include/asm/kprobes.h
+++ b/arch/sh/include/asm/kprobes.h
@@ -1,13 +1,16 @@
 #ifndef __ASM_SH_KPROBES_H
 #define __ASM_SH_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xc33a
+
 #ifdef CONFIG_KPROBES
 
 #include <linux/types.h>
 #include <linux/ptrace.h>
 
 typedef insn_size_t kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xc33a
 
 #define MAX_INSN_SIZE 16
 #define MAX_STACK_SIZE 64
diff --git a/arch/sparc/include/asm/kprobes.h b/arch/sparc/include/asm/kprobes.h
index a145d798e112..49f8402035d7 100644
--- a/arch/sparc/include/asm/kprobes.h
+++ b/arch/sparc/include/asm/kprobes.h
@@ -1,13 +1,17 @@
 #ifndef _SPARC64_KPROBES_H
 #define _SPARC64_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION   0x91d02070 /* ta 0x70 */
+#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/percpu.h>
 
 typedef u32 kprobe_opcode_t;
 
-#define BREAKPOINT_INSTRUCTION   0x91d02070 /* ta 0x70 */
-#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
 #define MAX_INSN_SIZE 2
 
 #define kretprobe_blacklist_size 0
@@ -48,4 +52,6 @@ int kprobe_exceptions_notify(struct notifier_block *self,
 int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
 				      struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _SPARC64_KPROBES_H */
diff --git a/arch/tile/include/asm/kprobes.h b/arch/tile/include/asm/kprobes.h
index d8f9a83943b1..4a8b1cadca24 100644
--- a/arch/tile/include/asm/kprobes.h
+++ b/arch/tile/include/asm/kprobes.h
@@ -17,10 +17,13 @@
 #ifndef _ASM_TILE_KPROBES_H
 #define _ASM_TILE_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
-
 #include <arch/opcode.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
@@ -76,4 +79,5 @@ void arch_remove_kprobe(struct kprobe *);
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 			     unsigned long val, void *data);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_TILE_KPROBES_H */
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index d2867aa09e23..ccc5ffeaeef5 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 6671a1f08ead..5aacafb6d385 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h
index d1d1e5094c28..200581691c6e 100644
--- a/arch/x86/include/asm/kprobes.h
+++ b/arch/x86/include/asm/kprobes.h
@@ -21,6 +21,12 @@
  *
  * See arch/x86/kernel/kprobes.c for x86 kprobes history.
  */
+
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xcc
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -32,7 +38,6 @@ struct pt_regs;
 struct kprobe;
 
 typedef u8 kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xcc
 #define RELATIVEJUMP_OPCODE 0xe9
 #define RELATIVEJUMP_SIZE 5
 #define RELATIVECALL_OPCODE 0xe8
@@ -116,4 +121,6 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 extern int kprobe_int3_handler(struct pt_regs *regs);
 extern int kprobe_debug_handler(struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_X86_KPROBES_H */
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index 7b41f32a2ba0..20f524ded00e 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
new file mode 100644
index 000000000000..57af9f21d148
--- /dev/null
+++ b/include/asm-generic/kprobes.h
@@ -0,0 +1,25 @@
+#ifndef _ASM_GENERIC_KPROBES_H
+#define _ASM_GENERIC_KPROBES_H
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#ifdef CONFIG_KPROBES
+/*
+ * Blacklist ganerating macro. Specify functions which is not probed
+ * by using this macro.
+ */
+# define __NOKPROBE_SYMBOL(fname)				\
+static unsigned long __used					\
+	__attribute__((__section__("_kprobe_blacklist")))	\
+	_kbl_addr_##fname = (unsigned long)fname;
+# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
+/* Use this to forbid a kprobes attach on very low level functions */
+# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define nokprobe_inline	__always_inline
+#else
+# define NOKPROBE_SYMBOL(fname)
+# define __kprobes
+# define nokprobe_inline	inline
+#endif
+#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
+
+#endif /* _ASM_GENERIC_KPROBES_H */
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index cf0fa5d86059..dca49b4099da 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -566,12 +566,4 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 	(_________p1); \
 })
 
-/* Ignore/forbid kprobes attach on very low level functions marked by this attribute: */
-#ifdef CONFIG_KPROBES
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
-# define nokprobe_inline	__always_inline
-#else
-# define __kprobes
-# define nokprobe_inline	inline
-#endif
 #endif /* __LINUX_COMPILER_H */
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 8f6849084248..985ed79ef431 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -29,7 +29,7 @@
  *		<jkenisto@us.ibm.com>  and Prasanna S Panchamukhi
  *		<prasanna@in.ibm.com> added function-return probes.
  */
-#include <linux/compiler.h>	/* for __kprobes */
+#include <linux/compiler.h>
 #include <linux/linkage.h>
 #include <linux/list.h>
 #include <linux/notifier.h>
@@ -40,9 +40,9 @@
 #include <linux/rcupdate.h>
 #include <linux/mutex.h>
 #include <linux/ftrace.h>
+#include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
-#include <asm/kprobes.h>
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
@@ -51,6 +51,7 @@
 #define KPROBE_HIT_SSDONE	0x00000008
 
 #else /* CONFIG_KPROBES */
+#include <asm-generic/kprobes.h>
 typedef int kprobe_opcode_t;
 struct arch_specific_insn {
 	int dummy;
@@ -481,18 +482,4 @@ static inline int enable_jprobe(struct jprobe *jp)
 	return enable_kprobe(&jp->kp);
 }
 
-#ifdef CONFIG_KPROBES
-/*
- * Blacklist ganerating macro. Specify functions which is not probed
- * by using this macro.
- */
-#define __NOKPROBE_SYMBOL(fname)			\
-static unsigned long __used				\
-	__attribute__((section("_kprobe_blacklist")))	\
-	_kbl_addr_##fname = (unsigned long)fname;
-#define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
-#else
-#define NOKPROBE_SYMBOL(fname)
-#endif
-
 #endif /* _LINUX_KPROBES_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 12/14] kprobes: port .kprobes.text to section range
  2017-01-09 14:58       ` Luis R. Rodriguez
  (?)
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt

kprobe makes use of two custom sections, each custom section
is folded into one of the standard Linux sections types as follows,
it currently relies on the linker script to fold the custom section
onto the respective Linux section:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist
range .text         .kprobes.text        __kprobes_text_start     __kprobes_text_end

This ports the .kprobes.text custom section to the standard
Linux ranges API allowing us remove all the custom kprobe section
declarations from the linker script.

Tested with CONFIG_KPROBES_SANITY_TEST, it passes with:

Kprobe smoke test: started
Kprobe smoke test: passed successfully

Then tested CONFIG_SAMPLE_KPROBES on do_fork, and the kprobe bites
and kicks as expected.

Also ran ./ftracetest with no issues:

sudo ./ftracetest
== Ftrace unit tests =[1] Basic trace file check	[PASS]
[2] Basic test for tracers	[PASS]
[3] Basic trace clock test	[PASS]
[4] Basic event tracing check	[PASS]
[5] event tracing - enable/disable with event level files	[PASS]
[6] event tracing - restricts events based on pid	[PASS]
[7] event tracing - enable/disable with subsystem level files	[PASS]
[8] event tracing - enable/disable with top level files	[PASS]
[9] ftrace - function graph filters with stack tracer	[PASS]
[10] ftrace - function graph filters	[PASS]
[11] ftrace - function glob filters	[PASS]
[12] ftrace - function profiler with function tracing	[PASS]
[13] Test creation and deletion of trace instances while setting an event	[PASS]
[14] Test creation and deletion of trace instances	[PASS]
[15] Kprobe dynamic event - adding and removing	[PASS]
[16] Kprobe dynamic event - busy event check	[PASS]
[17] Kprobe dynamic event with arguments	[PASS]
[18] Kprobes event arguments with types	[PASS]
[19] Kprobe dynamic event with function tracer	[PASS]
[20] Kretprobe dynamic event with arguments	[PASS]
[21] event trigger - test event enable/disable trigger	[PASS]
[22] event trigger - test trigger filter	[PASS]
[23] event trigger - test histogram modifiers	[PASS]
[24] event trigger - test histogram trigger	[PASS]
[25] event trigger - test multiple histogram triggers	[PASS]
[26] event trigger - test snapshot-trigger	[PASS]
[27] event trigger - test stacktrace-trigger	[PASS]
[28] event trigger - test traceon/off trigger	[PASS]

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

v4:

o arm64 build fixes with allmodconfig

o build fix suggested for avr32 with allnoconfig, otherwise we end up with:

arch/avr32/kernel/built-in.o: In function `save_full_context_ex':
(.ex.text+0x1c4): relocation truncated to fit: R_AVR32_16N_PCREL against
symbol `debug_trampoline' defined in .text.rng.kprobes.any section in
arch/avr32/kernel/built-in.o
arch/avr32/kernel/built-in.o: In function `debug_exit_work':
(.text.rng.kprobes.any+0xa8): relocation truncated to fit:
R_AVR32_16N_PCREL against `.ex.text'+3aa
make: *** [Makefile:953: vmlinux] Error 1

o open-code section use on scripts/ code -- folks to prefer the
  simplicity over dealing with having more tool code access kernel
  headers.

o NOPE: include #include <asm-generic/ranges.h> on compiler.h -- solves
  a few 0-day compilation issues

v3:

o after v2 arch/arm/kernel/vmlinux-xip.lds.S got kprobe support,
  this just removes the custom linker script reference to kprobes as
  that is no longer needed with linker tables.

o split kprobe linker table and kprobe section ranges use into
  two separate patches. This should make it easier to review and
  also demos both distinct use types, one a linker table another
  a simple section range.

v2: introduced this patch in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arc/kernel/vmlinux.lds.S        |  1 -
 arch/arm/kernel/entry-armv.S         |  3 ++-
 arch/arm/kernel/vmlinux-xip.lds.S    |  1 -
 arch/arm/kernel/vmlinux.lds.S        |  1 -
 arch/arm64/kernel/armv8_deprecated.c |  1 +
 arch/arm64/kernel/probes/kprobes.c   |  4 ++--
 arch/arm64/kernel/vmlinux.lds.S      |  1 -
 arch/avr32/kernel/entry-avr32b.S     | 13 +++++++++++--
 arch/avr32/kernel/vmlinux.lds.S      |  1 -
 arch/blackfin/kernel/vmlinux.lds.S   |  1 -
 arch/c6x/kernel/vmlinux.lds.S        |  1 -
 arch/hexagon/kernel/vmlinux.lds.S    |  1 -
 arch/ia64/kernel/jprobes.S           |  3 ++-
 arch/ia64/kernel/vmlinux.lds.S       |  1 -
 arch/ia64/lib/flush.S                |  6 +++---
 arch/metag/kernel/vmlinux.lds.S      |  1 -
 arch/microblaze/kernel/vmlinux.lds.S |  1 -
 arch/mips/kernel/vmlinux.lds.S       |  1 -
 arch/mn10300/kernel/vmlinux.lds.S    |  1 -
 arch/nios2/kernel/vmlinux.lds.S      |  1 -
 arch/openrisc/kernel/vmlinux.lds.S   |  1 -
 arch/parisc/kernel/vmlinux.lds.S     |  1 -
 arch/powerpc/include/asm/ppc_asm.h   |  1 +
 arch/powerpc/kernel/vmlinux.lds.S    |  1 -
 arch/s390/kernel/entry.S             |  5 +++--
 arch/s390/kernel/kprobes.c           |  6 +++---
 arch/s390/kernel/mcount.S            |  3 ++-
 arch/s390/kernel/vmlinux.lds.S       |  1 -
 arch/score/kernel/vmlinux.lds.S      |  1 -
 arch/sh/kernel/vmlinux.lds.S         |  1 -
 arch/sparc/kernel/vmlinux.lds.S      |  1 -
 arch/sparc/mm/ultra.S                |  3 ++-
 arch/tile/kernel/vmlinux.lds.S       |  1 -
 arch/x86/kernel/kprobes/core.c       | 11 +++++------
 arch/x86/kernel/vmlinux.lds.S        |  1 -
 include/asm-generic/kprobes.h        |  3 ++-
 include/asm-generic/sections.h       |  2 --
 include/asm-generic/vmlinux.lds.h    |  2 +-
 include/linux/kprobes.h              |  3 +++
 kernel/kprobes.c                     |  6 ++++--
 scripts/mod/modpost.c                |  2 +-
 scripts/recordmcount.c               |  2 +-
 scripts/recordmcount.pl              |  2 +-
 43 files changed, 50 insertions(+), 54 deletions(-)

diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S
index f35ed578e007..dd05c86eb96e 100644
--- a/arch/arc/kernel/vmlinux.lds.S
+++ b/arch/arc/kernel/vmlinux.lds.S
@@ -91,7 +91,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 9f157e7c51e7..c455b491b6d3 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -34,6 +34,7 @@
 #include "entry-header.S"
 #include <asm/entry-macro-multi.S>
 #include <asm/probes.h>
+#include <asm/ranges.h>
 
 /*
  * Interrupt handling.
@@ -83,7 +84,7 @@
 	.endm
 
 #ifdef CONFIG_KPROBES
-	.section	.kprobes.text,"ax",%progbits
+	set_section_rng_type(.text, kprobes, ax, %progbits)
 #else
 	.text
 #endif
diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S
index 37b2a11af345..1a84f84b8165 100644
--- a/arch/arm/kernel/vmlinux-xip.lds.S
+++ b/arch/arm/kernel/vmlinux-xip.lds.S
@@ -103,7 +103,6 @@ SECTIONS
 			SCHED_TEXT
 			CPUIDLE_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index f7f55df0bf7b..1e278e6c3506 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -114,7 +114,6 @@ SECTIONS
 			CPUIDLE_TEXT
 			LOCK_TEXT
 			HYPERVISOR_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index ecf9298a12d4..35574b9fe6d4 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -21,6 +21,7 @@
 #include <asm/traps.h>
 #include <linux/uaccess.h>
 #include <asm/cpufeature.h>
+#include <asm/kprobes.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace-events-emulation.h"
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index f0593c92279b..ec288dd165cb 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/stop_machine.h>
 #include <linux/stringify.h>
+#include <linux/ranges.h>
 #include <asm/traps.h>
 #include <asm/ptrace.h>
 #include <asm/cacheflush.h>
@@ -540,8 +541,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
-	if ((addr >= (unsigned long)__kprobes_text_start &&
-	    addr < (unsigned long)__kprobes_text_end) ||
+	if (SECTION_RANGE_ADDR_WITHIN(kprobes, addr) ||
 	    (addr >= (unsigned long)__entry_text_start &&
 	    addr < (unsigned long)__entry_text_end) ||
 	    (addr >= (unsigned long)__idmap_text_start &&
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index b8deffa9e1bf..c68e5d528706 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -124,7 +124,6 @@ SECTIONS
 			SCHED_TEXT
 			CPUIDLE_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			HYPERVISOR_TEXT
 			IDMAP_TEXT
 			HIBERNATE_TEXT
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index 7301f4806bbe..7b2a5c5ef047 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -23,6 +23,7 @@
 #include <asm/sysreg.h>
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
+#include <asm/ranges.h>
 
 #ifdef CONFIG_PREEMPT
 # define preempt_stop		mask_interrupts
@@ -605,7 +606,11 @@ fault_exit_work:
 	brcc	fault_resume_user
 	rjmp	enter_monitor_mode
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(.text, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	handle_debug, @function
 handle_debug:
 	sub	sp, 4		/* r12_orig */
@@ -826,7 +831,11 @@ irq_level\level:
 	IRQ_LEVEL 2
 	IRQ_LEVEL 3
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(.text, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	enter_monitor_mode, @function
 enter_monitor_mode:
 	/*
diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S
index 17f2730eb497..04627a9c178e 100644
--- a/arch/avr32/kernel/vmlinux.lds.S
+++ b/arch/avr32/kernel/vmlinux.lds.S
@@ -49,7 +49,6 @@ SECTIONS
 		_stext = .;
 		*(.ex.text)
 		*(.irq.text)
-		KPROBES_TEXT
 		TEXT_TEXT
 		SCHED_TEXT
 		CPUIDLE_TEXT
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 68069a120055..93220ff65014 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -37,7 +37,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 #ifdef CONFIG_ROMKERNEL
 		__sinittext = .;
 		INIT_TEXT
diff --git a/arch/c6x/kernel/vmlinux.lds.S b/arch/c6x/kernel/vmlinux.lds.S
index a1a5c166bc9b..a41d43b8254b 100644
--- a/arch/c6x/kernel/vmlinux.lds.S
+++ b/arch/c6x/kernel/vmlinux.lds.S
@@ -74,7 +74,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S
index ec87e67feb19..7e6f68584b55 100644
--- a/arch/hexagon/kernel/vmlinux.lds.S
+++ b/arch/hexagon/kernel/vmlinux.lds.S
@@ -52,7 +52,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 	}
 	_etext = .;
diff --git a/arch/ia64/kernel/jprobes.S b/arch/ia64/kernel/jprobes.S
index f69389c7be1d..71adc7132e22 100644
--- a/arch/ia64/kernel/jprobes.S
+++ b/arch/ia64/kernel/jprobes.S
@@ -46,11 +46,12 @@
  */
 #include <asm/asmmacro.h>
 #include <asm/break.h>
+#include <asm/ranges.h>
 
 	/*
 	 * void jprobe_break(void)
 	 */
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 ENTRY(jprobe_break)
 	break.m __IA64_BREAK_JPROBE
 END(jprobe_break)
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index f89d20c97412..3ff6edf913d2 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -48,7 +48,6 @@ SECTIONS {
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.gnu.linkonce.t*)
 	}
 
diff --git a/arch/ia64/lib/flush.S b/arch/ia64/lib/flush.S
index 9a5a2f9fad13..dec1b180d618 100644
--- a/arch/ia64/lib/flush.S
+++ b/arch/ia64/lib/flush.S
@@ -9,7 +9,7 @@
 
 #include <asm/asmmacro.h>
 #include <asm/export.h>
-
+#include <asm/ranges.h>
 
 	/*
 	 * flush_icache_range(start,end)
@@ -21,7 +21,7 @@
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(.text, kprobes, ax)
 GLOBAL_ENTRY(flush_icache_range)
 
 	.prologue
@@ -74,7 +74,7 @@ EXPORT_SYMBOL_GPL(flush_icache_range)
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(.text, kprobes, ax)
 GLOBAL_ENTRY(clflush_cache_range)
 
 	.prologue
diff --git a/arch/metag/kernel/vmlinux.lds.S b/arch/metag/kernel/vmlinux.lds.S
index e6c700eaf207..b18386d2250f 100644
--- a/arch/metag/kernel/vmlinux.lds.S
+++ b/arch/metag/kernel/vmlinux.lds.S
@@ -23,7 +23,6 @@ SECTIONS
 	SCHED_TEXT
 	CPUIDLE_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	IRQENTRY_TEXT
 	SOFTIRQENTRY_TEXT
 	*(.text.*)
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
index 289d0e7f3e3a..aadee2229ac6 100644
--- a/arch/microblaze/kernel/vmlinux.lds.S
+++ b/arch/microblaze/kernel/vmlinux.lds.S
@@ -35,7 +35,6 @@ SECTIONS {
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		. = ALIGN (4) ;
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index f0a0e6d62be3..44e21812c544 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -57,7 +57,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.*)
diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S
index 2d5f1c3f1afb..552ef00a3da5 100644
--- a/arch/mn10300/kernel/vmlinux.lds.S
+++ b/arch/mn10300/kernel/vmlinux.lds.S
@@ -32,7 +32,6 @@ SECTIONS
 	SCHED_TEXT
 	CPUIDLE_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0xcb
diff --git a/arch/nios2/kernel/vmlinux.lds.S b/arch/nios2/kernel/vmlinux.lds.S
index 6a8045bb1a77..aae4a00c4056 100644
--- a/arch/nios2/kernel/vmlinux.lds.S
+++ b/arch/nios2/kernel/vmlinux.lds.S
@@ -41,7 +41,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 	} =0
 	_etext = .;
 
diff --git a/arch/openrisc/kernel/vmlinux.lds.S b/arch/openrisc/kernel/vmlinux.lds.S
index 00ddb7804be4..8ade6ccca6ac 100644
--- a/arch/openrisc/kernel/vmlinux.lds.S
+++ b/arch/openrisc/kernel/vmlinux.lds.S
@@ -57,7 +57,6 @@ SECTIONS
 	  SCHED_TEXT
 	  CPUIDLE_TEXT
 	  LOCK_TEXT
-	  KPROBES_TEXT
 	  IRQENTRY_TEXT
 	  SOFTIRQENTRY_TEXT
 	  *(.fixup)
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 3d6ef1b29c6a..edbd6d9487dc 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -71,7 +71,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.do_softirq)
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 025833b8df9f..0846413b3a2e 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,6 +9,7 @@
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
 #include <asm/firmware.h>
+#include <asm/ranges.h>
 
 #ifdef __ASSEMBLY__
 
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 8cd940c72895..2285664abb52 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -112,7 +112,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		MEM_KEEP(init.text)
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 97298c58b2be..847e2e1df89c 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -24,6 +24,7 @@
 #include <asm/setup.h>
 #include <asm/nmi.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
 __PT_R0      =	__PT_GPRS
 __PT_R1      =	__PT_GPRS + 8
@@ -169,7 +170,7 @@ _PIF_WORK	= (_PIF_PER_TRAP)
 		tm	off+\addr, \mask
 	.endm
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 .Ldummy:
 	/*
 	 * This nop exists only in order to avoid that __switch_to starts at
@@ -986,7 +987,7 @@ ENTRY(restart_int_handler)
 	brc	2,2b
 3:	j	3b
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 
 #ifdef CONFIG_CHECK_STACK
 /*
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 84e0557b16fe..94a4918b5968 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -289,9 +289,9 @@ static void kprobe_reenter_check(struct kprobe_ctlblk *kcb, struct kprobe *p)
 	case KPROBE_REENTER:
 	default:
 		/*
-		 * A kprobe on the code path to single step an instruction
-		 * is a BUG. The code path resides in the .kprobes.text
-		 * section and is executed with interrupts disabled.
+		 * A kprobe on the code path to single step an instruction is a
+		 * BUG. The code path resides in the kprobes section range and
+		 * is executed with interrupts disabled.
 		 */
 		printk(KERN_EMERG "Invalid kprobe detected at %p.\n", p->addr);
 		dump_kprobe(p);
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S
index 9a17e4475d27..9d76056609f7 100644
--- a/arch/s390/kernel/mcount.S
+++ b/arch/s390/kernel/mcount.S
@@ -10,8 +10,9 @@
 #include <asm/ftrace.h>
 #include <asm/ptrace.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 
 ENTRY(ftrace_stub)
 	br	%r14
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 3667d20e997f..b2df6d9bab09 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -37,7 +37,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/score/kernel/vmlinux.lds.S b/arch/score/kernel/vmlinux.lds.S
index 4117890b1db1..a8b14f3ed474 100644
--- a/arch/score/kernel/vmlinux.lds.S
+++ b/arch/score/kernel/vmlinux.lds.S
@@ -42,7 +42,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.text.*)
 		*(.fixup)
 		. = ALIGN (4) ;
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 5b9a3cc90c58..58d9ba796f7a 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -38,7 +38,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 572db686f845..0ee41b0071e5 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -51,7 +51,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.gnu.warning)
diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S
index 5d2fd6cd3189..ee9f648549c0 100644
--- a/arch/sparc/mm/ultra.S
+++ b/arch/sparc/mm/ultra.S
@@ -16,6 +16,7 @@
 #include <asm/cacheflush.h>
 #include <asm/hypervisor.h>
 #include <asm/cpudata.h>
+#include <asm/ranges.h>
 
 	/* Basically, most of the Spitfire vs. Cheetah madness
 	 * has to do with the fact that Cheetah does not support
@@ -185,7 +186,7 @@ __spitfire_flush_tlb_mm_slow:
 /*
  * The following code flushes one page_size worth.
  */
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 	.align		32
 	.globl		__flush_icache_page
 __flush_icache_page:	/* %o0 = phys_page */
diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S
index e1baf094fba4..85d03ce6c0a0 100644
--- a/arch/tile/kernel/vmlinux.lds.S
+++ b/arch/tile/kernel/vmlinux.lds.S
@@ -44,7 +44,6 @@ SECTIONS
     SCHED_TEXT
     CPUIDLE_TEXT
     LOCK_TEXT
-    KPROBES_TEXT
     IRQENTRY_TEXT
     SOFTIRQENTRY_TEXT
     __fix_text_end = .;   /* tile-cpack won't rearrange before this */
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index eb3509338ae0..95e4b172e923 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -580,9 +580,9 @@ static int reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
 	case KPROBE_REENTER:
 		/* A probe has been hit in the codepath leading up to, or just
 		 * after, single-stepping of a probed instruction. This entire
-		 * codepath should strictly reside in .kprobes.text section.
-		 * Raise a BUG or we'll continue in an endless reentering loop
-		 * and eventually a stack overflow.
+		 * codepath should strictly reside in the kprobes section
+		 * range. Raise a BUG or we'll continue in an endless
+		 * reentering loop and eventually a stack overflow.
 		 */
 		printk(KERN_WARNING "Unrecoverable kprobe detected at %p.\n",
 		       p->addr);
@@ -1133,10 +1133,9 @@ NOKPROBE_SYMBOL(longjmp_break_handler);
 
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
-	return  (addr >= (unsigned long)__kprobes_text_start &&
-		 addr < (unsigned long)__kprobes_text_end) ||
+	return  (SECTION_RANGE_ADDR_WITHIN(kprobes, addr) ||
 		(addr >= (unsigned long)__entry_text_start &&
-		 addr < (unsigned long)__entry_text_end);
+		 addr < (unsigned long)__entry_text_end));
 }
 
 int __init arch_init_kprobes(void)
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index e79f15f108a8..4c16fadb9ac6 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -99,7 +99,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		ENTRY_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 57af9f21d148..02a26b975187 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,6 +3,7 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
@@ -13,7 +14,7 @@ static unsigned long __used					\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define __kprobes	__LINUX_RANGE(.text, kprobes)
 # define nokprobe_inline	__always_inline
 #else
 # define NOKPROBE_SYMBOL(fname)
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index b145ae8d9cbe..f3340f2772bb 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -26,7 +26,6 @@
  * Following global variables are optional and may be unavailable on some
  * architectures and/or kernel configurations.
  *	_text, _data
- *	__kprobes_text_start, __kprobes_text_end
  *	__entry_text_start, __entry_text_end
  *	__ctors_start, __ctors_end
  */
@@ -38,7 +37,6 @@ extern char _sinittext[], _einittext[];
 extern char __start_data_ro_after_init[], __end_data_ro_after_init[];
 extern char _end[];
 extern char __per_cpu_load[], __per_cpu_start[], __per_cpu_end[];
-extern char __kprobes_text_start[], __kprobes_text_end[];
 extern char __entry_text_start[], __entry_text_end[];
 extern char __start_rodata[], __end_rodata[];
 
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 37b99537d5a9..499caf5b4361 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -471,7 +471,7 @@
 #define KPROBES_TEXT							\
 		ALIGN_FUNCTION();					\
 		VMLINUX_SYMBOL(__kprobes_text_start) = .;		\
-		*(.kprobes.text)					\
+		*(.text..rng.kprobes.any)				\
 		VMLINUX_SYMBOL(__kprobes_text_end) = .;
 
 #define ENTRY_TEXT							\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 985ed79ef431..445cc6fe7afa 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -43,6 +43,9 @@
 #include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
+#include <linux/ranges.h>
+
+DECLARE_SECTION_RANGE(kprobes);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 43460104f119..82191f328e21 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1328,8 +1328,7 @@ static int register_aggr_kprobe(struct kprobe *orig_p, struct kprobe *p)
 bool __weak arch_within_kprobe_blacklist(unsigned long addr)
 {
 	/* The __kprobes marked functions and entry code must not be probed */
-	return addr >= (unsigned long)__kprobes_text_start &&
-	       addr < (unsigned long)__kprobes_text_end;
+	return SECTION_RANGE_ADDR_WITHIN(kprobes, addr);
 }
 
 bool within_kprobe_blacklist(unsigned long addr)
@@ -2129,6 +2128,9 @@ static struct notifier_block kprobe_module_nb = {
 extern unsigned long __start_kprobe_blacklist[];
 extern unsigned long __stop_kprobe_blacklist[];
 
+/* Actual kprobes section range */
+DEFINE_SECTION_RANGE(kprobes, .text);
+
 static int __init init_kprobes(void)
 {
 	int i, err = 0;
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 29c89a6bad3d..2b442234c69b 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -894,7 +894,7 @@ static void check_section(const char *modname, struct elf_info *elf,
 
 #define DATA_SECTIONS ".data", ".data.rel"
 #define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \
-		".kprobes.text", ".cpuidle.text"
+		".text..rng.kprobes.any", ".cpuidle.text"
 #define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
 		".fixup", ".entry.text", ".exception.text", ".text.*", \
 		".coldtext"
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index aeb34223167c..6e95f3f87db1 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -417,7 +417,7 @@ is_mcounted_section_name(char const *const txtname)
 		strcmp(".spinlock.text", txtname) = 0 ||
 		strcmp(".irqentry.text", txtname) = 0 ||
 		strcmp(".softirqentry.text", txtname) = 0 ||
-		strcmp(".kprobes.text", txtname) = 0 ||
+		strcmp(".text..rng.kprobes.any", txtname) = 0 ||
 		strcmp(".cpuidle.text", txtname) = 0 ||
 		strcmp(".text.unlikely", txtname) = 0;
 }
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 0b6002b36f20..15e2fa37c489 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -135,7 +135,7 @@ my %text_sections = (
      ".spinlock.text" => 1,
      ".irqentry.text" => 1,
      ".softirqentry.text" => 1,
-     ".kprobes.text" => 1,
+     ".text..rng.kprobes.any" => 1,
      ".cpuidle.text" => 1,
      ".text.unlikely" => 1,
 );
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 12/14] kprobes: port .kprobes.text to section range
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt, ak

kprobe makes use of two custom sections, each custom section
is folded into one of the standard Linux sections types as follows,
it currently relies on the linker script to fold the custom section
onto the respective Linux section:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist
range .text         .kprobes.text        __kprobes_text_start     __kprobes_text_end

This ports the .kprobes.text custom section to the standard
Linux ranges API allowing us remove all the custom kprobe section
declarations from the linker script.

Tested with CONFIG_KPROBES_SANITY_TEST, it passes with:

Kprobe smoke test: started
Kprobe smoke test: passed successfully

Then tested CONFIG_SAMPLE_KPROBES on do_fork, and the kprobe bites
and kicks as expected.

Also ran ./ftracetest with no issues:

sudo ./ftracetest
=== Ftrace unit tests ===
[1] Basic trace file check	[PASS]
[2] Basic test for tracers	[PASS]
[3] Basic trace clock test	[PASS]
[4] Basic event tracing check	[PASS]
[5] event tracing - enable/disable with event level files	[PASS]
[6] event tracing - restricts events based on pid	[PASS]
[7] event tracing - enable/disable with subsystem level files	[PASS]
[8] event tracing - enable/disable with top level files	[PASS]
[9] ftrace - function graph filters with stack tracer	[PASS]
[10] ftrace - function graph filters	[PASS]
[11] ftrace - function glob filters	[PASS]
[12] ftrace - function profiler with function tracing	[PASS]
[13] Test creation and deletion of trace instances while setting an event	[PASS]
[14] Test creation and deletion of trace instances	[PASS]
[15] Kprobe dynamic event - adding and removing	[PASS]
[16] Kprobe dynamic event - busy event check	[PASS]
[17] Kprobe dynamic event with arguments	[PASS]
[18] Kprobes event arguments with types	[PASS]
[19] Kprobe dynamic event with function tracer	[PASS]
[20] Kretprobe dynamic event with arguments	[PASS]
[21] event trigger - test event enable/disable trigger	[PASS]
[22] event trigger - test trigger filter	[PASS]
[23] event trigger - test histogram modifiers	[PASS]
[24] event trigger - test histogram trigger	[PASS]
[25] event trigger - test multiple histogram triggers	[PASS]
[26] event trigger - test snapshot-trigger	[PASS]
[27] event trigger - test stacktrace-trigger	[PASS]
[28] event trigger - test traceon/off trigger	[PASS]

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

v4:

o arm64 build fixes with allmodconfig

o build fix suggested for avr32 with allnoconfig, otherwise we end up with:

arch/avr32/kernel/built-in.o: In function `save_full_context_ex':
(.ex.text+0x1c4): relocation truncated to fit: R_AVR32_16N_PCREL against
symbol `debug_trampoline' defined in .text.rng.kprobes.any section in
arch/avr32/kernel/built-in.o
arch/avr32/kernel/built-in.o: In function `debug_exit_work':
(.text.rng.kprobes.any+0xa8): relocation truncated to fit:
R_AVR32_16N_PCREL against `.ex.text'+3aa
make: *** [Makefile:953: vmlinux] Error 1

o open-code section use on scripts/ code -- folks to prefer the
  simplicity over dealing with having more tool code access kernel
  headers.

o NOPE: include #include <asm-generic/ranges.h> on compiler.h -- solves
  a few 0-day compilation issues

v3:

o after v2 arch/arm/kernel/vmlinux-xip.lds.S got kprobe support,
  this just removes the custom linker script reference to kprobes as
  that is no longer needed with linker tables.

o split kprobe linker table and kprobe section ranges use into
  two separate patches. This should make it easier to review and
  also demos both distinct use types, one a linker table another
  a simple section range.

v2: introduced this patch in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arc/kernel/vmlinux.lds.S        |  1 -
 arch/arm/kernel/entry-armv.S         |  3 ++-
 arch/arm/kernel/vmlinux-xip.lds.S    |  1 -
 arch/arm/kernel/vmlinux.lds.S        |  1 -
 arch/arm64/kernel/armv8_deprecated.c |  1 +
 arch/arm64/kernel/probes/kprobes.c   |  4 ++--
 arch/arm64/kernel/vmlinux.lds.S      |  1 -
 arch/avr32/kernel/entry-avr32b.S     | 13 +++++++++++--
 arch/avr32/kernel/vmlinux.lds.S      |  1 -
 arch/blackfin/kernel/vmlinux.lds.S   |  1 -
 arch/c6x/kernel/vmlinux.lds.S        |  1 -
 arch/hexagon/kernel/vmlinux.lds.S    |  1 -
 arch/ia64/kernel/jprobes.S           |  3 ++-
 arch/ia64/kernel/vmlinux.lds.S       |  1 -
 arch/ia64/lib/flush.S                |  6 +++---
 arch/metag/kernel/vmlinux.lds.S      |  1 -
 arch/microblaze/kernel/vmlinux.lds.S |  1 -
 arch/mips/kernel/vmlinux.lds.S       |  1 -
 arch/mn10300/kernel/vmlinux.lds.S    |  1 -
 arch/nios2/kernel/vmlinux.lds.S      |  1 -
 arch/openrisc/kernel/vmlinux.lds.S   |  1 -
 arch/parisc/kernel/vmlinux.lds.S     |  1 -
 arch/powerpc/include/asm/ppc_asm.h   |  1 +
 arch/powerpc/kernel/vmlinux.lds.S    |  1 -
 arch/s390/kernel/entry.S             |  5 +++--
 arch/s390/kernel/kprobes.c           |  6 +++---
 arch/s390/kernel/mcount.S            |  3 ++-
 arch/s390/kernel/vmlinux.lds.S       |  1 -
 arch/score/kernel/vmlinux.lds.S      |  1 -
 arch/sh/kernel/vmlinux.lds.S         |  1 -
 arch/sparc/kernel/vmlinux.lds.S      |  1 -
 arch/sparc/mm/ultra.S                |  3 ++-
 arch/tile/kernel/vmlinux.lds.S       |  1 -
 arch/x86/kernel/kprobes/core.c       | 11 +++++------
 arch/x86/kernel/vmlinux.lds.S        |  1 -
 include/asm-generic/kprobes.h        |  3 ++-
 include/asm-generic/sections.h       |  2 --
 include/asm-generic/vmlinux.lds.h    |  2 +-
 include/linux/kprobes.h              |  3 +++
 kernel/kprobes.c                     |  6 ++++--
 scripts/mod/modpost.c                |  2 +-
 scripts/recordmcount.c               |  2 +-
 scripts/recordmcount.pl              |  2 +-
 43 files changed, 50 insertions(+), 54 deletions(-)

diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S
index f35ed578e007..dd05c86eb96e 100644
--- a/arch/arc/kernel/vmlinux.lds.S
+++ b/arch/arc/kernel/vmlinux.lds.S
@@ -91,7 +91,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 9f157e7c51e7..c455b491b6d3 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -34,6 +34,7 @@
 #include "entry-header.S"
 #include <asm/entry-macro-multi.S>
 #include <asm/probes.h>
+#include <asm/ranges.h>
 
 /*
  * Interrupt handling.
@@ -83,7 +84,7 @@
 	.endm
 
 #ifdef CONFIG_KPROBES
-	.section	.kprobes.text,"ax",%progbits
+	set_section_rng_type(.text, kprobes, ax, %progbits)
 #else
 	.text
 #endif
diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S
index 37b2a11af345..1a84f84b8165 100644
--- a/arch/arm/kernel/vmlinux-xip.lds.S
+++ b/arch/arm/kernel/vmlinux-xip.lds.S
@@ -103,7 +103,6 @@ SECTIONS
 			SCHED_TEXT
 			CPUIDLE_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index f7f55df0bf7b..1e278e6c3506 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -114,7 +114,6 @@ SECTIONS
 			CPUIDLE_TEXT
 			LOCK_TEXT
 			HYPERVISOR_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index ecf9298a12d4..35574b9fe6d4 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -21,6 +21,7 @@
 #include <asm/traps.h>
 #include <linux/uaccess.h>
 #include <asm/cpufeature.h>
+#include <asm/kprobes.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace-events-emulation.h"
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index f0593c92279b..ec288dd165cb 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/stop_machine.h>
 #include <linux/stringify.h>
+#include <linux/ranges.h>
 #include <asm/traps.h>
 #include <asm/ptrace.h>
 #include <asm/cacheflush.h>
@@ -540,8 +541,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
-	if ((addr >= (unsigned long)__kprobes_text_start &&
-	    addr < (unsigned long)__kprobes_text_end) ||
+	if (SECTION_RANGE_ADDR_WITHIN(kprobes, addr) ||
 	    (addr >= (unsigned long)__entry_text_start &&
 	    addr < (unsigned long)__entry_text_end) ||
 	    (addr >= (unsigned long)__idmap_text_start &&
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index b8deffa9e1bf..c68e5d528706 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -124,7 +124,6 @@ SECTIONS
 			SCHED_TEXT
 			CPUIDLE_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			HYPERVISOR_TEXT
 			IDMAP_TEXT
 			HIBERNATE_TEXT
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index 7301f4806bbe..7b2a5c5ef047 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -23,6 +23,7 @@
 #include <asm/sysreg.h>
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
+#include <asm/ranges.h>
 
 #ifdef CONFIG_PREEMPT
 # define preempt_stop		mask_interrupts
@@ -605,7 +606,11 @@ fault_exit_work:
 	brcc	fault_resume_user
 	rjmp	enter_monitor_mode
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(.text, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	handle_debug, @function
 handle_debug:
 	sub	sp, 4		/* r12_orig */
@@ -826,7 +831,11 @@ irq_level\level:
 	IRQ_LEVEL 2
 	IRQ_LEVEL 3
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(.text, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	enter_monitor_mode, @function
 enter_monitor_mode:
 	/*
diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S
index 17f2730eb497..04627a9c178e 100644
--- a/arch/avr32/kernel/vmlinux.lds.S
+++ b/arch/avr32/kernel/vmlinux.lds.S
@@ -49,7 +49,6 @@ SECTIONS
 		_stext = .;
 		*(.ex.text)
 		*(.irq.text)
-		KPROBES_TEXT
 		TEXT_TEXT
 		SCHED_TEXT
 		CPUIDLE_TEXT
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 68069a120055..93220ff65014 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -37,7 +37,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 #ifdef CONFIG_ROMKERNEL
 		__sinittext = .;
 		INIT_TEXT
diff --git a/arch/c6x/kernel/vmlinux.lds.S b/arch/c6x/kernel/vmlinux.lds.S
index a1a5c166bc9b..a41d43b8254b 100644
--- a/arch/c6x/kernel/vmlinux.lds.S
+++ b/arch/c6x/kernel/vmlinux.lds.S
@@ -74,7 +74,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S
index ec87e67feb19..7e6f68584b55 100644
--- a/arch/hexagon/kernel/vmlinux.lds.S
+++ b/arch/hexagon/kernel/vmlinux.lds.S
@@ -52,7 +52,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 	}
 	_etext = .;
diff --git a/arch/ia64/kernel/jprobes.S b/arch/ia64/kernel/jprobes.S
index f69389c7be1d..71adc7132e22 100644
--- a/arch/ia64/kernel/jprobes.S
+++ b/arch/ia64/kernel/jprobes.S
@@ -46,11 +46,12 @@
  */
 #include <asm/asmmacro.h>
 #include <asm/break.h>
+#include <asm/ranges.h>
 
 	/*
 	 * void jprobe_break(void)
 	 */
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 ENTRY(jprobe_break)
 	break.m __IA64_BREAK_JPROBE
 END(jprobe_break)
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index f89d20c97412..3ff6edf913d2 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -48,7 +48,6 @@ SECTIONS {
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.gnu.linkonce.t*)
 	}
 
diff --git a/arch/ia64/lib/flush.S b/arch/ia64/lib/flush.S
index 9a5a2f9fad13..dec1b180d618 100644
--- a/arch/ia64/lib/flush.S
+++ b/arch/ia64/lib/flush.S
@@ -9,7 +9,7 @@
 
 #include <asm/asmmacro.h>
 #include <asm/export.h>
-
+#include <asm/ranges.h>
 
 	/*
 	 * flush_icache_range(start,end)
@@ -21,7 +21,7 @@
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(.text, kprobes, ax)
 GLOBAL_ENTRY(flush_icache_range)
 
 	.prologue
@@ -74,7 +74,7 @@ EXPORT_SYMBOL_GPL(flush_icache_range)
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(.text, kprobes, ax)
 GLOBAL_ENTRY(clflush_cache_range)
 
 	.prologue
diff --git a/arch/metag/kernel/vmlinux.lds.S b/arch/metag/kernel/vmlinux.lds.S
index e6c700eaf207..b18386d2250f 100644
--- a/arch/metag/kernel/vmlinux.lds.S
+++ b/arch/metag/kernel/vmlinux.lds.S
@@ -23,7 +23,6 @@ SECTIONS
 	SCHED_TEXT
 	CPUIDLE_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	IRQENTRY_TEXT
 	SOFTIRQENTRY_TEXT
 	*(.text.*)
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
index 289d0e7f3e3a..aadee2229ac6 100644
--- a/arch/microblaze/kernel/vmlinux.lds.S
+++ b/arch/microblaze/kernel/vmlinux.lds.S
@@ -35,7 +35,6 @@ SECTIONS {
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		. = ALIGN (4) ;
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index f0a0e6d62be3..44e21812c544 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -57,7 +57,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.*)
diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S
index 2d5f1c3f1afb..552ef00a3da5 100644
--- a/arch/mn10300/kernel/vmlinux.lds.S
+++ b/arch/mn10300/kernel/vmlinux.lds.S
@@ -32,7 +32,6 @@ SECTIONS
 	SCHED_TEXT
 	CPUIDLE_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0xcb
diff --git a/arch/nios2/kernel/vmlinux.lds.S b/arch/nios2/kernel/vmlinux.lds.S
index 6a8045bb1a77..aae4a00c4056 100644
--- a/arch/nios2/kernel/vmlinux.lds.S
+++ b/arch/nios2/kernel/vmlinux.lds.S
@@ -41,7 +41,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 	} =0
 	_etext = .;
 
diff --git a/arch/openrisc/kernel/vmlinux.lds.S b/arch/openrisc/kernel/vmlinux.lds.S
index 00ddb7804be4..8ade6ccca6ac 100644
--- a/arch/openrisc/kernel/vmlinux.lds.S
+++ b/arch/openrisc/kernel/vmlinux.lds.S
@@ -57,7 +57,6 @@ SECTIONS
 	  SCHED_TEXT
 	  CPUIDLE_TEXT
 	  LOCK_TEXT
-	  KPROBES_TEXT
 	  IRQENTRY_TEXT
 	  SOFTIRQENTRY_TEXT
 	  *(.fixup)
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 3d6ef1b29c6a..edbd6d9487dc 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -71,7 +71,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.do_softirq)
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 025833b8df9f..0846413b3a2e 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,6 +9,7 @@
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
 #include <asm/firmware.h>
+#include <asm/ranges.h>
 
 #ifdef __ASSEMBLY__
 
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 8cd940c72895..2285664abb52 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -112,7 +112,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		MEM_KEEP(init.text)
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 97298c58b2be..847e2e1df89c 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -24,6 +24,7 @@
 #include <asm/setup.h>
 #include <asm/nmi.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
 __PT_R0      =	__PT_GPRS
 __PT_R1      =	__PT_GPRS + 8
@@ -169,7 +170,7 @@ _PIF_WORK	= (_PIF_PER_TRAP)
 		tm	off+\addr, \mask
 	.endm
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 .Ldummy:
 	/*
 	 * This nop exists only in order to avoid that __switch_to starts at
@@ -986,7 +987,7 @@ ENTRY(restart_int_handler)
 	brc	2,2b
 3:	j	3b
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 
 #ifdef CONFIG_CHECK_STACK
 /*
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 84e0557b16fe..94a4918b5968 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -289,9 +289,9 @@ static void kprobe_reenter_check(struct kprobe_ctlblk *kcb, struct kprobe *p)
 	case KPROBE_REENTER:
 	default:
 		/*
-		 * A kprobe on the code path to single step an instruction
-		 * is a BUG. The code path resides in the .kprobes.text
-		 * section and is executed with interrupts disabled.
+		 * A kprobe on the code path to single step an instruction is a
+		 * BUG. The code path resides in the kprobes section range and
+		 * is executed with interrupts disabled.
 		 */
 		printk(KERN_EMERG "Invalid kprobe detected at %p.\n", p->addr);
 		dump_kprobe(p);
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S
index 9a17e4475d27..9d76056609f7 100644
--- a/arch/s390/kernel/mcount.S
+++ b/arch/s390/kernel/mcount.S
@@ -10,8 +10,9 @@
 #include <asm/ftrace.h>
 #include <asm/ptrace.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 
 ENTRY(ftrace_stub)
 	br	%r14
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 3667d20e997f..b2df6d9bab09 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -37,7 +37,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/score/kernel/vmlinux.lds.S b/arch/score/kernel/vmlinux.lds.S
index 4117890b1db1..a8b14f3ed474 100644
--- a/arch/score/kernel/vmlinux.lds.S
+++ b/arch/score/kernel/vmlinux.lds.S
@@ -42,7 +42,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.text.*)
 		*(.fixup)
 		. = ALIGN (4) ;
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 5b9a3cc90c58..58d9ba796f7a 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -38,7 +38,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 572db686f845..0ee41b0071e5 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -51,7 +51,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.gnu.warning)
diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S
index 5d2fd6cd3189..ee9f648549c0 100644
--- a/arch/sparc/mm/ultra.S
+++ b/arch/sparc/mm/ultra.S
@@ -16,6 +16,7 @@
 #include <asm/cacheflush.h>
 #include <asm/hypervisor.h>
 #include <asm/cpudata.h>
+#include <asm/ranges.h>
 
 	/* Basically, most of the Spitfire vs. Cheetah madness
 	 * has to do with the fact that Cheetah does not support
@@ -185,7 +186,7 @@ __spitfire_flush_tlb_mm_slow:
 /*
  * The following code flushes one page_size worth.
  */
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 	.align		32
 	.globl		__flush_icache_page
 __flush_icache_page:	/* %o0 = phys_page */
diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S
index e1baf094fba4..85d03ce6c0a0 100644
--- a/arch/tile/kernel/vmlinux.lds.S
+++ b/arch/tile/kernel/vmlinux.lds.S
@@ -44,7 +44,6 @@ SECTIONS
     SCHED_TEXT
     CPUIDLE_TEXT
     LOCK_TEXT
-    KPROBES_TEXT
     IRQENTRY_TEXT
     SOFTIRQENTRY_TEXT
     __fix_text_end = .;   /* tile-cpack won't rearrange before this */
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index eb3509338ae0..95e4b172e923 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -580,9 +580,9 @@ static int reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
 	case KPROBE_REENTER:
 		/* A probe has been hit in the codepath leading up to, or just
 		 * after, single-stepping of a probed instruction. This entire
-		 * codepath should strictly reside in .kprobes.text section.
-		 * Raise a BUG or we'll continue in an endless reentering loop
-		 * and eventually a stack overflow.
+		 * codepath should strictly reside in the kprobes section
+		 * range. Raise a BUG or we'll continue in an endless
+		 * reentering loop and eventually a stack overflow.
 		 */
 		printk(KERN_WARNING "Unrecoverable kprobe detected at %p.\n",
 		       p->addr);
@@ -1133,10 +1133,9 @@ NOKPROBE_SYMBOL(longjmp_break_handler);
 
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
-	return  (addr >= (unsigned long)__kprobes_text_start &&
-		 addr < (unsigned long)__kprobes_text_end) ||
+	return  (SECTION_RANGE_ADDR_WITHIN(kprobes, addr) ||
 		(addr >= (unsigned long)__entry_text_start &&
-		 addr < (unsigned long)__entry_text_end);
+		 addr < (unsigned long)__entry_text_end));
 }
 
 int __init arch_init_kprobes(void)
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index e79f15f108a8..4c16fadb9ac6 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -99,7 +99,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		ENTRY_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 57af9f21d148..02a26b975187 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,6 +3,7 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
@@ -13,7 +14,7 @@ static unsigned long __used					\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define __kprobes	__LINUX_RANGE(.text, kprobes)
 # define nokprobe_inline	__always_inline
 #else
 # define NOKPROBE_SYMBOL(fname)
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index b145ae8d9cbe..f3340f2772bb 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -26,7 +26,6 @@
  * Following global variables are optional and may be unavailable on some
  * architectures and/or kernel configurations.
  *	_text, _data
- *	__kprobes_text_start, __kprobes_text_end
  *	__entry_text_start, __entry_text_end
  *	__ctors_start, __ctors_end
  */
@@ -38,7 +37,6 @@ extern char _sinittext[], _einittext[];
 extern char __start_data_ro_after_init[], __end_data_ro_after_init[];
 extern char _end[];
 extern char __per_cpu_load[], __per_cpu_start[], __per_cpu_end[];
-extern char __kprobes_text_start[], __kprobes_text_end[];
 extern char __entry_text_start[], __entry_text_end[];
 extern char __start_rodata[], __end_rodata[];
 
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 37b99537d5a9..499caf5b4361 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -471,7 +471,7 @@
 #define KPROBES_TEXT							\
 		ALIGN_FUNCTION();					\
 		VMLINUX_SYMBOL(__kprobes_text_start) = .;		\
-		*(.kprobes.text)					\
+		*(.text..rng.kprobes.any)				\
 		VMLINUX_SYMBOL(__kprobes_text_end) = .;
 
 #define ENTRY_TEXT							\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 985ed79ef431..445cc6fe7afa 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -43,6 +43,9 @@
 #include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
+#include <linux/ranges.h>
+
+DECLARE_SECTION_RANGE(kprobes);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 43460104f119..82191f328e21 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1328,8 +1328,7 @@ static int register_aggr_kprobe(struct kprobe *orig_p, struct kprobe *p)
 bool __weak arch_within_kprobe_blacklist(unsigned long addr)
 {
 	/* The __kprobes marked functions and entry code must not be probed */
-	return addr >= (unsigned long)__kprobes_text_start &&
-	       addr < (unsigned long)__kprobes_text_end;
+	return SECTION_RANGE_ADDR_WITHIN(kprobes, addr);
 }
 
 bool within_kprobe_blacklist(unsigned long addr)
@@ -2129,6 +2128,9 @@ static struct notifier_block kprobe_module_nb = {
 extern unsigned long __start_kprobe_blacklist[];
 extern unsigned long __stop_kprobe_blacklist[];
 
+/* Actual kprobes section range */
+DEFINE_SECTION_RANGE(kprobes, .text);
+
 static int __init init_kprobes(void)
 {
 	int i, err = 0;
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 29c89a6bad3d..2b442234c69b 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -894,7 +894,7 @@ static void check_section(const char *modname, struct elf_info *elf,
 
 #define DATA_SECTIONS ".data", ".data.rel"
 #define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \
-		".kprobes.text", ".cpuidle.text"
+		".text..rng.kprobes.any", ".cpuidle.text"
 #define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
 		".fixup", ".entry.text", ".exception.text", ".text.*", \
 		".coldtext"
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index aeb34223167c..6e95f3f87db1 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -417,7 +417,7 @@ is_mcounted_section_name(char const *const txtname)
 		strcmp(".spinlock.text", txtname) == 0 ||
 		strcmp(".irqentry.text", txtname) == 0 ||
 		strcmp(".softirqentry.text", txtname) == 0 ||
-		strcmp(".kprobes.text", txtname) == 0 ||
+		strcmp(".text..rng.kprobes.any", txtname) == 0 ||
 		strcmp(".cpuidle.text", txtname) == 0 ||
 		strcmp(".text.unlikely", txtname) == 0;
 }
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 0b6002b36f20..15e2fa37c489 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -135,7 +135,7 @@ my %text_sections = (
      ".spinlock.text" => 1,
      ".irqentry.text" => 1,
      ".softirqentry.text" => 1,
-     ".kprobes.text" => 1,
+     ".text..rng.kprobes.any" => 1,
      ".cpuidle.text" => 1,
      ".text.unlikely" => 1,
 );
-- 
2.11.0


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 12/14] kprobes: port .kprobes.text to section range
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

kprobe makes use of two custom sections, each custom section
is folded into one of the standard Linux sections types as follows,
it currently relies on the linker script to fold the custom section
onto the respective Linux section:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist
range .text         .kprobes.text        __kprobes_text_start     __kprobes_text_end

This ports the .kprobes.text custom section to the standard
Linux ranges API allowing us remove all the custom kprobe section
declarations from the linker script.

Tested with CONFIG_KPROBES_SANITY_TEST, it passes with:

Kprobe smoke test: started
Kprobe smoke test: passed successfully

Then tested CONFIG_SAMPLE_KPROBES on do_fork, and the kprobe bites
and kicks as expected.

Also ran ./ftracetest with no issues:

sudo ./ftracetest
=== Ftrace unit tests ===
[1] Basic trace file check	[PASS]
[2] Basic test for tracers	[PASS]
[3] Basic trace clock test	[PASS]
[4] Basic event tracing check	[PASS]
[5] event tracing - enable/disable with event level files	[PASS]
[6] event tracing - restricts events based on pid	[PASS]
[7] event tracing - enable/disable with subsystem level files	[PASS]
[8] event tracing - enable/disable with top level files	[PASS]
[9] ftrace - function graph filters with stack tracer	[PASS]
[10] ftrace - function graph filters	[PASS]
[11] ftrace - function glob filters	[PASS]
[12] ftrace - function profiler with function tracing	[PASS]
[13] Test creation and deletion of trace instances while setting an event	[PASS]
[14] Test creation and deletion of trace instances	[PASS]
[15] Kprobe dynamic event - adding and removing	[PASS]
[16] Kprobe dynamic event - busy event check	[PASS]
[17] Kprobe dynamic event with arguments	[PASS]
[18] Kprobes event arguments with types	[PASS]
[19] Kprobe dynamic event with function tracer	[PASS]
[20] Kretprobe dynamic event with arguments	[PASS]
[21] event trigger - test event enable/disable trigger	[PASS]
[22] event trigger - test trigger filter	[PASS]
[23] event trigger - test histogram modifiers	[PASS]
[24] event trigger - test histogram trigger	[PASS]
[25] event trigger - test multiple histogram triggers	[PASS]
[26] event trigger - test snapshot-trigger	[PASS]
[27] event trigger - test stacktrace-trigger	[PASS]
[28] event trigger - test traceon/off trigger	[PASS]

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

v4:

o arm64 build fixes with allmodconfig

o build fix suggested for avr32 with allnoconfig, otherwise we end up with:

arch/avr32/kernel/built-in.o: In function `save_full_context_ex':
(.ex.text+0x1c4): relocation truncated to fit: R_AVR32_16N_PCREL against
symbol `debug_trampoline' defined in .text.rng.kprobes.any section in
arch/avr32/kernel/built-in.o
arch/avr32/kernel/built-in.o: In function `debug_exit_work':
(.text.rng.kprobes.any+0xa8): relocation truncated to fit:
R_AVR32_16N_PCREL against `.ex.text'+3aa
make: *** [Makefile:953: vmlinux] Error 1

o open-code section use on scripts/ code -- folks to prefer the
  simplicity over dealing with having more tool code access kernel
  headers.

o NOPE: include #include <asm-generic/ranges.h> on compiler.h -- solves
  a few 0-day compilation issues

v3:

o after v2 arch/arm/kernel/vmlinux-xip.lds.S got kprobe support,
  this just removes the custom linker script reference to kprobes as
  that is no longer needed with linker tables.

o split kprobe linker table and kprobe section ranges use into
  two separate patches. This should make it easier to review and
  also demos both distinct use types, one a linker table another
  a simple section range.

v2: introduced this patch in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arc/kernel/vmlinux.lds.S        |  1 -
 arch/arm/kernel/entry-armv.S         |  3 ++-
 arch/arm/kernel/vmlinux-xip.lds.S    |  1 -
 arch/arm/kernel/vmlinux.lds.S        |  1 -
 arch/arm64/kernel/armv8_deprecated.c |  1 +
 arch/arm64/kernel/probes/kprobes.c   |  4 ++--
 arch/arm64/kernel/vmlinux.lds.S      |  1 -
 arch/avr32/kernel/entry-avr32b.S     | 13 +++++++++++--
 arch/avr32/kernel/vmlinux.lds.S      |  1 -
 arch/blackfin/kernel/vmlinux.lds.S   |  1 -
 arch/c6x/kernel/vmlinux.lds.S        |  1 -
 arch/hexagon/kernel/vmlinux.lds.S    |  1 -
 arch/ia64/kernel/jprobes.S           |  3 ++-
 arch/ia64/kernel/vmlinux.lds.S       |  1 -
 arch/ia64/lib/flush.S                |  6 +++---
 arch/metag/kernel/vmlinux.lds.S      |  1 -
 arch/microblaze/kernel/vmlinux.lds.S |  1 -
 arch/mips/kernel/vmlinux.lds.S       |  1 -
 arch/mn10300/kernel/vmlinux.lds.S    |  1 -
 arch/nios2/kernel/vmlinux.lds.S      |  1 -
 arch/openrisc/kernel/vmlinux.lds.S   |  1 -
 arch/parisc/kernel/vmlinux.lds.S     |  1 -
 arch/powerpc/include/asm/ppc_asm.h   |  1 +
 arch/powerpc/kernel/vmlinux.lds.S    |  1 -
 arch/s390/kernel/entry.S             |  5 +++--
 arch/s390/kernel/kprobes.c           |  6 +++---
 arch/s390/kernel/mcount.S            |  3 ++-
 arch/s390/kernel/vmlinux.lds.S       |  1 -
 arch/score/kernel/vmlinux.lds.S      |  1 -
 arch/sh/kernel/vmlinux.lds.S         |  1 -
 arch/sparc/kernel/vmlinux.lds.S      |  1 -
 arch/sparc/mm/ultra.S                |  3 ++-
 arch/tile/kernel/vmlinux.lds.S       |  1 -
 arch/x86/kernel/kprobes/core.c       | 11 +++++------
 arch/x86/kernel/vmlinux.lds.S        |  1 -
 include/asm-generic/kprobes.h        |  3 ++-
 include/asm-generic/sections.h       |  2 --
 include/asm-generic/vmlinux.lds.h    |  2 +-
 include/linux/kprobes.h              |  3 +++
 kernel/kprobes.c                     |  6 ++++--
 scripts/mod/modpost.c                |  2 +-
 scripts/recordmcount.c               |  2 +-
 scripts/recordmcount.pl              |  2 +-
 43 files changed, 50 insertions(+), 54 deletions(-)

diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S
index f35ed578e007..dd05c86eb96e 100644
--- a/arch/arc/kernel/vmlinux.lds.S
+++ b/arch/arc/kernel/vmlinux.lds.S
@@ -91,7 +91,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 9f157e7c51e7..c455b491b6d3 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -34,6 +34,7 @@
 #include "entry-header.S"
 #include <asm/entry-macro-multi.S>
 #include <asm/probes.h>
+#include <asm/ranges.h>
 
 /*
  * Interrupt handling.
@@ -83,7 +84,7 @@
 	.endm
 
 #ifdef CONFIG_KPROBES
-	.section	.kprobes.text,"ax",%progbits
+	set_section_rng_type(.text, kprobes, ax, %progbits)
 #else
 	.text
 #endif
diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S
index 37b2a11af345..1a84f84b8165 100644
--- a/arch/arm/kernel/vmlinux-xip.lds.S
+++ b/arch/arm/kernel/vmlinux-xip.lds.S
@@ -103,7 +103,6 @@ SECTIONS
 			SCHED_TEXT
 			CPUIDLE_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index f7f55df0bf7b..1e278e6c3506 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -114,7 +114,6 @@ SECTIONS
 			CPUIDLE_TEXT
 			LOCK_TEXT
 			HYPERVISOR_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index ecf9298a12d4..35574b9fe6d4 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -21,6 +21,7 @@
 #include <asm/traps.h>
 #include <linux/uaccess.h>
 #include <asm/cpufeature.h>
+#include <asm/kprobes.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace-events-emulation.h"
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index f0593c92279b..ec288dd165cb 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/stop_machine.h>
 #include <linux/stringify.h>
+#include <linux/ranges.h>
 #include <asm/traps.h>
 #include <asm/ptrace.h>
 #include <asm/cacheflush.h>
@@ -540,8 +541,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
-	if ((addr >= (unsigned long)__kprobes_text_start &&
-	    addr < (unsigned long)__kprobes_text_end) ||
+	if (SECTION_RANGE_ADDR_WITHIN(kprobes, addr) ||
 	    (addr >= (unsigned long)__entry_text_start &&
 	    addr < (unsigned long)__entry_text_end) ||
 	    (addr >= (unsigned long)__idmap_text_start &&
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index b8deffa9e1bf..c68e5d528706 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -124,7 +124,6 @@ SECTIONS
 			SCHED_TEXT
 			CPUIDLE_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			HYPERVISOR_TEXT
 			IDMAP_TEXT
 			HIBERNATE_TEXT
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index 7301f4806bbe..7b2a5c5ef047 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -23,6 +23,7 @@
 #include <asm/sysreg.h>
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
+#include <asm/ranges.h>
 
 #ifdef CONFIG_PREEMPT
 # define preempt_stop		mask_interrupts
@@ -605,7 +606,11 @@ fault_exit_work:
 	brcc	fault_resume_user
 	rjmp	enter_monitor_mode
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(.text, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	handle_debug, @function
 handle_debug:
 	sub	sp, 4		/* r12_orig */
@@ -826,7 +831,11 @@ irq_level\level:
 	IRQ_LEVEL 2
 	IRQ_LEVEL 3
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(.text, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	enter_monitor_mode, @function
 enter_monitor_mode:
 	/*
diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S
index 17f2730eb497..04627a9c178e 100644
--- a/arch/avr32/kernel/vmlinux.lds.S
+++ b/arch/avr32/kernel/vmlinux.lds.S
@@ -49,7 +49,6 @@ SECTIONS
 		_stext = .;
 		*(.ex.text)
 		*(.irq.text)
-		KPROBES_TEXT
 		TEXT_TEXT
 		SCHED_TEXT
 		CPUIDLE_TEXT
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 68069a120055..93220ff65014 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -37,7 +37,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 #ifdef CONFIG_ROMKERNEL
 		__sinittext = .;
 		INIT_TEXT
diff --git a/arch/c6x/kernel/vmlinux.lds.S b/arch/c6x/kernel/vmlinux.lds.S
index a1a5c166bc9b..a41d43b8254b 100644
--- a/arch/c6x/kernel/vmlinux.lds.S
+++ b/arch/c6x/kernel/vmlinux.lds.S
@@ -74,7 +74,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S
index ec87e67feb19..7e6f68584b55 100644
--- a/arch/hexagon/kernel/vmlinux.lds.S
+++ b/arch/hexagon/kernel/vmlinux.lds.S
@@ -52,7 +52,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 	}
 	_etext = .;
diff --git a/arch/ia64/kernel/jprobes.S b/arch/ia64/kernel/jprobes.S
index f69389c7be1d..71adc7132e22 100644
--- a/arch/ia64/kernel/jprobes.S
+++ b/arch/ia64/kernel/jprobes.S
@@ -46,11 +46,12 @@
  */
 #include <asm/asmmacro.h>
 #include <asm/break.h>
+#include <asm/ranges.h>
 
 	/*
 	 * void jprobe_break(void)
 	 */
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 ENTRY(jprobe_break)
 	break.m __IA64_BREAK_JPROBE
 END(jprobe_break)
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index f89d20c97412..3ff6edf913d2 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -48,7 +48,6 @@ SECTIONS {
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.gnu.linkonce.t*)
 	}
 
diff --git a/arch/ia64/lib/flush.S b/arch/ia64/lib/flush.S
index 9a5a2f9fad13..dec1b180d618 100644
--- a/arch/ia64/lib/flush.S
+++ b/arch/ia64/lib/flush.S
@@ -9,7 +9,7 @@
 
 #include <asm/asmmacro.h>
 #include <asm/export.h>
-
+#include <asm/ranges.h>
 
 	/*
 	 * flush_icache_range(start,end)
@@ -21,7 +21,7 @@
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(.text, kprobes, ax)
 GLOBAL_ENTRY(flush_icache_range)
 
 	.prologue
@@ -74,7 +74,7 @@ EXPORT_SYMBOL_GPL(flush_icache_range)
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(.text, kprobes, ax)
 GLOBAL_ENTRY(clflush_cache_range)
 
 	.prologue
diff --git a/arch/metag/kernel/vmlinux.lds.S b/arch/metag/kernel/vmlinux.lds.S
index e6c700eaf207..b18386d2250f 100644
--- a/arch/metag/kernel/vmlinux.lds.S
+++ b/arch/metag/kernel/vmlinux.lds.S
@@ -23,7 +23,6 @@ SECTIONS
 	SCHED_TEXT
 	CPUIDLE_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	IRQENTRY_TEXT
 	SOFTIRQENTRY_TEXT
 	*(.text.*)
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
index 289d0e7f3e3a..aadee2229ac6 100644
--- a/arch/microblaze/kernel/vmlinux.lds.S
+++ b/arch/microblaze/kernel/vmlinux.lds.S
@@ -35,7 +35,6 @@ SECTIONS {
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		. = ALIGN (4) ;
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index f0a0e6d62be3..44e21812c544 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -57,7 +57,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.*)
diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S
index 2d5f1c3f1afb..552ef00a3da5 100644
--- a/arch/mn10300/kernel/vmlinux.lds.S
+++ b/arch/mn10300/kernel/vmlinux.lds.S
@@ -32,7 +32,6 @@ SECTIONS
 	SCHED_TEXT
 	CPUIDLE_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0xcb
diff --git a/arch/nios2/kernel/vmlinux.lds.S b/arch/nios2/kernel/vmlinux.lds.S
index 6a8045bb1a77..aae4a00c4056 100644
--- a/arch/nios2/kernel/vmlinux.lds.S
+++ b/arch/nios2/kernel/vmlinux.lds.S
@@ -41,7 +41,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 	} =0
 	_etext = .;
 
diff --git a/arch/openrisc/kernel/vmlinux.lds.S b/arch/openrisc/kernel/vmlinux.lds.S
index 00ddb7804be4..8ade6ccca6ac 100644
--- a/arch/openrisc/kernel/vmlinux.lds.S
+++ b/arch/openrisc/kernel/vmlinux.lds.S
@@ -57,7 +57,6 @@ SECTIONS
 	  SCHED_TEXT
 	  CPUIDLE_TEXT
 	  LOCK_TEXT
-	  KPROBES_TEXT
 	  IRQENTRY_TEXT
 	  SOFTIRQENTRY_TEXT
 	  *(.fixup)
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 3d6ef1b29c6a..edbd6d9487dc 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -71,7 +71,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.do_softirq)
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 025833b8df9f..0846413b3a2e 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,6 +9,7 @@
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
 #include <asm/firmware.h>
+#include <asm/ranges.h>
 
 #ifdef __ASSEMBLY__
 
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 8cd940c72895..2285664abb52 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -112,7 +112,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		MEM_KEEP(init.text)
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 97298c58b2be..847e2e1df89c 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -24,6 +24,7 @@
 #include <asm/setup.h>
 #include <asm/nmi.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
 __PT_R0      =	__PT_GPRS
 __PT_R1      =	__PT_GPRS + 8
@@ -169,7 +170,7 @@ _PIF_WORK	= (_PIF_PER_TRAP)
 		tm	off+\addr, \mask
 	.endm
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 .Ldummy:
 	/*
 	 * This nop exists only in order to avoid that __switch_to starts at
@@ -986,7 +987,7 @@ ENTRY(restart_int_handler)
 	brc	2,2b
 3:	j	3b
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 
 #ifdef CONFIG_CHECK_STACK
 /*
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 84e0557b16fe..94a4918b5968 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -289,9 +289,9 @@ static void kprobe_reenter_check(struct kprobe_ctlblk *kcb, struct kprobe *p)
 	case KPROBE_REENTER:
 	default:
 		/*
-		 * A kprobe on the code path to single step an instruction
-		 * is a BUG. The code path resides in the .kprobes.text
-		 * section and is executed with interrupts disabled.
+		 * A kprobe on the code path to single step an instruction is a
+		 * BUG. The code path resides in the kprobes section range and
+		 * is executed with interrupts disabled.
 		 */
 		printk(KERN_EMERG "Invalid kprobe detected at %p.\n", p->addr);
 		dump_kprobe(p);
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S
index 9a17e4475d27..9d76056609f7 100644
--- a/arch/s390/kernel/mcount.S
+++ b/arch/s390/kernel/mcount.S
@@ -10,8 +10,9 @@
 #include <asm/ftrace.h>
 #include <asm/ptrace.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 
 ENTRY(ftrace_stub)
 	br	%r14
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 3667d20e997f..b2df6d9bab09 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -37,7 +37,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/score/kernel/vmlinux.lds.S b/arch/score/kernel/vmlinux.lds.S
index 4117890b1db1..a8b14f3ed474 100644
--- a/arch/score/kernel/vmlinux.lds.S
+++ b/arch/score/kernel/vmlinux.lds.S
@@ -42,7 +42,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.text.*)
 		*(.fixup)
 		. = ALIGN (4) ;
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 5b9a3cc90c58..58d9ba796f7a 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -38,7 +38,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 572db686f845..0ee41b0071e5 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -51,7 +51,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.gnu.warning)
diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S
index 5d2fd6cd3189..ee9f648549c0 100644
--- a/arch/sparc/mm/ultra.S
+++ b/arch/sparc/mm/ultra.S
@@ -16,6 +16,7 @@
 #include <asm/cacheflush.h>
 #include <asm/hypervisor.h>
 #include <asm/cpudata.h>
+#include <asm/ranges.h>
 
 	/* Basically, most of the Spitfire vs. Cheetah madness
 	 * has to do with the fact that Cheetah does not support
@@ -185,7 +186,7 @@ __spitfire_flush_tlb_mm_slow:
 /*
  * The following code flushes one page_size worth.
  */
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 	.align		32
 	.globl		__flush_icache_page
 __flush_icache_page:	/* %o0 = phys_page */
diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S
index e1baf094fba4..85d03ce6c0a0 100644
--- a/arch/tile/kernel/vmlinux.lds.S
+++ b/arch/tile/kernel/vmlinux.lds.S
@@ -44,7 +44,6 @@ SECTIONS
     SCHED_TEXT
     CPUIDLE_TEXT
     LOCK_TEXT
-    KPROBES_TEXT
     IRQENTRY_TEXT
     SOFTIRQENTRY_TEXT
     __fix_text_end = .;   /* tile-cpack won't rearrange before this */
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index eb3509338ae0..95e4b172e923 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -580,9 +580,9 @@ static int reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
 	case KPROBE_REENTER:
 		/* A probe has been hit in the codepath leading up to, or just
 		 * after, single-stepping of a probed instruction. This entire
-		 * codepath should strictly reside in .kprobes.text section.
-		 * Raise a BUG or we'll continue in an endless reentering loop
-		 * and eventually a stack overflow.
+		 * codepath should strictly reside in the kprobes section
+		 * range. Raise a BUG or we'll continue in an endless
+		 * reentering loop and eventually a stack overflow.
 		 */
 		printk(KERN_WARNING "Unrecoverable kprobe detected at %p.\n",
 		       p->addr);
@@ -1133,10 +1133,9 @@ NOKPROBE_SYMBOL(longjmp_break_handler);
 
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
-	return  (addr >= (unsigned long)__kprobes_text_start &&
-		 addr < (unsigned long)__kprobes_text_end) ||
+	return  (SECTION_RANGE_ADDR_WITHIN(kprobes, addr) ||
 		(addr >= (unsigned long)__entry_text_start &&
-		 addr < (unsigned long)__entry_text_end);
+		 addr < (unsigned long)__entry_text_end));
 }
 
 int __init arch_init_kprobes(void)
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index e79f15f108a8..4c16fadb9ac6 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -99,7 +99,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		ENTRY_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 57af9f21d148..02a26b975187 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,6 +3,7 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
@@ -13,7 +14,7 @@ static unsigned long __used					\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define __kprobes	__LINUX_RANGE(.text, kprobes)
 # define nokprobe_inline	__always_inline
 #else
 # define NOKPROBE_SYMBOL(fname)
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index b145ae8d9cbe..f3340f2772bb 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -26,7 +26,6 @@
  * Following global variables are optional and may be unavailable on some
  * architectures and/or kernel configurations.
  *	_text, _data
- *	__kprobes_text_start, __kprobes_text_end
  *	__entry_text_start, __entry_text_end
  *	__ctors_start, __ctors_end
  */
@@ -38,7 +37,6 @@ extern char _sinittext[], _einittext[];
 extern char __start_data_ro_after_init[], __end_data_ro_after_init[];
 extern char _end[];
 extern char __per_cpu_load[], __per_cpu_start[], __per_cpu_end[];
-extern char __kprobes_text_start[], __kprobes_text_end[];
 extern char __entry_text_start[], __entry_text_end[];
 extern char __start_rodata[], __end_rodata[];
 
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 37b99537d5a9..499caf5b4361 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -471,7 +471,7 @@
 #define KPROBES_TEXT							\
 		ALIGN_FUNCTION();					\
 		VMLINUX_SYMBOL(__kprobes_text_start) = .;		\
-		*(.kprobes.text)					\
+		*(.text..rng.kprobes.any)				\
 		VMLINUX_SYMBOL(__kprobes_text_end) = .;
 
 #define ENTRY_TEXT							\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 985ed79ef431..445cc6fe7afa 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -43,6 +43,9 @@
 #include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
+#include <linux/ranges.h>
+
+DECLARE_SECTION_RANGE(kprobes);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 43460104f119..82191f328e21 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1328,8 +1328,7 @@ static int register_aggr_kprobe(struct kprobe *orig_p, struct kprobe *p)
 bool __weak arch_within_kprobe_blacklist(unsigned long addr)
 {
 	/* The __kprobes marked functions and entry code must not be probed */
-	return addr >= (unsigned long)__kprobes_text_start &&
-	       addr < (unsigned long)__kprobes_text_end;
+	return SECTION_RANGE_ADDR_WITHIN(kprobes, addr);
 }
 
 bool within_kprobe_blacklist(unsigned long addr)
@@ -2129,6 +2128,9 @@ static struct notifier_block kprobe_module_nb = {
 extern unsigned long __start_kprobe_blacklist[];
 extern unsigned long __stop_kprobe_blacklist[];
 
+/* Actual kprobes section range */
+DEFINE_SECTION_RANGE(kprobes, .text);
+
 static int __init init_kprobes(void)
 {
 	int i, err = 0;
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 29c89a6bad3d..2b442234c69b 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -894,7 +894,7 @@ static void check_section(const char *modname, struct elf_info *elf,
 
 #define DATA_SECTIONS ".data", ".data.rel"
 #define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \
-		".kprobes.text", ".cpuidle.text"
+		".text..rng.kprobes.any", ".cpuidle.text"
 #define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
 		".fixup", ".entry.text", ".exception.text", ".text.*", \
 		".coldtext"
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index aeb34223167c..6e95f3f87db1 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -417,7 +417,7 @@ is_mcounted_section_name(char const *const txtname)
 		strcmp(".spinlock.text", txtname) == 0 ||
 		strcmp(".irqentry.text", txtname) == 0 ||
 		strcmp(".softirqentry.text", txtname) == 0 ||
-		strcmp(".kprobes.text", txtname) == 0 ||
+		strcmp(".text..rng.kprobes.any", txtname) == 0 ||
 		strcmp(".cpuidle.text", txtname) == 0 ||
 		strcmp(".text.unlikely", txtname) == 0;
 }
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 0b6002b36f20..15e2fa37c489 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -135,7 +135,7 @@ my %text_sections = (
      ".spinlock.text" => 1,
      ".irqentry.text" => 1,
      ".softirqentry.text" => 1,
-     ".kprobes.text" => 1,
+     ".text..rng.kprobes.any" => 1,
      ".cpuidle.text" => 1,
      ".text.unlikely" => 1,
 );
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 13/14] kprobes: port blacklist kprobes to linker table
  2017-01-09 14:58       ` Luis R. Rodriguez
  (?)
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt

kprobe makes use of two sections, the one dealing with the actual
kprobes was recently ported using the standard section range API.
The blacklist functionality of kprobes is still using a custom
section and declaring its custom section using the linker script
as follows:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist

This ports the _kprobe_blacklist custom section to the standard
Linux linker table API allowing us remove all the custom blacklist
kprobe section declarations from the linker script.

This has been tested by trying to register a kprobe on a blacklisted
symbol (these are declared with NOKPROBE_SYMBOL()), and confirms that
this fails to work as expected. This was tested with:

 # insmod samples/kprobes/kprobe_example.ko symbol="get_kprobe"

This fails to load as expected with:

insmod: ERROR: could not insert module samples/kprobes/kprobe_example.ko: Invalid parameters

v5: Use push_section_tbl() for _ASM_NOKPROBE() for x86, and
    _ASM_NOKPROBE_SYMBOL() on powerpc
v4: ported over _ASM_NOKPROBE_SYMBOL() on powerpc and
    ASM_NOKPROBE() on x86
v3: this patch was introduced in this series

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/powerpc/include/asm/ppc_asm.h |  4 ++--
 arch/x86/include/asm/asm.h         |  4 +++-
 include/asm-generic/kprobes.h      |  4 ++--
 include/asm-generic/vmlinux.lds.h  | 10 ----------
 include/linux/kprobes.h            |  2 ++
 kernel/kprobes.c                   | 11 ++++-------
 6 files changed, 13 insertions(+), 22 deletions(-)

diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 0846413b3a2e..20cd9c00eef5 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,7 +9,7 @@
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
 #include <asm/firmware.h>
-#include <asm/ranges.h>
+#include <asm/tables.h>
 
 #ifdef __ASSEMBLY__
 
@@ -266,7 +266,7 @@ GLUE(.,name):
  */
 #ifdef CONFIG_KPROBES
 #define _ASM_NOKPROBE_SYMBOL(entry)			\
-	.pushsection "_kprobe_blacklist","aw";		\
+	push_section_tbl(.init.data, _kprobe_blacklist, any, aw); \
 	PPC_LONG (entry) ;				\
 	.popsection
 #else
diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
index 7acb51c49fec..48b1bc85c0e6 100644
--- a/arch/x86/include/asm/asm.h
+++ b/arch/x86/include/asm/asm.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_ASM_H
 #define _ASM_X86_ASM_H
 
+#include <asm/tables.h>
+
 #ifdef __ASSEMBLY__
 # define __ASM_FORM(x)	x
 # define __ASM_FORM_RAW(x)     x
@@ -74,7 +76,7 @@
 	_ASM_EXTABLE_HANDLE(from, to, ex_handler_ext)
 
 # define _ASM_NOKPROBE(entry)					\
-	.pushsection "_kprobe_blacklist","aw" ;			\
+	push_section_tbl_any(.init.data, _kprobe_blacklist, aw);\
 	_ASM_ALIGN ;						\
 	_ASM_PTR (entry);					\
 	.popsection
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 02a26b975187..7d29a208390e 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,14 +3,14 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <linux/tables.h>
 #include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
  */
 # define __NOKPROBE_SYMBOL(fname)				\
-static unsigned long __used					\
-	__attribute__((__section__("_kprobe_blacklist")))	\
+static LINKTABLE_INIT_DATA(_kprobe_blacklist, all)		\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 499caf5b4361..9f062af1f728 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -114,15 +114,6 @@
 #define BRANCH_PROFILE()
 #endif
 
-#ifdef CONFIG_KPROBES
-#define KPROBE_BLACKLIST()	. = ALIGN(8);				      \
-				VMLINUX_SYMBOL(__start_kprobe_blacklist) = .; \
-				KEEP(*(_kprobe_blacklist))		      \
-				VMLINUX_SYMBOL(__stop_kprobe_blacklist) = .;
-#else
-#define KPROBE_BLACKLIST()
-#endif
-
 #ifdef CONFIG_EVENT_TRACING
 #define FTRACE_EVENTS()	. = ALIGN(8);					\
 			VMLINUX_SYMBOL(__start_ftrace_events) = .;	\
@@ -551,7 +542,6 @@
 	*(.init.rodata)							\
 	FTRACE_EVENTS()							\
 	TRACE_SYSCALLS()						\
-	KPROBE_BLACKLIST()						\
 	MEM_DISCARD(init.rodata)					\
 	CLK_OF_TABLES()							\
 	RESERVEDMEM_OF_TABLES()						\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 445cc6fe7afa..2707820cbb56 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -44,8 +44,10 @@
 
 #ifdef CONFIG_KPROBES
 #include <linux/ranges.h>
+#include <linux/tables.h>
 
 DECLARE_SECTION_RANGE(kprobes);
+DECLARE_LINKTABLE(unsigned long, _kprobe_blacklist);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 82191f328e21..9d102ac95256 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -2053,14 +2053,13 @@ NOKPROBE_SYMBOL(dump_kprobe);
  * since a kprobe need not necessarily be at the beginning
  * of a function.
  */
-static int __init populate_kprobe_blacklist(unsigned long *start,
-					     unsigned long *end)
+static int __init populate_kprobe_blacklist(void)
 {
 	unsigned long *iter;
 	struct kprobe_blacklist_entry *ent;
 	unsigned long entry, offset = 0, size = 0;
 
-	for (iter = start; iter < end; iter++) {
+	linktable_for_each(iter, _kprobe_blacklist) {
 		entry = arch_deref_entry_point((void *)*iter);
 
 		if (!kernel_text_address(entry) ||
@@ -2125,8 +2124,7 @@ static struct notifier_block kprobe_module_nb = {
 };
 
 /* Markers of _kprobe_blacklist section */
-extern unsigned long __start_kprobe_blacklist[];
-extern unsigned long __stop_kprobe_blacklist[];
+DEFINE_LINKTABLE_INIT_DATA(unsigned long, _kprobe_blacklist);
 
 /* Actual kprobes section range */
 DEFINE_SECTION_RANGE(kprobes, .text);
@@ -2143,8 +2141,7 @@ static int __init init_kprobes(void)
 		raw_spin_lock_init(&(kretprobe_table_locks[i].lock));
 	}
 
-	err = populate_kprobe_blacklist(__start_kprobe_blacklist,
-					__stop_kprobe_blacklist);
+	err = populate_kprobe_blacklist();
 	if (err) {
 		pr_err("kprobes: failed to populate blacklist: %d\n", err);
 		pr_err("Please take care of using kprobes.\n");
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 13/14] kprobes: port blacklist kprobes to linker table
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt, ak

kprobe makes use of two sections, the one dealing with the actual
kprobes was recently ported using the standard section range API.
The blacklist functionality of kprobes is still using a custom
section and declaring its custom section using the linker script
as follows:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist

This ports the _kprobe_blacklist custom section to the standard
Linux linker table API allowing us remove all the custom blacklist
kprobe section declarations from the linker script.

This has been tested by trying to register a kprobe on a blacklisted
symbol (these are declared with NOKPROBE_SYMBOL()), and confirms that
this fails to work as expected. This was tested with:

 # insmod samples/kprobes/kprobe_example.ko symbol="get_kprobe"

This fails to load as expected with:

insmod: ERROR: could not insert module samples/kprobes/kprobe_example.ko: Invalid parameters

v5: Use push_section_tbl() for _ASM_NOKPROBE() for x86, and
    _ASM_NOKPROBE_SYMBOL() on powerpc
v4: ported over _ASM_NOKPROBE_SYMBOL() on powerpc and
    ASM_NOKPROBE() on x86
v3: this patch was introduced in this series

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/powerpc/include/asm/ppc_asm.h |  4 ++--
 arch/x86/include/asm/asm.h         |  4 +++-
 include/asm-generic/kprobes.h      |  4 ++--
 include/asm-generic/vmlinux.lds.h  | 10 ----------
 include/linux/kprobes.h            |  2 ++
 kernel/kprobes.c                   | 11 ++++-------
 6 files changed, 13 insertions(+), 22 deletions(-)

diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 0846413b3a2e..20cd9c00eef5 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,7 +9,7 @@
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
 #include <asm/firmware.h>
-#include <asm/ranges.h>
+#include <asm/tables.h>
 
 #ifdef __ASSEMBLY__
 
@@ -266,7 +266,7 @@ GLUE(.,name):
  */
 #ifdef CONFIG_KPROBES
 #define _ASM_NOKPROBE_SYMBOL(entry)			\
-	.pushsection "_kprobe_blacklist","aw";		\
+	push_section_tbl(.init.data, _kprobe_blacklist, any, aw); \
 	PPC_LONG (entry) ;				\
 	.popsection
 #else
diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
index 7acb51c49fec..48b1bc85c0e6 100644
--- a/arch/x86/include/asm/asm.h
+++ b/arch/x86/include/asm/asm.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_ASM_H
 #define _ASM_X86_ASM_H
 
+#include <asm/tables.h>
+
 #ifdef __ASSEMBLY__
 # define __ASM_FORM(x)	x
 # define __ASM_FORM_RAW(x)     x
@@ -74,7 +76,7 @@
 	_ASM_EXTABLE_HANDLE(from, to, ex_handler_ext)
 
 # define _ASM_NOKPROBE(entry)					\
-	.pushsection "_kprobe_blacklist","aw" ;			\
+	push_section_tbl_any(.init.data, _kprobe_blacklist, aw);\
 	_ASM_ALIGN ;						\
 	_ASM_PTR (entry);					\
 	.popsection
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 02a26b975187..7d29a208390e 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,14 +3,14 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <linux/tables.h>
 #include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
  */
 # define __NOKPROBE_SYMBOL(fname)				\
-static unsigned long __used					\
-	__attribute__((__section__("_kprobe_blacklist")))	\
+static LINKTABLE_INIT_DATA(_kprobe_blacklist, all)		\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 499caf5b4361..9f062af1f728 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -114,15 +114,6 @@
 #define BRANCH_PROFILE()
 #endif
 
-#ifdef CONFIG_KPROBES
-#define KPROBE_BLACKLIST()	. = ALIGN(8);				      \
-				VMLINUX_SYMBOL(__start_kprobe_blacklist) = .; \
-				KEEP(*(_kprobe_blacklist))		      \
-				VMLINUX_SYMBOL(__stop_kprobe_blacklist) = .;
-#else
-#define KPROBE_BLACKLIST()
-#endif
-
 #ifdef CONFIG_EVENT_TRACING
 #define FTRACE_EVENTS()	. = ALIGN(8);					\
 			VMLINUX_SYMBOL(__start_ftrace_events) = .;	\
@@ -551,7 +542,6 @@
 	*(.init.rodata)							\
 	FTRACE_EVENTS()							\
 	TRACE_SYSCALLS()						\
-	KPROBE_BLACKLIST()						\
 	MEM_DISCARD(init.rodata)					\
 	CLK_OF_TABLES()							\
 	RESERVEDMEM_OF_TABLES()						\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 445cc6fe7afa..2707820cbb56 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -44,8 +44,10 @@
 
 #ifdef CONFIG_KPROBES
 #include <linux/ranges.h>
+#include <linux/tables.h>
 
 DECLARE_SECTION_RANGE(kprobes);
+DECLARE_LINKTABLE(unsigned long, _kprobe_blacklist);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 82191f328e21..9d102ac95256 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -2053,14 +2053,13 @@ NOKPROBE_SYMBOL(dump_kprobe);
  * since a kprobe need not necessarily be at the beginning
  * of a function.
  */
-static int __init populate_kprobe_blacklist(unsigned long *start,
-					     unsigned long *end)
+static int __init populate_kprobe_blacklist(void)
 {
 	unsigned long *iter;
 	struct kprobe_blacklist_entry *ent;
 	unsigned long entry, offset = 0, size = 0;
 
-	for (iter = start; iter < end; iter++) {
+	linktable_for_each(iter, _kprobe_blacklist) {
 		entry = arch_deref_entry_point((void *)*iter);
 
 		if (!kernel_text_address(entry) ||
@@ -2125,8 +2124,7 @@ static struct notifier_block kprobe_module_nb = {
 };
 
 /* Markers of _kprobe_blacklist section */
-extern unsigned long __start_kprobe_blacklist[];
-extern unsigned long __stop_kprobe_blacklist[];
+DEFINE_LINKTABLE_INIT_DATA(unsigned long, _kprobe_blacklist);
 
 /* Actual kprobes section range */
 DEFINE_SECTION_RANGE(kprobes, .text);
@@ -2143,8 +2141,7 @@ static int __init init_kprobes(void)
 		raw_spin_lock_init(&(kretprobe_table_locks[i].lock));
 	}
 
-	err = populate_kprobe_blacklist(__start_kprobe_blacklist,
-					__stop_kprobe_blacklist);
+	err = populate_kprobe_blacklist();
 	if (err) {
 		pr_err("kprobes: failed to populate blacklist: %d\n", err);
 		pr_err("Please take care of using kprobes.\n");
-- 
2.11.0


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 13/14] kprobes: port blacklist kprobes to linker table
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

kprobe makes use of two sections, the one dealing with the actual
kprobes was recently ported using the standard section range API.
The blacklist functionality of kprobes is still using a custom
section and declaring its custom section using the linker script
as follows:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist

This ports the _kprobe_blacklist custom section to the standard
Linux linker table API allowing us remove all the custom blacklist
kprobe section declarations from the linker script.

This has been tested by trying to register a kprobe on a blacklisted
symbol (these are declared with NOKPROBE_SYMBOL()), and confirms that
this fails to work as expected. This was tested with:

 # insmod samples/kprobes/kprobe_example.ko symbol="get_kprobe"

This fails to load as expected with:

insmod: ERROR: could not insert module samples/kprobes/kprobe_example.ko: Invalid parameters

v5: Use push_section_tbl() for _ASM_NOKPROBE() for x86, and
    _ASM_NOKPROBE_SYMBOL() on powerpc
v4: ported over _ASM_NOKPROBE_SYMBOL() on powerpc and
    ASM_NOKPROBE() on x86
v3: this patch was introduced in this series

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/powerpc/include/asm/ppc_asm.h |  4 ++--
 arch/x86/include/asm/asm.h         |  4 +++-
 include/asm-generic/kprobes.h      |  4 ++--
 include/asm-generic/vmlinux.lds.h  | 10 ----------
 include/linux/kprobes.h            |  2 ++
 kernel/kprobes.c                   | 11 ++++-------
 6 files changed, 13 insertions(+), 22 deletions(-)

diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 0846413b3a2e..20cd9c00eef5 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,7 +9,7 @@
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
 #include <asm/firmware.h>
-#include <asm/ranges.h>
+#include <asm/tables.h>
 
 #ifdef __ASSEMBLY__
 
@@ -266,7 +266,7 @@ GLUE(.,name):
  */
 #ifdef CONFIG_KPROBES
 #define _ASM_NOKPROBE_SYMBOL(entry)			\
-	.pushsection "_kprobe_blacklist","aw";		\
+	push_section_tbl(.init.data, _kprobe_blacklist, any, aw); \
 	PPC_LONG (entry) ;				\
 	.popsection
 #else
diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
index 7acb51c49fec..48b1bc85c0e6 100644
--- a/arch/x86/include/asm/asm.h
+++ b/arch/x86/include/asm/asm.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_ASM_H
 #define _ASM_X86_ASM_H
 
+#include <asm/tables.h>
+
 #ifdef __ASSEMBLY__
 # define __ASM_FORM(x)	x
 # define __ASM_FORM_RAW(x)     x
@@ -74,7 +76,7 @@
 	_ASM_EXTABLE_HANDLE(from, to, ex_handler_ext)
 
 # define _ASM_NOKPROBE(entry)					\
-	.pushsection "_kprobe_blacklist","aw" ;			\
+	push_section_tbl_any(.init.data, _kprobe_blacklist, aw);\
 	_ASM_ALIGN ;						\
 	_ASM_PTR (entry);					\
 	.popsection
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 02a26b975187..7d29a208390e 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,14 +3,14 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <linux/tables.h>
 #include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
  */
 # define __NOKPROBE_SYMBOL(fname)				\
-static unsigned long __used					\
-	__attribute__((__section__("_kprobe_blacklist")))	\
+static LINKTABLE_INIT_DATA(_kprobe_blacklist, all)		\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 499caf5b4361..9f062af1f728 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -114,15 +114,6 @@
 #define BRANCH_PROFILE()
 #endif
 
-#ifdef CONFIG_KPROBES
-#define KPROBE_BLACKLIST()	. = ALIGN(8);				      \
-				VMLINUX_SYMBOL(__start_kprobe_blacklist) = .; \
-				KEEP(*(_kprobe_blacklist))		      \
-				VMLINUX_SYMBOL(__stop_kprobe_blacklist) = .;
-#else
-#define KPROBE_BLACKLIST()
-#endif
-
 #ifdef CONFIG_EVENT_TRACING
 #define FTRACE_EVENTS()	. = ALIGN(8);					\
 			VMLINUX_SYMBOL(__start_ftrace_events) = .;	\
@@ -551,7 +542,6 @@
 	*(.init.rodata)							\
 	FTRACE_EVENTS()							\
 	TRACE_SYSCALLS()						\
-	KPROBE_BLACKLIST()						\
 	MEM_DISCARD(init.rodata)					\
 	CLK_OF_TABLES()							\
 	RESERVEDMEM_OF_TABLES()						\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 445cc6fe7afa..2707820cbb56 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -44,8 +44,10 @@
 
 #ifdef CONFIG_KPROBES
 #include <linux/ranges.h>
+#include <linux/tables.h>
 
 DECLARE_SECTION_RANGE(kprobes);
+DECLARE_LINKTABLE(unsigned long, _kprobe_blacklist);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 82191f328e21..9d102ac95256 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -2053,14 +2053,13 @@ NOKPROBE_SYMBOL(dump_kprobe);
  * since a kprobe need not necessarily be at the beginning
  * of a function.
  */
-static int __init populate_kprobe_blacklist(unsigned long *start,
-					     unsigned long *end)
+static int __init populate_kprobe_blacklist(void)
 {
 	unsigned long *iter;
 	struct kprobe_blacklist_entry *ent;
 	unsigned long entry, offset = 0, size = 0;
 
-	for (iter = start; iter < end; iter++) {
+	linktable_for_each(iter, _kprobe_blacklist) {
 		entry = arch_deref_entry_point((void *)*iter);
 
 		if (!kernel_text_address(entry) ||
@@ -2125,8 +2124,7 @@ static struct notifier_block kprobe_module_nb = {
 };
 
 /* Markers of _kprobe_blacklist section */
-extern unsigned long __start_kprobe_blacklist[];
-extern unsigned long __stop_kprobe_blacklist[];
+DEFINE_LINKTABLE_INIT_DATA(unsigned long, _kprobe_blacklist);
 
 /* Actual kprobes section range */
 DEFINE_SECTION_RANGE(kprobes, .text);
@@ -2143,8 +2141,7 @@ static int __init init_kprobes(void)
 		raw_spin_lock_init(&(kretprobe_table_locks[i].lock));
 	}
 
-	err = populate_kprobe_blacklist(__start_kprobe_blacklist,
-					__stop_kprobe_blacklist);
+	err = populate_kprobe_blacklist();
 	if (err) {
 		pr_err("kprobes: failed to populate blacklist: %d\n", err);
 		pr_err("Please take care of using kprobes.\n");
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 14/14] lib: add linker tables test driver
  2017-01-09 14:58       ` Luis R. Rodriguez
  (?)
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt

Add a test drivers for linker tables.

v6: rename table macro as suggested by Andy Shevchenko
v5: added this commit for the first time in this series.

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

diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 5655bd95919a..8c99ee3c9fd7 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1827,6 +1827,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 94ed5cc4e89c..b5c5a7a9146c 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..b78fb5b554cb
--- /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.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 14/14] lib: add linker tables test driver
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt, ak

Add a test drivers for linker tables.

v6: rename table macro as suggested by Andy Shevchenko
v5: added this commit for the first time in this series.

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

diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 5655bd95919a..8c99ee3c9fd7 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1827,6 +1827,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 94ed5cc4e89c..b5c5a7a9146c 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..b78fb5b554cb
--- /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.11.0


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v6 14/14] lib: add linker tables test driver
@ 2017-01-09 14:58         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 14:58 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

Add a test drivers for linker tables.

v6: rename table macro as suggested by Andy Shevchenko
v5: added this commit for the first time in this series.

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

diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 5655bd95919a..8c99ee3c9fd7 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1827,6 +1827,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 94ed5cc4e89c..b5c5a7a9146c 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..b78fb5b554cb
--- /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.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v3 0/6] tools: add linker table userspace sandbox
  2016-12-22  2:39       ` Luis R. Rodriguez
  (?)
@ 2017-01-09 15:02         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 15:02 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This v3 only modifies the tools sandbox to adjust for the linker tables
macro renames suggested by Andy Shevchenko. It applies after the kernel
changes, a public tree is available with both series applied [0] based on
linux-next tag next-20170109, if you pull from there please drop the last
patch as it is a debug patch used to force 0-day to force-enable the test
driver.

[0] https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h 170109-linker-tables-v6

  Luis

Luis R. Rodriguez (6):
  tools: add a userspace tools bug.h
  tools: add init.h for tools
  tools: add __used and enable to override
  tools: expand export.h with VMLINUX_SYMBOL()
  tools: add __section() to compiler.h
  tools: add userspace linker table sandbox

 Documentation/sections/linker-tables.rst           |   4 +-
 MAINTAINERS                                        |   1 +
 include/linux/tables.h                             |   5 +-
 tools/Makefile                                     |   3 +-
 .../arch/x86/include/generated/asm/section-core.h  |   1 +
 tools/arch/x86/include/generated/ranges.h          |   1 +
 tools/arch/x86/include/generated/tables.h          |   1 +
 tools/include/asm-generic/bug.h                    |  24 +
 tools/include/asm-generic/ranges.h                 |  93 +++
 tools/include/asm-generic/section-core.h           | 348 +++++++++++
 tools/include/asm-generic/tables.h                 |  48 ++
 tools/include/linux/bug.h                          |   6 +
 tools/include/linux/compiler.h                     |   8 +
 tools/include/linux/export.h                       |  22 +
 tools/include/linux/init.h                         |   9 +
 tools/include/linux/kernel.h                       |   2 +
 tools/include/linux/ranges.h                       | 183 ++++++
 tools/include/linux/sections.h                     |  87 +++
 tools/include/linux/string.h                       |   1 +
 tools/include/linux/tables.h                       | 684 +++++++++++++++++++++
 tools/linker-tables/.gitignore                     |   2 +
 tools/linker-tables/Makefile                       | 184 ++++++
 tools/linker-tables/README                         | 114 ++++
 tools/linker-tables/arch/x86/include/asm/asm.h     |  17 +
 tools/linker-tables/arch/x86/include/asm/boot.h    |   1 +
 .../linker-tables/arch/x86/include/asm/bootparam.h |  32 +
 tools/linker-tables/arch/x86/include/asm/kprobes.h |   7 +
 .../linker-tables/arch/x86/include/asm/ps_const.h  |  23 +
 tools/linker-tables/arch/x86/include/asm/ranges.h  |   6 +
 .../arch/x86/include/asm/section-core.h            |   1 +
 tools/linker-tables/arch/x86/include/asm/setup.h   |   6 +
 tools/linker-tables/arch/x86/include/asm/tables.h  |   6 +
 tools/linker-tables/arch/x86/include/asm/x86.h     |   4 +
 .../arch/x86/include/asm/x86_init_fn.h             | 169 +++++
 tools/linker-tables/arch/x86/kernel/alpha.c        |   9 +
 tools/linker-tables/arch/x86/kernel/alternative.c  |  31 +
 tools/linker-tables/arch/x86/kernel/beta.c         |   9 +
 tools/linker-tables/arch/x86/kernel/head64.c       |  58 ++
 tools/linker-tables/arch/x86/kernel/init.c         |  42 ++
 tools/linker-tables/arch/x86/kernel/kasan.c        |  10 +
 tools/linker-tables/arch/x86/kernel/kprobes.c      |  51 ++
 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S  | 277 +++++++++
 tools/linker-tables/arch/x86/mm/init.c             |  10 +
 tools/linker-tables/arch/x86/xen/init.c            |  13 +
 tools/linker-tables/drivers/acme.c                 |  32 +
 tools/linker-tables/drivers/synth/common.c         |  16 +
 tools/linker-tables/drivers/synth/common.h         |   2 +
 tools/linker-tables/drivers/synth/main.c           |  35 ++
 tools/linker-tables/drivers/synth/or.S             |  39 ++
 tools/linker-tables/drivers/synth/synth.h          |   2 +
 tools/linker-tables/drivers/xen-driver.c           |  11 +
 .../include/asm-generic/arch_init_fn.h             |  50 ++
 tools/linker-tables/include/asm-generic/kprobes.h  |  26 +
 tools/linker-tables/include/linux/bitops.h         |   6 +
 tools/linker-tables/include/linux/init.h           |  40 ++
 tools/linker-tables/include/linux/kasan.h          |   5 +
 tools/linker-tables/include/linux/kernel.h         |   2 +
 tools/linker-tables/include/linux/kprobes.h        |  11 +
 tools/linker-tables/include/linux/module.h         |  14 +
 tools/linker-tables/include/linux/mutex.h          |  17 +
 tools/linker-tables/include/linux/pci.h            |   7 +
 tools/linker-tables/include/linux/printk.h         |  26 +
 tools/linker-tables/include/linux/ps_const.h       |  46 ++
 tools/linker-tables/include/linux/sched.h          |   9 +
 tools/linker-tables/include/linux/spinlock.h       |  13 +
 tools/linker-tables/include/linux/start_kernel.h   |   1 +
 tools/linker-tables/include/linux/types.h          |  13 +
 tools/linker-tables/include/linux/workqueue.h      |  51 ++
 tools/linker-tables/include/xen/xen.h              |   4 +
 tools/linker-tables/kernel/locking/mutex.c         |  28 +
 tools/linker-tables/kernel/locking/spinlock.c      |  26 +
 tools/linker-tables/kernel/main.c                  |  32 +
 tools/linker-tables/kernel/workqueue.c             |  43 ++
 tools/linker-tables/lib/string.c                   |  26 +
 tools/linker-tables/main.c                         |  20 +
 tools/linker-tables/pci-quirks.c                   |  13 +
 tools/linker-tables/pci.c                          |  29 +
 77 files changed, 3303 insertions(+), 5 deletions(-)
 create mode 100644 tools/arch/x86/include/generated/asm/section-core.h
 create mode 100644 tools/arch/x86/include/generated/ranges.h
 create mode 100644 tools/arch/x86/include/generated/tables.h
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/asm-generic/ranges.h
 create mode 100644 tools/include/asm-generic/section-core.h
 create mode 100644 tools/include/asm-generic/tables.h
 create mode 100644 tools/include/linux/bug.h
 create mode 100644 tools/include/linux/init.h
 create mode 100644 tools/include/linux/ranges.h
 create mode 100644 tools/include/linux/sections.h
 create mode 100644 tools/include/linux/tables.h
 create mode 100644 tools/linker-tables/.gitignore
 create mode 100644 tools/linker-tables/Makefile
 create mode 100644 tools/linker-tables/README
 create mode 100644 tools/linker-tables/arch/x86/include/asm/asm.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/boot.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/bootparam.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/kprobes.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ps_const.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ranges.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/section-core.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/setup.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/tables.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
 create mode 100644 tools/linker-tables/arch/x86/kernel/alpha.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/alternative.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/beta.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/head64.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/init.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kasan.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kprobes.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
 create mode 100644 tools/linker-tables/arch/x86/mm/init.c
 create mode 100644 tools/linker-tables/arch/x86/xen/init.c
 create mode 100644 tools/linker-tables/drivers/acme.c
 create mode 100644 tools/linker-tables/drivers/synth/common.c
 create mode 100644 tools/linker-tables/drivers/synth/common.h
 create mode 100644 tools/linker-tables/drivers/synth/main.c
 create mode 100644 tools/linker-tables/drivers/synth/or.S
 create mode 100644 tools/linker-tables/drivers/synth/synth.h
 create mode 100644 tools/linker-tables/drivers/xen-driver.c
 create mode 100644 tools/linker-tables/include/asm-generic/arch_init_fn.h
 create mode 100644 tools/linker-tables/include/asm-generic/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/bitops.h
 create mode 100644 tools/linker-tables/include/linux/init.h
 create mode 100644 tools/linker-tables/include/linux/kasan.h
 create mode 100644 tools/linker-tables/include/linux/kernel.h
 create mode 100644 tools/linker-tables/include/linux/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/module.h
 create mode 100644 tools/linker-tables/include/linux/mutex.h
 create mode 100644 tools/linker-tables/include/linux/pci.h
 create mode 100644 tools/linker-tables/include/linux/printk.h
 create mode 100644 tools/linker-tables/include/linux/ps_const.h
 create mode 100644 tools/linker-tables/include/linux/sched.h
 create mode 100644 tools/linker-tables/include/linux/spinlock.h
 create mode 100644 tools/linker-tables/include/linux/start_kernel.h
 create mode 100644 tools/linker-tables/include/linux/types.h
 create mode 100644 tools/linker-tables/include/linux/workqueue.h
 create mode 100644 tools/linker-tables/include/xen/xen.h
 create mode 100644 tools/linker-tables/kernel/locking/mutex.c
 create mode 100644 tools/linker-tables/kernel/locking/spinlock.c
 create mode 100644 tools/linker-tables/kernel/main.c
 create mode 100644 tools/linker-tables/kernel/workqueue.c
 create mode 100644 tools/linker-tables/lib/string.c
 create mode 100644 tools/linker-tables/main.c
 create mode 100644 tools/linker-tables/pci-quirks.c
 create mode 100644 tools/linker-tables/pci.c

-- 
2.11.0


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v3 0/6] tools: add linker table userspace sandbox
@ 2017-01-09 15:02         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 15:02 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This v3 only modifies the tools sandbox to adjust for the linker tables
macro renames suggested by Andy Shevchenko. It applies after the kernel
changes, a public tree is available with both series applied [0] based on
linux-next tag next-20170109, if you pull from there please drop the last
patch as it is a debug patch used to force 0-day to force-enable the test
driver.

[0] https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h=20170109-linker-tables-v6

  Luis

Luis R. Rodriguez (6):
  tools: add a userspace tools bug.h
  tools: add init.h for tools
  tools: add __used and enable to override
  tools: expand export.h with VMLINUX_SYMBOL()
  tools: add __section() to compiler.h
  tools: add userspace linker table sandbox

 Documentation/sections/linker-tables.rst           |   4 +-
 MAINTAINERS                                        |   1 +
 include/linux/tables.h                             |   5 +-
 tools/Makefile                                     |   3 +-
 .../arch/x86/include/generated/asm/section-core.h  |   1 +
 tools/arch/x86/include/generated/ranges.h          |   1 +
 tools/arch/x86/include/generated/tables.h          |   1 +
 tools/include/asm-generic/bug.h                    |  24 +
 tools/include/asm-generic/ranges.h                 |  93 +++
 tools/include/asm-generic/section-core.h           | 348 +++++++++++
 tools/include/asm-generic/tables.h                 |  48 ++
 tools/include/linux/bug.h                          |   6 +
 tools/include/linux/compiler.h                     |   8 +
 tools/include/linux/export.h                       |  22 +
 tools/include/linux/init.h                         |   9 +
 tools/include/linux/kernel.h                       |   2 +
 tools/include/linux/ranges.h                       | 183 ++++++
 tools/include/linux/sections.h                     |  87 +++
 tools/include/linux/string.h                       |   1 +
 tools/include/linux/tables.h                       | 684 +++++++++++++++++++++
 tools/linker-tables/.gitignore                     |   2 +
 tools/linker-tables/Makefile                       | 184 ++++++
 tools/linker-tables/README                         | 114 ++++
 tools/linker-tables/arch/x86/include/asm/asm.h     |  17 +
 tools/linker-tables/arch/x86/include/asm/boot.h    |   1 +
 .../linker-tables/arch/x86/include/asm/bootparam.h |  32 +
 tools/linker-tables/arch/x86/include/asm/kprobes.h |   7 +
 .../linker-tables/arch/x86/include/asm/ps_const.h  |  23 +
 tools/linker-tables/arch/x86/include/asm/ranges.h  |   6 +
 .../arch/x86/include/asm/section-core.h            |   1 +
 tools/linker-tables/arch/x86/include/asm/setup.h   |   6 +
 tools/linker-tables/arch/x86/include/asm/tables.h  |   6 +
 tools/linker-tables/arch/x86/include/asm/x86.h     |   4 +
 .../arch/x86/include/asm/x86_init_fn.h             | 169 +++++
 tools/linker-tables/arch/x86/kernel/alpha.c        |   9 +
 tools/linker-tables/arch/x86/kernel/alternative.c  |  31 +
 tools/linker-tables/arch/x86/kernel/beta.c         |   9 +
 tools/linker-tables/arch/x86/kernel/head64.c       |  58 ++
 tools/linker-tables/arch/x86/kernel/init.c         |  42 ++
 tools/linker-tables/arch/x86/kernel/kasan.c        |  10 +
 tools/linker-tables/arch/x86/kernel/kprobes.c      |  51 ++
 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S  | 277 +++++++++
 tools/linker-tables/arch/x86/mm/init.c             |  10 +
 tools/linker-tables/arch/x86/xen/init.c            |  13 +
 tools/linker-tables/drivers/acme.c                 |  32 +
 tools/linker-tables/drivers/synth/common.c         |  16 +
 tools/linker-tables/drivers/synth/common.h         |   2 +
 tools/linker-tables/drivers/synth/main.c           |  35 ++
 tools/linker-tables/drivers/synth/or.S             |  39 ++
 tools/linker-tables/drivers/synth/synth.h          |   2 +
 tools/linker-tables/drivers/xen-driver.c           |  11 +
 .../include/asm-generic/arch_init_fn.h             |  50 ++
 tools/linker-tables/include/asm-generic/kprobes.h  |  26 +
 tools/linker-tables/include/linux/bitops.h         |   6 +
 tools/linker-tables/include/linux/init.h           |  40 ++
 tools/linker-tables/include/linux/kasan.h          |   5 +
 tools/linker-tables/include/linux/kernel.h         |   2 +
 tools/linker-tables/include/linux/kprobes.h        |  11 +
 tools/linker-tables/include/linux/module.h         |  14 +
 tools/linker-tables/include/linux/mutex.h          |  17 +
 tools/linker-tables/include/linux/pci.h            |   7 +
 tools/linker-tables/include/linux/printk.h         |  26 +
 tools/linker-tables/include/linux/ps_const.h       |  46 ++
 tools/linker-tables/include/linux/sched.h          |   9 +
 tools/linker-tables/include/linux/spinlock.h       |  13 +
 tools/linker-tables/include/linux/start_kernel.h   |   1 +
 tools/linker-tables/include/linux/types.h          |  13 +
 tools/linker-tables/include/linux/workqueue.h      |  51 ++
 tools/linker-tables/include/xen/xen.h              |   4 +
 tools/linker-tables/kernel/locking/mutex.c         |  28 +
 tools/linker-tables/kernel/locking/spinlock.c      |  26 +
 tools/linker-tables/kernel/main.c                  |  32 +
 tools/linker-tables/kernel/workqueue.c             |  43 ++
 tools/linker-tables/lib/string.c                   |  26 +
 tools/linker-tables/main.c                         |  20 +
 tools/linker-tables/pci-quirks.c                   |  13 +
 tools/linker-tables/pci.c                          |  29 +
 77 files changed, 3303 insertions(+), 5 deletions(-)
 create mode 100644 tools/arch/x86/include/generated/asm/section-core.h
 create mode 100644 tools/arch/x86/include/generated/ranges.h
 create mode 100644 tools/arch/x86/include/generated/tables.h
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/asm-generic/ranges.h
 create mode 100644 tools/include/asm-generic/section-core.h
 create mode 100644 tools/include/asm-generic/tables.h
 create mode 100644 tools/include/linux/bug.h
 create mode 100644 tools/include/linux/init.h
 create mode 100644 tools/include/linux/ranges.h
 create mode 100644 tools/include/linux/sections.h
 create mode 100644 tools/include/linux/tables.h
 create mode 100644 tools/linker-tables/.gitignore
 create mode 100644 tools/linker-tables/Makefile
 create mode 100644 tools/linker-tables/README
 create mode 100644 tools/linker-tables/arch/x86/include/asm/asm.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/boot.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/bootparam.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/kprobes.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ps_const.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ranges.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/section-core.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/setup.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/tables.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
 create mode 100644 tools/linker-tables/arch/x86/kernel/alpha.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/alternative.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/beta.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/head64.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/init.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kasan.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kprobes.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
 create mode 100644 tools/linker-tables/arch/x86/mm/init.c
 create mode 100644 tools/linker-tables/arch/x86/xen/init.c
 create mode 100644 tools/linker-tables/drivers/acme.c
 create mode 100644 tools/linker-tables/drivers/synth/common.c
 create mode 100644 tools/linker-tables/drivers/synth/common.h
 create mode 100644 tools/linker-tables/drivers/synth/main.c
 create mode 100644 tools/linker-tables/drivers/synth/or.S
 create mode 100644 tools/linker-tables/drivers/synth/synth.h
 create mode 100644 tools/linker-tables/drivers/xen-driver.c
 create mode 100644 tools/linker-tables/include/asm-generic/arch_init_fn.h
 create mode 100644 tools/linker-tables/include/asm-generic/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/bitops.h
 create mode 100644 tools/linker-tables/include/linux/init.h
 create mode 100644 tools/linker-tables/include/linux/kasan.h
 create mode 100644 tools/linker-tables/include/linux/kernel.h
 create mode 100644 tools/linker-tables/include/linux/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/module.h
 create mode 100644 tools/linker-tables/include/linux/mutex.h
 create mode 100644 tools/linker-tables/include/linux/pci.h
 create mode 100644 tools/linker-tables/include/linux/printk.h
 create mode 100644 tools/linker-tables/include/linux/ps_const.h
 create mode 100644 tools/linker-tables/include/linux/sched.h
 create mode 100644 tools/linker-tables/include/linux/spinlock.h
 create mode 100644 tools/linker-tables/include/linux/start_kernel.h
 create mode 100644 tools/linker-tables/include/linux/types.h
 create mode 100644 tools/linker-tables/include/linux/workqueue.h
 create mode 100644 tools/linker-tables/include/xen/xen.h
 create mode 100644 tools/linker-tables/kernel/locking/mutex.c
 create mode 100644 tools/linker-tables/kernel/locking/spinlock.c
 create mode 100644 tools/linker-tables/kernel/main.c
 create mode 100644 tools/linker-tables/kernel/workqueue.c
 create mode 100644 tools/linker-tables/lib/string.c
 create mode 100644 tools/linker-tables/main.c
 create mode 100644 tools/linker-tables/pci-quirks.c
 create mode 100644 tools/linker-tables/pci.c

-- 
2.11.0


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v3 0/6] tools: add linker table userspace sandbox
@ 2017-01-09 15:02         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 15:02 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

This v3 only modifies the tools sandbox to adjust for the linker tables
macro renames suggested by Andy Shevchenko. It applies after the kernel
changes, a public tree is available with both series applied [0] based on
linux-next tag next-20170109, if you pull from there please drop the last
patch as it is a debug patch used to force 0-day to force-enable the test
driver.

[0] https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h=20170109-linker-tables-v6

  Luis

Luis R. Rodriguez (6):
  tools: add a userspace tools bug.h
  tools: add init.h for tools
  tools: add __used and enable to override
  tools: expand export.h with VMLINUX_SYMBOL()
  tools: add __section() to compiler.h
  tools: add userspace linker table sandbox

 Documentation/sections/linker-tables.rst           |   4 +-
 MAINTAINERS                                        |   1 +
 include/linux/tables.h                             |   5 +-
 tools/Makefile                                     |   3 +-
 .../arch/x86/include/generated/asm/section-core.h  |   1 +
 tools/arch/x86/include/generated/ranges.h          |   1 +
 tools/arch/x86/include/generated/tables.h          |   1 +
 tools/include/asm-generic/bug.h                    |  24 +
 tools/include/asm-generic/ranges.h                 |  93 +++
 tools/include/asm-generic/section-core.h           | 348 +++++++++++
 tools/include/asm-generic/tables.h                 |  48 ++
 tools/include/linux/bug.h                          |   6 +
 tools/include/linux/compiler.h                     |   8 +
 tools/include/linux/export.h                       |  22 +
 tools/include/linux/init.h                         |   9 +
 tools/include/linux/kernel.h                       |   2 +
 tools/include/linux/ranges.h                       | 183 ++++++
 tools/include/linux/sections.h                     |  87 +++
 tools/include/linux/string.h                       |   1 +
 tools/include/linux/tables.h                       | 684 +++++++++++++++++++++
 tools/linker-tables/.gitignore                     |   2 +
 tools/linker-tables/Makefile                       | 184 ++++++
 tools/linker-tables/README                         | 114 ++++
 tools/linker-tables/arch/x86/include/asm/asm.h     |  17 +
 tools/linker-tables/arch/x86/include/asm/boot.h    |   1 +
 .../linker-tables/arch/x86/include/asm/bootparam.h |  32 +
 tools/linker-tables/arch/x86/include/asm/kprobes.h |   7 +
 .../linker-tables/arch/x86/include/asm/ps_const.h  |  23 +
 tools/linker-tables/arch/x86/include/asm/ranges.h  |   6 +
 .../arch/x86/include/asm/section-core.h            |   1 +
 tools/linker-tables/arch/x86/include/asm/setup.h   |   6 +
 tools/linker-tables/arch/x86/include/asm/tables.h  |   6 +
 tools/linker-tables/arch/x86/include/asm/x86.h     |   4 +
 .../arch/x86/include/asm/x86_init_fn.h             | 169 +++++
 tools/linker-tables/arch/x86/kernel/alpha.c        |   9 +
 tools/linker-tables/arch/x86/kernel/alternative.c  |  31 +
 tools/linker-tables/arch/x86/kernel/beta.c         |   9 +
 tools/linker-tables/arch/x86/kernel/head64.c       |  58 ++
 tools/linker-tables/arch/x86/kernel/init.c         |  42 ++
 tools/linker-tables/arch/x86/kernel/kasan.c        |  10 +
 tools/linker-tables/arch/x86/kernel/kprobes.c      |  51 ++
 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S  | 277 +++++++++
 tools/linker-tables/arch/x86/mm/init.c             |  10 +
 tools/linker-tables/arch/x86/xen/init.c            |  13 +
 tools/linker-tables/drivers/acme.c                 |  32 +
 tools/linker-tables/drivers/synth/common.c         |  16 +
 tools/linker-tables/drivers/synth/common.h         |   2 +
 tools/linker-tables/drivers/synth/main.c           |  35 ++
 tools/linker-tables/drivers/synth/or.S             |  39 ++
 tools/linker-tables/drivers/synth/synth.h          |   2 +
 tools/linker-tables/drivers/xen-driver.c           |  11 +
 .../include/asm-generic/arch_init_fn.h             |  50 ++
 tools/linker-tables/include/asm-generic/kprobes.h  |  26 +
 tools/linker-tables/include/linux/bitops.h         |   6 +
 tools/linker-tables/include/linux/init.h           |  40 ++
 tools/linker-tables/include/linux/kasan.h          |   5 +
 tools/linker-tables/include/linux/kernel.h         |   2 +
 tools/linker-tables/include/linux/kprobes.h        |  11 +
 tools/linker-tables/include/linux/module.h         |  14 +
 tools/linker-tables/include/linux/mutex.h          |  17 +
 tools/linker-tables/include/linux/pci.h            |   7 +
 tools/linker-tables/include/linux/printk.h         |  26 +
 tools/linker-tables/include/linux/ps_const.h       |  46 ++
 tools/linker-tables/include/linux/sched.h          |   9 +
 tools/linker-tables/include/linux/spinlock.h       |  13 +
 tools/linker-tables/include/linux/start_kernel.h   |   1 +
 tools/linker-tables/include/linux/types.h          |  13 +
 tools/linker-tables/include/linux/workqueue.h      |  51 ++
 tools/linker-tables/include/xen/xen.h              |   4 +
 tools/linker-tables/kernel/locking/mutex.c         |  28 +
 tools/linker-tables/kernel/locking/spinlock.c      |  26 +
 tools/linker-tables/kernel/main.c                  |  32 +
 tools/linker-tables/kernel/workqueue.c             |  43 ++
 tools/linker-tables/lib/string.c                   |  26 +
 tools/linker-tables/main.c                         |  20 +
 tools/linker-tables/pci-quirks.c                   |  13 +
 tools/linker-tables/pci.c                          |  29 +
 77 files changed, 3303 insertions(+), 5 deletions(-)
 create mode 100644 tools/arch/x86/include/generated/asm/section-core.h
 create mode 100644 tools/arch/x86/include/generated/ranges.h
 create mode 100644 tools/arch/x86/include/generated/tables.h
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/asm-generic/ranges.h
 create mode 100644 tools/include/asm-generic/section-core.h
 create mode 100644 tools/include/asm-generic/tables.h
 create mode 100644 tools/include/linux/bug.h
 create mode 100644 tools/include/linux/init.h
 create mode 100644 tools/include/linux/ranges.h
 create mode 100644 tools/include/linux/sections.h
 create mode 100644 tools/include/linux/tables.h
 create mode 100644 tools/linker-tables/.gitignore
 create mode 100644 tools/linker-tables/Makefile
 create mode 100644 tools/linker-tables/README
 create mode 100644 tools/linker-tables/arch/x86/include/asm/asm.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/boot.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/bootparam.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/kprobes.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ps_const.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ranges.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/section-core.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/setup.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/tables.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
 create mode 100644 tools/linker-tables/arch/x86/kernel/alpha.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/alternative.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/beta.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/head64.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/init.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kasan.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kprobes.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
 create mode 100644 tools/linker-tables/arch/x86/mm/init.c
 create mode 100644 tools/linker-tables/arch/x86/xen/init.c
 create mode 100644 tools/linker-tables/drivers/acme.c
 create mode 100644 tools/linker-tables/drivers/synth/common.c
 create mode 100644 tools/linker-tables/drivers/synth/common.h
 create mode 100644 tools/linker-tables/drivers/synth/main.c
 create mode 100644 tools/linker-tables/drivers/synth/or.S
 create mode 100644 tools/linker-tables/drivers/synth/synth.h
 create mode 100644 tools/linker-tables/drivers/xen-driver.c
 create mode 100644 tools/linker-tables/include/asm-generic/arch_init_fn.h
 create mode 100644 tools/linker-tables/include/asm-generic/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/bitops.h
 create mode 100644 tools/linker-tables/include/linux/init.h
 create mode 100644 tools/linker-tables/include/linux/kasan.h
 create mode 100644 tools/linker-tables/include/linux/kernel.h
 create mode 100644 tools/linker-tables/include/linux/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/module.h
 create mode 100644 tools/linker-tables/include/linux/mutex.h
 create mode 100644 tools/linker-tables/include/linux/pci.h
 create mode 100644 tools/linker-tables/include/linux/printk.h
 create mode 100644 tools/linker-tables/include/linux/ps_const.h
 create mode 100644 tools/linker-tables/include/linux/sched.h
 create mode 100644 tools/linker-tables/include/linux/spinlock.h
 create mode 100644 tools/linker-tables/include/linux/start_kernel.h
 create mode 100644 tools/linker-tables/include/linux/types.h
 create mode 100644 tools/linker-tables/include/linux/workqueue.h
 create mode 100644 tools/linker-tables/include/xen/xen.h
 create mode 100644 tools/linker-tables/kernel/locking/mutex.c
 create mode 100644 tools/linker-tables/kernel/locking/spinlock.c
 create mode 100644 tools/linker-tables/kernel/main.c
 create mode 100644 tools/linker-tables/kernel/workqueue.c
 create mode 100644 tools/linker-tables/lib/string.c
 create mode 100644 tools/linker-tables/main.c
 create mode 100644 tools/linker-tables/pci-quirks.c
 create mode 100644 tools/linker-tables/pci.c

-- 
2.11.0


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v3 1/6] tools: add a userspace tools bug.h
  2017-01-09 15:02         ` Luis R. Rodriguez
  (?)
@ 2017-01-09 15:02           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 15:02 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This will be used later by the userspace linker-tables sandbox.
As a convenience, include bug.h on kernel.h -- this is not done
on upstream kernel.h, however most header files do include bug.h
eventually, if we were to only add the ones that need it we'd
need to copy a lot of headers to tools for the ony purpose of
includeing bug.h. This simplifies that.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/asm-generic/bug.h | 24 ++++++++++++++++++++++++
 tools/include/linux/bug.h       |  6 ++++++
 tools/include/linux/kernel.h    |  2 ++
 3 files changed, 32 insertions(+)
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/linux/bug.h

diff --git a/tools/include/asm-generic/bug.h b/tools/include/asm-generic/bug.h
new file mode 100644
index 000000000000..7b0f48b60dbe
--- /dev/null
+++ b/tools/include/asm-generic/bug.h
@@ -0,0 +1,24 @@
+#ifndef __TOOLS_ASM_GENERIC_BUG
+#define __TOOLS_ASM_GENERIC_BUG
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define BUG() do {										\
+	fprintf(stderr, "----------------------------------------------------------\n");	\
+	fprintf (stderr, "BUG on %s at %s: %i\n", __func__, __FILE__, __LINE__);		\
+	abort();										\
+}												\
+while (0)
+
+#define BUG_ON(cond) do { if (cond) BUG(); } while (0)
+
+#define WARN_ON(__test) do {									\
+	if (__test) {										\
+		fprintf(stderr, "----------------------------------------------------------\n");\
+		fprintf (stderr, "WARN_ON on %s at %s: %i\n", __func__, __FILE__, __LINE__);	\
+	}											\
+}												\
+while (0)
+
+#endif /* __TOOLS_ASM_GENERIC_BUG */
diff --git a/tools/include/linux/bug.h b/tools/include/linux/bug.h
new file mode 100644
index 000000000000..9be515b40b5c
--- /dev/null
+++ b/tools/include/linux/bug.h
@@ -0,0 +1,6 @@
+#ifndef _TOOLS_LINUX_BUG_H
+#define _TOOLS_LINUX_BUG_H
+
+#include <asm-generic/bug.h>
+
+#endif /* _TOOLS_LINUX_BUG_H */
diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
index 28607db02bd3..3d385a6d4fc1 100644
--- a/tools/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -5,6 +5,8 @@
 #include <stddef.h>
 #include <assert.h>
 
+#include <linux/bug.h>
+
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 
 #define PERF_ALIGN(x, a)	__PERF_ALIGN_MASK(x, (typeof(x))(a)-1)
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v3 1/6] tools: add a userspace tools bug.h
@ 2017-01-09 15:02           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 15:02 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This will be used later by the userspace linker-tables sandbox.
As a convenience, include bug.h on kernel.h -- this is not done
on upstream kernel.h, however most header files do include bug.h
eventually, if we were to only add the ones that need it we'd
need to copy a lot of headers to tools for the ony purpose of
includeing bug.h. This simplifies that.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/asm-generic/bug.h | 24 ++++++++++++++++++++++++
 tools/include/linux/bug.h       |  6 ++++++
 tools/include/linux/kernel.h    |  2 ++
 3 files changed, 32 insertions(+)
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/linux/bug.h

diff --git a/tools/include/asm-generic/bug.h b/tools/include/asm-generic/bug.h
new file mode 100644
index 000000000000..7b0f48b60dbe
--- /dev/null
+++ b/tools/include/asm-generic/bug.h
@@ -0,0 +1,24 @@
+#ifndef __TOOLS_ASM_GENERIC_BUG
+#define __TOOLS_ASM_GENERIC_BUG
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define BUG() do {										\
+	fprintf(stderr, "----------------------------------------------------------\n");	\
+	fprintf (stderr, "BUG on %s at %s: %i\n", __func__, __FILE__, __LINE__);		\
+	abort();										\
+}												\
+while (0)
+
+#define BUG_ON(cond) do { if (cond) BUG(); } while (0)
+
+#define WARN_ON(__test) do {									\
+	if (__test) {										\
+		fprintf(stderr, "----------------------------------------------------------\n");\
+		fprintf (stderr, "WARN_ON on %s at %s: %i\n", __func__, __FILE__, __LINE__);	\
+	}											\
+}												\
+while (0)
+
+#endif /* __TOOLS_ASM_GENERIC_BUG */
diff --git a/tools/include/linux/bug.h b/tools/include/linux/bug.h
new file mode 100644
index 000000000000..9be515b40b5c
--- /dev/null
+++ b/tools/include/linux/bug.h
@@ -0,0 +1,6 @@
+#ifndef _TOOLS_LINUX_BUG_H
+#define _TOOLS_LINUX_BUG_H
+
+#include <asm-generic/bug.h>
+
+#endif /* _TOOLS_LINUX_BUG_H */
diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
index 28607db02bd3..3d385a6d4fc1 100644
--- a/tools/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -5,6 +5,8 @@
 #include <stddef.h>
 #include <assert.h>
 
+#include <linux/bug.h>
+
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 
 #define PERF_ALIGN(x, a)	__PERF_ALIGN_MASK(x, (typeof(x))(a)-1)
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v3 1/6] tools: add a userspace tools bug.h
@ 2017-01-09 15:02           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 15:02 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

This will be used later by the userspace linker-tables sandbox.
As a convenience, include bug.h on kernel.h -- this is not done
on upstream kernel.h, however most header files do include bug.h
eventually, if we were to only add the ones that need it we'd
need to copy a lot of headers to tools for the ony purpose of
includeing bug.h. This simplifies that.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/asm-generic/bug.h | 24 ++++++++++++++++++++++++
 tools/include/linux/bug.h       |  6 ++++++
 tools/include/linux/kernel.h    |  2 ++
 3 files changed, 32 insertions(+)
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/linux/bug.h

diff --git a/tools/include/asm-generic/bug.h b/tools/include/asm-generic/bug.h
new file mode 100644
index 000000000000..7b0f48b60dbe
--- /dev/null
+++ b/tools/include/asm-generic/bug.h
@@ -0,0 +1,24 @@
+#ifndef __TOOLS_ASM_GENERIC_BUG
+#define __TOOLS_ASM_GENERIC_BUG
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define BUG() do {										\
+	fprintf(stderr, "----------------------------------------------------------\n");	\
+	fprintf (stderr, "BUG on %s at %s: %i\n", __func__, __FILE__, __LINE__);		\
+	abort();										\
+}												\
+while (0)
+
+#define BUG_ON(cond) do { if (cond) BUG(); } while (0)
+
+#define WARN_ON(__test) do {									\
+	if (__test) {										\
+		fprintf(stderr, "----------------------------------------------------------\n");\
+		fprintf (stderr, "WARN_ON on %s at %s: %i\n", __func__, __FILE__, __LINE__);	\
+	}											\
+}												\
+while (0)
+
+#endif /* __TOOLS_ASM_GENERIC_BUG */
diff --git a/tools/include/linux/bug.h b/tools/include/linux/bug.h
new file mode 100644
index 000000000000..9be515b40b5c
--- /dev/null
+++ b/tools/include/linux/bug.h
@@ -0,0 +1,6 @@
+#ifndef _TOOLS_LINUX_BUG_H
+#define _TOOLS_LINUX_BUG_H
+
+#include <asm-generic/bug.h>
+
+#endif /* _TOOLS_LINUX_BUG_H */
diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
index 28607db02bd3..3d385a6d4fc1 100644
--- a/tools/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -5,6 +5,8 @@
 #include <stddef.h>
 #include <assert.h>
 
+#include <linux/bug.h>
+
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 
 #define PERF_ALIGN(x, a)	__PERF_ALIGN_MASK(x, (typeof(x))(a)-1)
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v3 2/6] tools: add init.h for tools
  2017-01-09 15:02         ` Luis R. Rodriguez
  (?)
@ 2017-01-09 15:02           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 15:02 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Start off with just __ref -- we enalbe you to override, if you do
that then you can define your own. The way you'd use this, if you
do override, is define your own __ref and then use include_next.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/init.h | 9 +++++++++
 1 file changed, 9 insertions(+)
 create mode 100644 tools/include/linux/init.h

diff --git a/tools/include/linux/init.h b/tools/include/linux/init.h
new file mode 100644
index 000000000000..6d970a360a05
--- /dev/null
+++ b/tools/include/linux/init.h
@@ -0,0 +1,9 @@
+#ifndef _TOOLS_LINUX_INIT_H
+#define _TOOLS_LINUX_INIT_H
+
+/* this means you can add your own to fit you own userspace needs */
+#ifndef __ref
+#define __ref
+#endif
+
+#endif /* _TOOLS_LINUX_INIT_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v3 2/6] tools: add init.h for tools
@ 2017-01-09 15:02           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 15:02 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Start off with just __ref -- we enalbe you to override, if you do
that then you can define your own. The way you'd use this, if you
do override, is define your own __ref and then use include_next.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/init.h | 9 +++++++++
 1 file changed, 9 insertions(+)
 create mode 100644 tools/include/linux/init.h

diff --git a/tools/include/linux/init.h b/tools/include/linux/init.h
new file mode 100644
index 000000000000..6d970a360a05
--- /dev/null
+++ b/tools/include/linux/init.h
@@ -0,0 +1,9 @@
+#ifndef _TOOLS_LINUX_INIT_H
+#define _TOOLS_LINUX_INIT_H
+
+/* this means you can add your own to fit you own userspace needs */
+#ifndef __ref
+#define __ref
+#endif
+
+#endif /* _TOOLS_LINUX_INIT_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v3 2/6] tools: add init.h for tools
@ 2017-01-09 15:02           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 15:02 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

Start off with just __ref -- we enalbe you to override, if you do
that then you can define your own. The way you'd use this, if you
do override, is define your own __ref and then use include_next.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/init.h | 9 +++++++++
 1 file changed, 9 insertions(+)
 create mode 100644 tools/include/linux/init.h

diff --git a/tools/include/linux/init.h b/tools/include/linux/init.h
new file mode 100644
index 000000000000..6d970a360a05
--- /dev/null
+++ b/tools/include/linux/init.h
@@ -0,0 +1,9 @@
+#ifndef _TOOLS_LINUX_INIT_H
+#define _TOOLS_LINUX_INIT_H
+
+/* this means you can add your own to fit you own userspace needs */
+#ifndef __ref
+#define __ref
+#endif
+
+#endif /* _TOOLS_LINUX_INIT_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v3 3/6] tools: add __used and enable to override
  2017-01-09 15:02         ` Luis R. Rodriguez
  (?)
@ 2017-01-09 15:02           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 15:02 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This adds __used, to be used later in the userspace linker-tables
sandbox. If any userspace applicaiton wants to override they can
add their own definition and then use include_next.

This definition should probably suffice for most uses cases though.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index e33fc1df3935..556c991de212 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -5,6 +5,12 @@
 /* The "volatile" is due to gcc bugs */
 #define barrier() __asm__ __volatile__("": : :"memory")
 
+
+/* You can override as you see fit on your userspace tool */
+#ifndef __used
+#define __used          __attribute__((__used__))
+#endif
+
 #ifndef __always_inline
 # define __always_inline	inline __attribute__((always_inline))
 #endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v3 3/6] tools: add __used and enable to override
@ 2017-01-09 15:02           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 15:02 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This adds __used, to be used later in the userspace linker-tables
sandbox. If any userspace applicaiton wants to override they can
add their own definition and then use include_next.

This definition should probably suffice for most uses cases though.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index e33fc1df3935..556c991de212 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -5,6 +5,12 @@
 /* The "volatile" is due to gcc bugs */
 #define barrier() __asm__ __volatile__("": : :"memory")
 
+
+/* You can override as you see fit on your userspace tool */
+#ifndef __used
+#define __used          __attribute__((__used__))
+#endif
+
 #ifndef __always_inline
 # define __always_inline	inline __attribute__((always_inline))
 #endif
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v3 3/6] tools: add __used and enable to override
@ 2017-01-09 15:02           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 15:02 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

This adds __used, to be used later in the userspace linker-tables
sandbox. If any userspace applicaiton wants to override they can
add their own definition and then use include_next.

This definition should probably suffice for most uses cases though.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index e33fc1df3935..556c991de212 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -5,6 +5,12 @@
 /* The "volatile" is due to gcc bugs */
 #define barrier() __asm__ __volatile__("": : :"memory")
 
+
+/* You can override as you see fit on your userspace tool */
+#ifndef __used
+#define __used          __attribute__((__used__))
+#endif
+
 #ifndef __always_inline
 # define __always_inline	inline __attribute__((always_inline))
 #endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v3 4/6] tools: expand export.h with VMLINUX_SYMBOL()
  2017-01-09 15:02         ` Luis R. Rodriguez
  (?)
@ 2017-01-09 15:02           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 15:02 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This will be used later by the linker-table userspace sandbox.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/export.h | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/tools/include/linux/export.h b/tools/include/linux/export.h
index d07e586b9ba0..cb7d6b490e08 100644
--- a/tools/include/linux/export.h
+++ b/tools/include/linux/export.h
@@ -1,6 +1,28 @@
 #ifndef _TOOLS_LINUX_EXPORT_H_
 #define _TOOLS_LINUX_EXPORT_H_
 
+/*
+ * Export symbols from the kernel to modules.  Forked from module.h
+ * to reduce the amount of pointless cruft we feed to gcc when only
+ * exporting a simple symbol or two.
+ *
+ * Try not to add #includes here.  It slows compilation and makes kernel
+ * hackers place grumpy comments in header files.
+ */
+
+/* Some toolchains use a `_' prefix for all user symbols. */
+#ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX
+#define __VMLINUX_SYMBOL(x) _##x
+#define __VMLINUX_SYMBOL_STR(x) "_" #x
+#else
+#define __VMLINUX_SYMBOL(x) x
+#define __VMLINUX_SYMBOL_STR(x) #x
+#endif
+
+/* Indirect, so macros are expanded before pasting. */
+#define VMLINUX_SYMBOL(x) __VMLINUX_SYMBOL(x)
+#define VMLINUX_SYMBOL_STR(x) __VMLINUX_SYMBOL_STR(x)
+
 #define EXPORT_SYMBOL(sym)
 #define EXPORT_SYMBOL_GPL(sym)
 #define EXPORT_SYMBOL_GPL_FUTURE(sym)
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v3 4/6] tools: expand export.h with VMLINUX_SYMBOL()
@ 2017-01-09 15:02           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 15:02 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This will be used later by the linker-table userspace sandbox.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/export.h | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/tools/include/linux/export.h b/tools/include/linux/export.h
index d07e586b9ba0..cb7d6b490e08 100644
--- a/tools/include/linux/export.h
+++ b/tools/include/linux/export.h
@@ -1,6 +1,28 @@
 #ifndef _TOOLS_LINUX_EXPORT_H_
 #define _TOOLS_LINUX_EXPORT_H_
 
+/*
+ * Export symbols from the kernel to modules.  Forked from module.h
+ * to reduce the amount of pointless cruft we feed to gcc when only
+ * exporting a simple symbol or two.
+ *
+ * Try not to add #includes here.  It slows compilation and makes kernel
+ * hackers place grumpy comments in header files.
+ */
+
+/* Some toolchains use a `_' prefix for all user symbols. */
+#ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX
+#define __VMLINUX_SYMBOL(x) _##x
+#define __VMLINUX_SYMBOL_STR(x) "_" #x
+#else
+#define __VMLINUX_SYMBOL(x) x
+#define __VMLINUX_SYMBOL_STR(x) #x
+#endif
+
+/* Indirect, so macros are expanded before pasting. */
+#define VMLINUX_SYMBOL(x) __VMLINUX_SYMBOL(x)
+#define VMLINUX_SYMBOL_STR(x) __VMLINUX_SYMBOL_STR(x)
+
 #define EXPORT_SYMBOL(sym)
 #define EXPORT_SYMBOL_GPL(sym)
 #define EXPORT_SYMBOL_GPL_FUTURE(sym)
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v3 4/6] tools: expand export.h with VMLINUX_SYMBOL()
@ 2017-01-09 15:02           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 15:02 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

This will be used later by the linker-table userspace sandbox.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/export.h | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/tools/include/linux/export.h b/tools/include/linux/export.h
index d07e586b9ba0..cb7d6b490e08 100644
--- a/tools/include/linux/export.h
+++ b/tools/include/linux/export.h
@@ -1,6 +1,28 @@
 #ifndef _TOOLS_LINUX_EXPORT_H_
 #define _TOOLS_LINUX_EXPORT_H_
 
+/*
+ * Export symbols from the kernel to modules.  Forked from module.h
+ * to reduce the amount of pointless cruft we feed to gcc when only
+ * exporting a simple symbol or two.
+ *
+ * Try not to add #includes here.  It slows compilation and makes kernel
+ * hackers place grumpy comments in header files.
+ */
+
+/* Some toolchains use a `_' prefix for all user symbols. */
+#ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX
+#define __VMLINUX_SYMBOL(x) _##x
+#define __VMLINUX_SYMBOL_STR(x) "_" #x
+#else
+#define __VMLINUX_SYMBOL(x) x
+#define __VMLINUX_SYMBOL_STR(x) #x
+#endif
+
+/* Indirect, so macros are expanded before pasting. */
+#define VMLINUX_SYMBOL(x) __VMLINUX_SYMBOL(x)
+#define VMLINUX_SYMBOL_STR(x) __VMLINUX_SYMBOL_STR(x)
+
 #define EXPORT_SYMBOL(sym)
 #define EXPORT_SYMBOL_GPL(sym)
 #define EXPORT_SYMBOL_GPL_FUTURE(sym)
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v3 5/6] tools: add __section() to compiler.h
  2017-01-09 15:02         ` Luis R. Rodriguez
  (?)
@ 2017-01-09 15:02           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 15:02 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This will be used later by the userspace linker table.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index 556c991de212..6321265df00a 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -132,4 +132,6 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 #define WRITE_ONCE(x, val) \
 	({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
 
+#define __section(S)	__attribute__ ((__section__(#S)))
+
 #endif /* _TOOLS_LINUX_COMPILER_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v3 5/6] tools: add __section() to compiler.h
@ 2017-01-09 15:02           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 15:02 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This will be used later by the userspace linker table.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index 556c991de212..6321265df00a 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -132,4 +132,6 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 #define WRITE_ONCE(x, val) \
 	({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
 
+#define __section(S)	__attribute__ ((__section__(#S)))
+
 #endif /* _TOOLS_LINUX_COMPILER_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v3 5/6] tools: add __section() to compiler.h
@ 2017-01-09 15:02           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 15:02 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

This will be used later by the userspace linker table.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index 556c991de212..6321265df00a 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -132,4 +132,6 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 #define WRITE_ONCE(x, val) \
 	({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
 
+#define __section(S)	__attribute__ ((__section__(#S)))
+
 #endif /* _TOOLS_LINUX_COMPILER_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v3 6/6] tools: add userspace linker table sandbox
  2017-01-09 15:02         ` Luis R. Rodriguez
@ 2017-01-09 15:02           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 15:02 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Add a userspace sandbox to allow easy experimentation and
test extensions with linker tables, section ranges and the
new section core definitions.

The userspace sandbox tries to mimic the Linux kernel development
flow as much as possible, it however relies on and uses libc. Support
is currently only provided to x86_64.

Demo run:

cd tools/linker-tables
make clean; make;
./demo
Initializing x86 bare metal world
x86-init: Number of init entries: 8
Initializing memory ...
Completed initializing memory !
Initializing pci ...
PCI fixup size: 1
Demo: Using LINKTABLE_FOR_EACH
foo_fixup
Demo: Using LINKTABLE_RUN_ALL
foo_fixup
Completed initializing pci !
Number of init entries: 1
Initializing kprobes ...
== OK: test_kprobe_0001 within range!
== OK: test_kprobe_0002 not in range as expected!
Completed initializing kprobes !
Initializing kasan ...
Early init for Kasan...
Completed initializing kasan !
Initializing beta ...
Completed initializing beta !
Initializing alpha ...
Completed initializing alpha !
Booting bare metal
Calling start_kernel()...
ACME: Initializing ...
ACME: Finished init ... !
Synthetics: synth_init_or(2) returns: 0xDEADBEEF
Synthetics: ps_shr(0xDEADBEEF, get_demo_shr) returns: 0x0000DEAD

v6: rename table macros as suggested by Andy Shevchenko

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clashes with compiler generated
  sections.

o moves tools/include/linux/printk.h to tools
  linker-table/include/linux/printk.h -- we cannot generalize this
  just yet, more work is needed in terms of providing a namespace for
  headers for types of ports of kernel functionality to userspace.

o Adjust code according to the latest discussions for the linker
  tables API (section name macros are now gone).

o Give CONFIG_HAVE_ARCH_PS_CONST for x86 another good 'ol college try,
  still fails, but this is just a demo anyway. We can amend and fix
  make this more optimized for x86 later. Thanks Boris!

v4: this patch is new in this series -- added to the kenrel as
    suggested by Boris, as otherwise it'd be really hard to keep
    an external userspace repository in sync.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/linker-tables.rst           |   4 +-
 MAINTAINERS                                        |   1 +
 include/linux/tables.h                             |   5 +-
 tools/Makefile                                     |   3 +-
 .../arch/x86/include/generated/asm/section-core.h  |   1 +
 tools/arch/x86/include/generated/ranges.h          |   1 +
 tools/arch/x86/include/generated/tables.h          |   1 +
 tools/include/asm-generic/ranges.h                 |  93 +++
 tools/include/asm-generic/section-core.h           | 348 +++++++++++
 tools/include/asm-generic/tables.h                 |  48 ++
 tools/include/linux/ranges.h                       | 183 ++++++
 tools/include/linux/sections.h                     |  87 +++
 tools/include/linux/string.h                       |   1 +
 tools/include/linux/tables.h                       | 684 +++++++++++++++++++++
 tools/linker-tables/.gitignore                     |   2 +
 tools/linker-tables/Makefile                       | 184 ++++++
 tools/linker-tables/README                         | 114 ++++
 tools/linker-tables/arch/x86/include/asm/asm.h     |  17 +
 tools/linker-tables/arch/x86/include/asm/boot.h    |   1 +
 .../linker-tables/arch/x86/include/asm/bootparam.h |  32 +
 tools/linker-tables/arch/x86/include/asm/kprobes.h |   7 +
 .../linker-tables/arch/x86/include/asm/ps_const.h  |  23 +
 tools/linker-tables/arch/x86/include/asm/ranges.h  |   6 +
 .../arch/x86/include/asm/section-core.h            |   1 +
 tools/linker-tables/arch/x86/include/asm/setup.h   |   6 +
 tools/linker-tables/arch/x86/include/asm/tables.h  |   6 +
 tools/linker-tables/arch/x86/include/asm/x86.h     |   4 +
 .../arch/x86/include/asm/x86_init_fn.h             | 169 +++++
 tools/linker-tables/arch/x86/kernel/alpha.c        |   9 +
 tools/linker-tables/arch/x86/kernel/alternative.c  |  31 +
 tools/linker-tables/arch/x86/kernel/beta.c         |   9 +
 tools/linker-tables/arch/x86/kernel/head64.c       |  58 ++
 tools/linker-tables/arch/x86/kernel/init.c         |  42 ++
 tools/linker-tables/arch/x86/kernel/kasan.c        |  10 +
 tools/linker-tables/arch/x86/kernel/kprobes.c      |  51 ++
 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S  | 277 +++++++++
 tools/linker-tables/arch/x86/mm/init.c             |  10 +
 tools/linker-tables/arch/x86/xen/init.c            |  13 +
 tools/linker-tables/drivers/acme.c                 |  32 +
 tools/linker-tables/drivers/synth/common.c         |  16 +
 tools/linker-tables/drivers/synth/common.h         |   2 +
 tools/linker-tables/drivers/synth/main.c           |  35 ++
 tools/linker-tables/drivers/synth/or.S             |  39 ++
 tools/linker-tables/drivers/synth/synth.h          |   2 +
 tools/linker-tables/drivers/xen-driver.c           |  11 +
 .../include/asm-generic/arch_init_fn.h             |  50 ++
 tools/linker-tables/include/asm-generic/kprobes.h  |  26 +
 tools/linker-tables/include/linux/bitops.h         |   6 +
 tools/linker-tables/include/linux/init.h           |  40 ++
 tools/linker-tables/include/linux/kasan.h          |   5 +
 tools/linker-tables/include/linux/kernel.h         |   2 +
 tools/linker-tables/include/linux/kprobes.h        |  11 +
 tools/linker-tables/include/linux/module.h         |  14 +
 tools/linker-tables/include/linux/mutex.h          |  17 +
 tools/linker-tables/include/linux/pci.h            |   7 +
 tools/linker-tables/include/linux/printk.h         |  26 +
 tools/linker-tables/include/linux/ps_const.h       |  46 ++
 tools/linker-tables/include/linux/sched.h          |   9 +
 tools/linker-tables/include/linux/spinlock.h       |  13 +
 tools/linker-tables/include/linux/start_kernel.h   |   1 +
 tools/linker-tables/include/linux/types.h          |  13 +
 tools/linker-tables/include/linux/workqueue.h      |  51 ++
 tools/linker-tables/include/xen/xen.h              |   4 +
 tools/linker-tables/kernel/locking/mutex.c         |  28 +
 tools/linker-tables/kernel/locking/spinlock.c      |  26 +
 tools/linker-tables/kernel/main.c                  |  32 +
 tools/linker-tables/kernel/workqueue.c             |  43 ++
 tools/linker-tables/lib/string.c                   |  26 +
 tools/linker-tables/main.c                         |  20 +
 tools/linker-tables/pci-quirks.c                   |  13 +
 tools/linker-tables/pci.c                          |  29 +
 71 files changed, 3232 insertions(+), 5 deletions(-)
 create mode 100644 tools/arch/x86/include/generated/asm/section-core.h
 create mode 100644 tools/arch/x86/include/generated/ranges.h
 create mode 100644 tools/arch/x86/include/generated/tables.h
 create mode 100644 tools/include/asm-generic/ranges.h
 create mode 100644 tools/include/asm-generic/section-core.h
 create mode 100644 tools/include/asm-generic/tables.h
 create mode 100644 tools/include/linux/ranges.h
 create mode 100644 tools/include/linux/sections.h
 create mode 100644 tools/include/linux/tables.h
 create mode 100644 tools/linker-tables/.gitignore
 create mode 100644 tools/linker-tables/Makefile
 create mode 100644 tools/linker-tables/README
 create mode 100644 tools/linker-tables/arch/x86/include/asm/asm.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/boot.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/bootparam.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/kprobes.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ps_const.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ranges.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/section-core.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/setup.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/tables.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
 create mode 100644 tools/linker-tables/arch/x86/kernel/alpha.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/alternative.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/beta.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/head64.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/init.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kasan.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kprobes.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
 create mode 100644 tools/linker-tables/arch/x86/mm/init.c
 create mode 100644 tools/linker-tables/arch/x86/xen/init.c
 create mode 100644 tools/linker-tables/drivers/acme.c
 create mode 100644 tools/linker-tables/drivers/synth/common.c
 create mode 100644 tools/linker-tables/drivers/synth/common.h
 create mode 100644 tools/linker-tables/drivers/synth/main.c
 create mode 100644 tools/linker-tables/drivers/synth/or.S
 create mode 100644 tools/linker-tables/drivers/synth/synth.h
 create mode 100644 tools/linker-tables/drivers/xen-driver.c
 create mode 100644 tools/linker-tables/include/asm-generic/arch_init_fn.h
 create mode 100644 tools/linker-tables/include/asm-generic/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/bitops.h
 create mode 100644 tools/linker-tables/include/linux/init.h
 create mode 100644 tools/linker-tables/include/linux/kasan.h
 create mode 100644 tools/linker-tables/include/linux/kernel.h
 create mode 100644 tools/linker-tables/include/linux/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/module.h
 create mode 100644 tools/linker-tables/include/linux/mutex.h
 create mode 100644 tools/linker-tables/include/linux/pci.h
 create mode 100644 tools/linker-tables/include/linux/printk.h
 create mode 100644 tools/linker-tables/include/linux/ps_const.h
 create mode 100644 tools/linker-tables/include/linux/sched.h
 create mode 100644 tools/linker-tables/include/linux/spinlock.h
 create mode 100644 tools/linker-tables/include/linux/start_kernel.h
 create mode 100644 tools/linker-tables/include/linux/types.h
 create mode 100644 tools/linker-tables/include/linux/workqueue.h
 create mode 100644 tools/linker-tables/include/xen/xen.h
 create mode 100644 tools/linker-tables/kernel/locking/mutex.c
 create mode 100644 tools/linker-tables/kernel/locking/spinlock.c
 create mode 100644 tools/linker-tables/kernel/main.c
 create mode 100644 tools/linker-tables/kernel/workqueue.c
 create mode 100644 tools/linker-tables/lib/string.c
 create mode 100644 tools/linker-tables/main.c
 create mode 100644 tools/linker-tables/pci-quirks.c
 create mode 100644 tools/linker-tables/pci.c

diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index bc2d9f46cde6..2f2bb1fc0798 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -11,11 +11,11 @@ About Linker tables
 .. kernel-doc:: include/linux/tables.h
    :doc: Introduction
 
-Linker table provenance
+Linker table provenance and userspace testing
 ---------------------------------------------
 
 .. kernel-doc:: include/linux/tables.h
-   :doc: Linker table provenance
+   :doc: Linker table provenance and userspace testing
 
 Benefits of using Linker tables
 ===============================
diff --git a/MAINTAINERS b/MAINTAINERS
index bbf519da3a78..30105cd3edaf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5415,6 +5415,7 @@ L:	linux-kernel@vger.kernel.org
 S:	Supported
 F:	include/asm-generic/tables.h
 F:	include/linux/tables.h
+F:	tools/linker-tables/
 F:	Documentation/sections/linker-tables.rst
 
 GENERIC PHY FRAMEWORK
diff --git a/include/linux/tables.h b/include/linux/tables.h
index 70a41edfa127..64b864949a02 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -35,12 +35,13 @@
  */
 
 /**
- * DOC: Linker table provenance
+ * DOC: Linker table provenance and userspace testing
  *
  * 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].
+ * userspace linker-table tree [1]. Linux has a similar userspace application
+ * in tools/linker-tables/ to help more easily test adding new extensions.
  *
  * Contrary to iPXE's solution which strives to force compilation of
  * everything using linker tables, Linux's solution allows for developers to be
diff --git a/tools/Makefile b/tools/Makefile
index 00caacd3ed92..ecb2e651c930 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -19,6 +19,7 @@ help:
 	@echo '  kvm_stat               - top-like utility for displaying kvm statistics'
 	@echo '  leds                   - LEDs  tools'
 	@echo '  lguest                 - a minimal 32-bit x86 hypervisor'
+	@echo '  linker-tables		- userspace liker table sandbox and related tools'
 	@echo '  net                    - misc networking tools'
 	@echo '  perf                   - Linux performance measurement and analysis tool'
 	@echo '  selftests              - various kernel selftests'
@@ -86,7 +87,7 @@ tmon: FORCE
 freefall: FORCE
 	$(call descend,laptop/$@)
 
-all: acpi cgroup cpupower gpio hv firewire lguest \
+all: acpi cgroup cpupower gpio hv firewire lguest linker-tables \
 		perf selftests turbostat usb \
 		virtio vm net x86_energy_perf_policy \
 		tmon freefall objtool
diff --git a/tools/arch/x86/include/generated/asm/section-core.h b/tools/arch/x86/include/generated/asm/section-core.h
new file mode 100644
index 000000000000..06be2b1c424f
--- /dev/null
+++ b/tools/arch/x86/include/generated/asm/section-core.h
@@ -0,0 +1 @@
+#include <asm-generic/section-core.h>
diff --git a/tools/arch/x86/include/generated/ranges.h b/tools/arch/x86/include/generated/ranges.h
new file mode 100644
index 000000000000..dac1a9a11367
--- /dev/null
+++ b/tools/arch/x86/include/generated/ranges.h
@@ -0,0 +1 @@
+#include <asm-generic/ranges.h>
diff --git a/tools/arch/x86/include/generated/tables.h b/tools/arch/x86/include/generated/tables.h
new file mode 100644
index 000000000000..d437818275c5
--- /dev/null
+++ b/tools/arch/x86/include/generated/tables.h
@@ -0,0 +1 @@
+#include <asm-generic/tables.h>
diff --git a/tools/include/asm-generic/ranges.h b/tools/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..75c196864f45
--- /dev/null
+++ b/tools/include/asm-generic/ranges.h
@@ -0,0 +1,93 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  any, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       any, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   any, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(#section "..rng.name.any")))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using
+ * 	binutils SORT(), the number is sorted as a string, as such be
+ * 	sure to fill with zeroes any empty digits. For instance if you are
+ * 	using 3 levels of digits for order levels, use 001 for the first entry,
+ * 	0002 for the second, 999 for the last entry. You can use however many
+ * 	digits you need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(#section "..rng.name." #level)))
+
+#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/tools/include/asm-generic/section-core.h b/tools/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..65fb076765f8
--- /dev/null
+++ b/tools/include/asm-generic/section-core.h
@@ -0,0 +1,348 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Linux ELF program specific sections
+ *
+ * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and
+ * definition of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
+ * sections. This chaper is dedicated to documenting Linux program specific
+ * sections and helpers available to make use of these easier to implement and
+ * use.
+ *
+ * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
+ */
+
+/**
+ * DOC: Linux linker script
+ *
+ * Linux uses a custom linker script to build the vmlinux binary, it uses it to
+ * strategically place and define Linux ELF sections.  Each architecture needs
+ * to implement its own linker script, it is expected to reside in
+ * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
+ * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
+ * as well as some helpers documented in this chapter.
+ *
+ * In assembly it is common practice to use dots (``.``) in labels to avoid
+ * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
+ * name but not a C symbol. Historically then, two dots are used (``..``)
+ * have been used in linker scripts when adding program specific sections
+ * when there are concerns to avoid clashes with compiler generated sections.
+ */
+
+/**
+ * DOC: Memory protection
+ *
+ * Linux allows architectures which support memory protection features to
+ * take advantage of them by letting architectures define and enable
+ * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.
+ * mark_rodata_ro() can be used for instance to mark specific sections as
+ * read-only or non-executable.
+ *
+ * Linux typically follows a convention to have the .rodata ELF section follow
+ * after the .text ELF section, it does this to help architectures which
+ * support memory protection to mark both .text and .rodata as read-only in
+ * one shot.
+ *
+ * For more details refer to mark_rodata_ro().
+ */
+
+/**
+ * DOC: .rodata
+ *
+ * ELF section used for data which must be protected from write access.
+ */
+
+/**
+ * DOC: .text
+ *
+ * ELF section name used for code (functions) used during regular
+ * kernel run time.
+ */
+
+/**
+ * DOC: .data
+ *
+ * ELF section used for read-write data.
+ */
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: .init.text
+ *
+ * ELF section for code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+
+/**
+ * DOC: .init.data
+ *
+ * ELF section used for data structures used only during boot or driver
+ * initialization.
+ */
+
+/**
+ * DOC: .init.rodata
+ *
+ * ELF section used for read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+
+/**
+ * DOC: .initcall
+ *
+ * ELF section used for subsystem init calls. There are init levels
+ * representing different functionality in the kernel. For more details
+ * refer to __define_initcall().
+ */
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: .exit.text
+ *
+ * ELF section used to for code (functions) used only during module unload.
+ */
+
+/**
+ * DOC: .exit.data
+ *
+ * ELF section used to for data structures used only during module
+ * unload.
+ */
+
+/**
+ * DOC: .exitcall.exit
+ *
+ * ELF section used for exit routines, order is important and maintained by
+ * link order.
+ */
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: .ref.text
+ *
+ * ELF section used to annotate code (functions) which has been vetteed as
+ * valid for its reference or use of other code (functions) or data structures
+ * which are part of the init sections.
+ */
+
+/**
+ * DOC: .ref.data
+ *
+ * ELF section used for data structures which have been vetteed for its
+ * reference or use of other code (functions) or data structures part of the
+ * init sections.
+ */
+
+/**
+ * DOC: .ref.rodata
+ *
+ * ELF section used to annotate const code (functions) const data structures
+ * which has been vetteed for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections alpha numerically. Linux has historically used 'SORT()' in
+ * ``include/asm-generic/vmlinux.lds.h``, its a well established practice. If
+ * 'SORT()' is used on a section one can provide ordering using a postfix on
+ * each section entry added. For instance if a linker script uses::
+ *
+ *    SORT(.foo.*)
+ *
+ * one can then add entries with explicit ordering using numeric postfixes for
+ * each entry, we refer to these as 'order levels'. Since 'SORT()' sorts alpha
+ * numerically a specific series set of digits must be agreed a-priori which
+ * would give also an idea of the max expected number of entries added to a
+ * section. For instance, if you expect a maximum of 999 entries you can use
+ * 3 digits for a section order level. If you wanted an entry to be ordered
+ * first you could use the postfix '000', if you wanted an entry to follow this
+ * you could use '001', and so on. We could for instance have::
+ *
+ *    .foo.000
+ *    .foo.001
+ *    .foo.002
+ *
+ * Often times one may want the option to specify no order is required for
+ * certain elements added to a section which does use 'SORT()' on the linker
+ * script. You can use any arbitrary string value to to specify no order is
+ * used, so long as its used consistantly. For instance, one possibility is to
+ * use the 'any' postfix.  All entries on the section would then have no
+ * specific ordering::
+ *
+ *    .foo.any
+ *    .foo.any
+ *    .foo.any
+ *
+ * To help establish a convention we reserve the special name 'any' for this
+ * purpose. Developers can use and expect the 'any' postfix string on sections
+ * as a helper to annotate section ordering at link time is not relevant
+ * for entries on a section.
+ */
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section..___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section..__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifndef LINKER_SCRIPT
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align=16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/tools/include/asm-generic/tables.h b/tools/include/asm-generic/tables.h
new file mode 100644
index 000000000000..16ef40d145fb
--- /dev/null
+++ b/tools/include/asm-generic/tables.h
@@ -0,0 +1,48 @@
+#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..tbl.name.level
+
+/* Some toolchains are buggy, let them override */
+#ifndef SECTION_TBL_RO
+# define SECTION_TBL_RO	.rodata
+#endif
+
+#define SECTION_TBL_RO_STR __stringify(SECTION_TBL_RO)
+
+#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, 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, any, flags)
+#endif
+
+#endif /* _ASM_GENERIC_TABLES_H_ */
diff --git a/tools/include/linux/ranges.h b/tools/include/linux/ranges.h
new file mode 100644
index 000000000000..1e64674f6d7d
--- /dev/null
+++ b/tools/include/linux/ranges.h
@@ -0,0 +1,183 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * SECTION_RANGE_START - get address of start of section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the start address of the section range.
+ * This should give you the address of the first entry.
+ *
+ */
+#define SECTION_RANGE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * SECTION_RANGE_END - get address of end of the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define SECTION_RANGE_END(name)		LINUX_SECTION_END(name)
+
+/**
+ * SECTION_RANGE_SIZE - get number of entries in the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the number of entries in the section range.
+ * Example usage:
+ *
+ *   unsigned int num_ents = LINKTABLE_SIZE(some_fns);
+ */
+#define SECTION_RANGE_SIZE(name)					\
+	((SECTION_RANGE_END(name)) - (SECTION_RANGE_START(name)))
+
+/**
+ * SECTION_RANGE_EMPTY - check if section range has no entries
+ *
+ * @name: name of the section range
+ *
+ * Returns true if the section range is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(some_fns);
+ */
+#define SECTION_RANGE_EMPTY(name)	(SECTION_RANGE_SIZE(name) == 0)
+
+/**
+ * SECTION_RANGE_ADDR_WITHIN - returns true if address is in the section range
+ *
+ * @name: name of the section range
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_RANGE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) SECTION_RANGE_START(name) &&		\
+          addr < (unsigned long) SECTION_RANGE_END(name))
+
+/**
+ * SECTION_RANGE_ALIGNMENT - get the alignment of the section range
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the section range.
+ */
+#define SECTION_RANGE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.")))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.~")))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) SECTION_RANGE_START(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) SECTION_RANGE_END(name)[0] = {}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
diff --git a/tools/include/linux/sections.h b/tools/include/linux/sections.h
new file mode 100644
index 000000000000..6771c727bcd1
--- /dev/null
+++ b/tools/include/linux/sections.h
@@ -0,0 +1,87 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_CORE(section, core, name, level)			\
+	#section ".." #core "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
diff --git a/tools/include/linux/string.h b/tools/include/linux/string.h
index f436d2420a18..a6b12564bbd9 100644
--- a/tools/include/linux/string.h
+++ b/tools/include/linux/string.h
@@ -3,6 +3,7 @@
 
 
 #include <linux/types.h>	/* for size_t */
+#include <string.h>
 
 void *memdup(const void *src, size_t len);
 
diff --git a/tools/include/linux/tables.h b/tools/include/linux/tables.h
new file mode 100644
index 000000000000..64b864949a02
--- /dev/null
+++ b/tools/include/linux/tables.h
@@ -0,0 +1,684 @@
+#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 and userspace testing
+ *
+ * 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]. Linux has a similar userspace application
+ * in tools/linker-tables/ to help more easily test adding new extensions.
+ *
+ * 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(.foo..tbl.*))
+ *
+ * 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: The code bit-rot problem
+ *
+ * Linux provides a rich array of features, enabling each feature
+ * however increases the size of the kernel and there are many
+ * features which users often want disabled. The traditional
+ * solution to this problem is for each feature to have its own
+ * Kconfig symbol, followed by a series of #ifdef statements
+ * in C code and header files, allowing the feature to be compiled
+ * only when desirable. As the variability of Linux increases build
+ * tests can and are often done with random kernel configurations,
+ * allyesconfig, and allmodconfig to help find code issues. This
+ * however doesn't catch all errors and as a consequence code that
+ * is typically not enabled often can suffer from bit-rot over time.
+ */
+
+/**
+ * DOC: The build-all selective-link philosophy
+ *
+ * A code architecture philosophy to help avoid code bit-rot consists
+ * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
+ * by instead having each feature implemented it its own C file, and force
+ * compilation for all features. Only features that are enabled get linked in,
+ * the forced compilation therefore has no size impact on the final result of
+ * the kernel. The practice of having each feature implemented in its own C
+ * file is already prevalent in many subsystems, however #ifdefs are still
+ * typically required during feature initialization. For instance in::
+ *
+ *	#ifdef CONFIG_FOO
+ *	foo_init();
+ *	#endif
+ *
+ * We cannot remove the #ifdef and leave foo_init() as we'd either
+ * need to always enable the feature or add a respective #ifdef in a
+ * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem with linker tables
+ *
+ * Linker tables can be used to further help avoid the code bit-rot problem
+ * when embracing the 'build-all selective-link philosophy' by lifting the
+ * requirement to use of #ifdefs during initialization. With linker tables
+ * initialization sequences can be aggregated into a custom ELF section at
+ * link time, during run time the table can be iterated over and each init
+ * sequence enabled can be called. A feature's init routine is only added to a
+ * table when its respective Kconfig symbols has been enabled and therefore
+ * linked in. Linker tables enable subsystems to completely do away with
+ * #ifdefs if one is comfortable in accepting all subsystem's feature's
+ * structural size implications.
+ *
+ * To further help with this the Linux build system supports two special
+ * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
+ * follow the 'build-all selective-link philosophy' can use these targets for a
+ * feature's kconfig symbol. Using these targets will always require
+ * compilation of the kconfig's objects if the kconfig symbol's dependencies
+ * are met but only link the objects into the kernel, and therefore enable the
+ * feature, if and only if the kconfig symbol has been enabled.
+ *
+ * Not all users or build systems may want to opt-in to compile all objects
+ * following the 'build-all selective-link philosophy', as such the targets
+ * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
+ * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
+ * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
+ * ``obj-y`` and ``lib-y`` respectively.
+ *
+ * Example use::
+ *
+ * 	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+ */
+
+/**
+ * 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_START - get address of start of linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the start address of the linker table.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINKTABLE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * LINKTABLE_END - get address of end of the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define LINKTABLE_END(name)	LINUX_SECTION_END(name)
+
+/**
+ * LINKTABLE_SIZE - get number of entries in the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the number of entries in the linker table.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINKTABLE_SIZE(frobnicator_fns);
+ */
+#define LINKTABLE_SIZE(name)					\
+	((LINKTABLE_END(name)) - (LINKTABLE_START(name)))
+
+/**
+ * LINKTABLE_EMPTY - check if linker table has no entries
+ *
+ * @name: name of linker table
+ *
+ * Returns true if the linker table is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(frobnicator_fns);
+ */
+#define LINKTABLE_EMPTY(name)	(LINKTABLE_SIZE(name) == 0)
+
+/**
+ * LINKTABLE_ADDR_WITHIN - returns true if address is in the linker table
+ *
+ * @name: name of the linker table
+ * @addr: address to query for
+ *
+ * Returns true if the address is part of the linker table.
+ */
+#define LINKTABLE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) LINKTABLE_START(name) &&		\
+          addr < (unsigned long) LINKTABLE_END(name))
+
+/**
+ * LINKTABLE_ALIGNMENT - get the alignment of the linker table
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the linker table.
+ */
+#define LINKTABLE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * 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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_TEXT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE_RO(name, ~) LINKTABLE_END(name)[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_RO(type, name);				\
+	LINKTABLE_INIT_WEAK(name,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT_DATA(name, ~) LINKTABLE_END(name)[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 = LINKTABLE_START(tbl);				\
+	     pointer < LINKTABLE_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 < LINKTABLE_SIZE(tbl); i++)			\
+		(LINKTABLE_START(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 < LINKTABLE_SIZE(tbl); i++)		\
+		err = (LINKTABLE_START(tbl)[i]).func (args);		\
+	err;								\
+})
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_LINKER_TABLES_H */
diff --git a/tools/linker-tables/.gitignore b/tools/linker-tables/.gitignore
new file mode 100644
index 000000000000..8275b0c55385
--- /dev/null
+++ b/tools/linker-tables/.gitignore
@@ -0,0 +1,2 @@
+arch/x86/kernel/vmlinux.lds
+demo
diff --git a/tools/linker-tables/Makefile b/tools/linker-tables/Makefile
new file mode 100644
index 000000000000..9d4e6fb0d176
--- /dev/null
+++ b/tools/linker-tables/Makefile
@@ -0,0 +1,184 @@
+include ../scripts/Makefile.include
+
+all:
+
+include ../scripts/utilities.mak
+
+MAKEFLAGS += --no-print-directory
+
+unexport LC_ALL
+LC_COLLATE=C
+LC_NUMERIC=C
+export LC_COLLATE LC_NUMERIC
+
+ifeq ($(srctree),)
+	srctree := $(patsubst %/,%,$(dir $(shell pwd)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Determined 'srctree' to be $(srctree))
+endif
+
+ifneq ($(objtree),)
+#$(info Determined 'objtree' to be $(objtree))
+endif
+
+ifneq ($(OUTPUT),)
+#$(info Determined 'OUTPUT' to be $(OUTPUT))
+# Adding $(OUTPUT) as a directory to look for source files,
+# because use generated output files as sources dependency
+# for flex/bison parsers.
+VPATH += $(OUTPUT)
+export VPATH
+endif
+
+export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK
+include $(srctree)/tools/build/Makefile.include
+
+ifeq ($(V),1)
+	Q=
+	NQ=@true
+else
+	Q=@
+	NQ=@echo
+endif
+
+MAKEFLAGS += -r
+
+define allow-override
+  $(if $(or $(findstring environment,$(origin $(1))),\
+            $(findstring command line,$(origin $(1)))),,\
+    $(eval $(1) = $(2)))
+endef
+
+# Allow setting CC and AR and LD, or setting CROSS_COMPILE as a prefix.
+$(call allow-override,CC,$(CROSS_COMPILE)gcc)
+$(call allow-override,AR,$(CROSS_COMPILE)ar)
+$(call allow-override,LD,$(CROSS_COMPILE)ld)
+
+LD += $(EXTRA_LDFLAGS)
+
+include $(srctree)/tools/scripts/Makefile.arch
+
+# Refer to README to learn how to support your architecture
+SUPPORTED_ARCHS = x86
+
+ifeq ($(filter $(ARCH),$(SUPPORTED_ARCHS)),)
+$(error Unsupported arch: $(ARCH))
+endif
+
+CFLAGS += -O2 -g
+CFLAGS += -std=gnu99 -Wall -Werror
+CFLAGS += -lpthread
+CFLAGS += -DCONFIG_KPROBES
+
+# We confine the includes used below to those we know are safe
+# for this type of hack.
+CFLAGS += -D__KERNEL__
+
+# CFLAGS += -DCONFIG_HAVE_ARCH_PS_CONST
+INCLUDES = \
+	   -I include/ \
+	   -I arch/$(ARCH)/include/ \
+	   -I ../include/ \
+	   -I ../arch/$(ARCH)/include/ \
+	   -I ../arch/$(ARCH)/include/generated/
+
+CFLAGS += $(INCLUDES)
+CFLAGS +=-Wl,-Tarch/$(ARCH)/kernel/vmlinux.lds
+
+HEADERS = \
+	  ../../include/asm-generic/section-core.h \
+	  ../../include/asm-generic/ranges.h \
+	  ../../include/asm-generic/tables.h \
+	  ../../include/linux/sections.h \
+	  ../../include/linux/ranges.h \
+	  ../../include/linux/tables.h
+
+__check_headers: $(HEADERS)
+	@$(foreach h, $(HEADERS), \
+		(test -f $(h) && ( \
+			(diff -B $(subst ../,../,$(h)) $(h) >/dev/null) \
+			|| echo "Warning: $(subst ../../,tools/,$(h)) differs from kernel" >&2 ) || true);)
+
+$(OUTPUT)arch/$(ARCH)/kernel/vmlinux.lds: arch/$(ARCH)/kernel/vmlinux.lds.S
+	$(NQ) '  LD  ' $@
+	$(Q)$(CC) $(CFLAGS) $(INCLUDES) -E -P \
+		-D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
+
+# Note, we use obj-y as a convenience factor, the cmd build
+# stuff doesn't allow this magic, it resolves our depds but
+# we still need to provide a series of targets for our objects.
+# We stick to the convenient shorthand we're used to in the
+# kernel. The final object resolution build stuff is handled
+# by tool_target_obj and its caller below. This also enables
+# OUTPUT=foo-path support so you can build externally.
+obj-y += \
+	arch/$(ARCH)/kernel/head64.o \
+	arch/$(ARCH)/mm/init.o \
+	kernel/locking/mutex.o \
+	kernel/locking/spinlock.o \
+	kernel/workqueue.o \
+	kernel/main.o \
+	pci.o \
+	lib/string.o \
+	pci-quirks.o \
+	drivers/acme.o \
+	drivers/synth/main.o \
+	drivers/synth/common.o \
+	drivers/synth/or.s \
+	main.o
+
+ifeq ($(ARCH),x86)
+obj-y += \
+	arch/$(ARCH)/kernel/alternative.o \
+	arch/$(ARCH)/kernel/init.o \
+	arch/$(ARCH)/kernel/kprobes.o \
+	arch/$(ARCH)/kernel/kasan.o \
+	arch/$(ARCH)/kernel/beta.o \
+	arch/$(ARCH)/kernel/alpha.o \
+	arch/$(ARCH)/xen/init.o	\
+	drivers/xen-driver.o
+endif
+
+obj-y-out = $(patsubst %,$(OUTPUT)%,$(obj-y))
+
+__build-dir = $(subst $(OUTPUT),,$(dir $1))
+build-dir   = $(if $(__build-dir),$(__build-dir),.)
+
+build := -f $(srctree)/tools/build/Makefile.build dir=$(build-dir)
+
+define tool_target_obj
+$(1): $(subst .s,.S,$(subst .o,.c,$(patsubst $(OUTPUT)%,%,$(1))))
+	$(Q)$(MAKE) $(build) obj=$(1)
+endef
+
+$(foreach tool_obj, $(obj-y-out), \
+	$(eval $(call tool_target_obj, $(tool_obj))))
+
+$(OUTPUT)demo: $(obj-y-out)
+	$(NQ) '  CC  ' $@
+	$(Q)$(CC) $(obj-y-out) -o $@ $(CPPFLAGS) $(CFLAGS)
+
+CHECK_HEADERS := __check_headers
+PHONY += $(CHECK_HEADERS)
+
+CMD_TARGETS = $(OUTPUT)arch/$(ARCH)/kernel/vmlinux.lds $(OUTPUT)demo
+TARGETS = $(CMD_TARGETS)
+
+all: $(CHECK_HEADERS) all_cmd
+
+all_cmd: $(CMD_TARGETS)
+
+ifeq ($(OUTPUT),)
+clean_dir = ./
+else
+clean_dir = $(OUTPUT)
+endif
+
+clean::
+	$(NQ)  '  CLEAN deps'
+	$(Q)find $(clean_dir) -name \*.o \
+		-o -name \*.s \
+		-o -name \*.o.d \
+		-o -name \*.o.cmd | xargs rm -f
+	$(NQ)  '  CLEAN targets'
+	$(Q)$(foreach f, $(CMD_TARGETS), rm -f $(f);)
diff --git a/tools/linker-tables/README b/tools/linker-tables/README
new file mode 100644
index 000000000000..729241f9e4c4
--- /dev/null
+++ b/tools/linker-tables/README
@@ -0,0 +1,114 @@
+Linux linker table userspace sandbox
+====================================
+
+This is a userspace sandbox to allow easy experimentation and
+test extensions with linker tables. It tries to mimic the Linux
+kernel development flow as much as possible, it however relies
+on and uses libc and is nothing but a simple stupid userspace
+application demo.
+
+You can use the sandbox to modify the kernel's linker table
+solution or add use it in creative ways without having to run
+qemu with a real kernel or user mode linux. You can simply try
+to extend this sandbox as you would for a regular userspace
+application.
+
+History
+=======
+
+This was hacked on first in an external repository, that tree has
+the full set of history of how this work came about. Refer to that
+tree for more details if you are interested in the logic used for
+a lot of decisions made for linker tables:
+
+https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linker-tables.git/
+
+This tree is discontinued now in favor of an upstream solution which
+is kept in sync with the kernel.
+
+Compile
+=======
+
+Run:
+	make
+
+Clean:
+	make clean
+
+If you need to get object files outside of the source tree:
+
+	make OUTPUT=/tmp/path/
+	make OUTPUT=/tmp/path/ clean
+
+Supported architectures
+=======================
+
+x86_64
+
+Currently only x86_64 is supported for the demo. It should be
+relatively easy to add more. To add a new architecture you need
+a toolchain available with libc. You then need to generate a
+respective base template custom linker script for userspace
+as is provided on x86 in arch/x86/kernel/vmlinux.lds.S.
+
+A respective architecture tools/arch/$(ARCH)/include/* file for
+each section-core.h, ranges.h, tables.h will need to be provided
+as well. If your architecture's file is generated copy the generated
+file over.
+
+x86 Simulated boots
+===================
+
+This programs simulates boot on both bare metal and with the
+Xen PV entry on x86.
+
+Emulate bare metal boot:
+
+./demo
+
+Emulate Xen boot (x86):
+
+./demo -x
+
+Testing new features
+====================
+
+A copy of each kernel header file is maintained in tools/include/,
+as well as a respective generated asm file for each sandbox supported
+architecture. This sandbox has a built in checker for when these files
+get out of sync.
+
+If testing new extensions on the files:
+
+  o section-core
+  o ranges.h
+  o tables.h
+
+You'll want to copy them into tools as well. If you are working on
+using these files you can work within the current directory's namespace,
+including its own set of header files, so tools/linker-tables/include/ and
+each respective tools/linker-tables/arch/$(ARCH)/include/asm/.
+
+Features evaluation
+===================
+
+This lists features currently being evaluated in the sandbox, not yet
+present upstream. These make use of the existing set of header files
+without modification.
+
+ o Demo use of initialization on for x86, refer to arch/x86/kernel/init.c
+
+ o Demo use of porting the kernel's init call levels to linker tables, refer
+   to the init_calls linker table use on kernel/main.c
+
+ o Demo use of an asm-generic architecture init family, which could potentially
+   be used to help share initialization sequences on simple architectures.
+   Refer to include/asm-generic/arch_init_fn.h
+
+ o Building synthetic routines with the option to provide enhancements
+   per architecture in asm, refer to drivers/synth/or.S and its use on
+   synth_init_or().
+
+ o User of linker tables for alternatives with consts - refer to
+   use of the ps_set_const_table linker table and its use in
+   arch/x86/kernel/alternative.c
diff --git a/tools/linker-tables/arch/x86/include/asm/asm.h b/tools/linker-tables/arch/x86/include/asm/asm.h
new file mode 100644
index 000000000000..155a52920dfb
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/asm.h
@@ -0,0 +1,17 @@
+#ifndef _ASM_X86_ASM_H
+
+#ifdef __ASSEMBLY__
+# define __ASM_FORM(x)	x
+# define __ASM_FORM_RAW(x)     x
+# define __ASM_FORM_COMMA(x) x,
+#else
+# define __ASM_FORM(x)	" " #x " "
+# define __ASM_FORM_RAW(x)     #x
+# define __ASM_FORM_COMMA(x) " " #x ","
+#endif
+
+# define __ASM_SEL(a,b) __ASM_FORM(b)
+# define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(b)
+#define _ASM_PTR	__ASM_SEL(.long, .quad)
+
+#endif /* _ASM_X86_ASM_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/boot.h b/tools/linker-tables/arch/x86/include/asm/boot.h
new file mode 100644
index 000000000000..af91b94ad5a6
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/boot.h
@@ -0,0 +1 @@
+extern struct boot_params boot_params;
diff --git a/tools/linker-tables/arch/x86/include/asm/bootparam.h b/tools/linker-tables/arch/x86/include/asm/bootparam.h
new file mode 100644
index 000000000000..a7ef34216f7f
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/bootparam.h
@@ -0,0 +1,32 @@
+#ifndef __BOOTPARAM_H
+#define __BOOTPARAM_H
+
+#include <linux/types.h>
+
+struct setup_header {
+	__u32 hardware_subarch;
+} __attribute__((packed));
+
+struct boot_params {
+	struct setup_header hdr;
+} __attribute__((packed));
+
+enum {
+	X86_SUBARCH_PC = 0,
+	X86_SUBARCH_LGUEST,
+	X86_SUBARCH_XEN,
+	X86_SUBARCH_INTEL_MID,
+	X86_SUBARCH_CE4100,
+	X86_NR_SUBARCHS,
+};
+
+#define X86_SUBARCH_ALL_SUBARCHS 	\
+	(				\
+	BIT(X86_SUBARCH_PC) |		\
+	BIT(X86_SUBARCH_LGUEST) |	\
+	BIT(X86_SUBARCH_XEN) |		\
+	BIT(X86_SUBARCH_INTEL_MID) |	\
+	BIT(X86_SUBARCH_CE4100)		\
+	)
+
+#endif /* __BOOTPARAM_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/kprobes.h b/tools/linker-tables/arch/x86/include/asm/kprobes.h
new file mode 100644
index 000000000000..f702fc359efe
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/kprobes.h
@@ -0,0 +1,7 @@
+#ifndef _SANDBOX_ASM_X86_KPROBES_H
+#define _SANDBOX_ASM_X86_KPROBES_H
+
+/* This is all we need for the demo */
+#include <asm-generic/kprobes.h>
+
+#endif /* _SANDBOX_ASM_X86_KPROBES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/ps_const.h b/tools/linker-tables/arch/x86/include/asm/ps_const.h
new file mode 100644
index 000000000000..3847f03fca92
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/ps_const.h
@@ -0,0 +1,23 @@
+#ifndef __X86_PS_CONST
+#define __X86_PS_CONST
+
+#include <linux/stringify.h>
+#include <linux/tables.h>
+#include <asm/asm.h>
+
+#define ps_shr(in, _func)						\
+({									\
+	 __typeof__(in) _count;						\
+									\
+	asm volatile(							\
+		"shr %P[_in],%[_count]\n"				\
+		"1:\n"							\
+		push_section_tbl(.init.data, ps_set_const_table, 01,)	\
+		_ASM_PTR "1b-1, %P2, %P3\n"				\
+		".popsection\n"						\
+		: [_count] "=g" (_count)				\
+		: [_in] "i" (in), "i" (SET_CONST_U8), "i" (_func));	\
+	(_count);							\
+})
+
+#endif /* __X86_PS_CONST */
diff --git a/tools/linker-tables/arch/x86/include/asm/ranges.h b/tools/linker-tables/arch/x86/include/asm/ranges.h
new file mode 100644
index 000000000000..823789d2b010
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/ranges.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_RANGES_H
+#define _ASM_X86_RANGES_H
+
+#include <asm-generic/ranges.h>
+
+#endif  /* _ASM_X86_RANGES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/section-core.h b/tools/linker-tables/arch/x86/include/asm/section-core.h
new file mode 100644
index 000000000000..06be2b1c424f
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/section-core.h
@@ -0,0 +1 @@
+#include <asm-generic/section-core.h>
diff --git a/tools/linker-tables/arch/x86/include/asm/setup.h b/tools/linker-tables/arch/x86/include/asm/setup.h
new file mode 100644
index 000000000000..366c36bd2910
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/setup.h
@@ -0,0 +1,6 @@
+#ifndef __LINUX_X86_USER_SETUP_H
+#define __LINUX_X86_USER_SETUP_H
+
+/* I'm lazy */
+
+#endif /* __LINUX_X86_USER_SETUP_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/tables.h b/tools/linker-tables/arch/x86/include/asm/tables.h
new file mode 100644
index 000000000000..797df3407ee1
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/tables.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_TABLES_H
+#define _ASM_X86_TABLES_H
+
+#include <asm-generic/tables.h>
+
+#endif  /* _ASM_X86_RANGES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/x86.h b/tools/linker-tables/arch/x86/include/asm/x86.h
new file mode 100644
index 000000000000..680c1141e0de
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/x86.h
@@ -0,0 +1,4 @@
+int startup_64(void);
+int x86_64_start_reservations(void);
+void setup_arch(void);
+void late_init(void);
diff --git a/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h b/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
new file mode 100644
index 000000000000..afece8ce6dd4
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
@@ -0,0 +1,169 @@
+#ifndef __X86_INIT_TABLES_H
+#define __X86_INIT_TABLES_H
+
+#include <linux/types.h>
+#include <linux/tables.h>
+
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <asm/bootparam.h>
+
+/**
+ * struct x86_init_fn - x86 generic kernel init call
+ *
+ * Linux x86 features vary in complexity, features may require work done at
+ * different levels of the full x86 init sequence. Today there are also two
+ * different possible entry points for Linux on x86, one for bare metal, KVM
+ * and Xen HVM, and another for Xen PV guests / dom0.  Assuming a bootloader
+ * has set up 64-bit mode, roughly the x86 init sequence follows this path:
+ *
+ * Bare metal, KVM, Xen HVM                      Xen PV / dom0
+ *       startup_64()                             startup_xen()
+ *              \                                     /
+ *      x86_64_start_kernel()                 xen_start_kernel()
+ *                           \               /
+ *                      x86_64_start_reservations()
+ *                                   |
+ *                              start_kernel()
+ *                              [   ...        ]
+ *                              [ setup_arch() ]
+ *                              [   ...        ]
+ *                                  init
+ *
+ * x86_64_start_kernel() and xen_start_kernel() are the respective first C code
+ * entry starting points. The different entry points exist to enable Xen to
+ * skip a lot of hardware setup already done and managed on behalf of the
+ * hypervisor, we refer to this as "paravirtualization yielding". The different
+ * levels of init calls on the x86 init sequence exist to account for these
+ * slight differences and requirements. These different entry points also share
+ * a common entry x86 specific path, x86_64_start_reservations().
+ *
+ * A generic x86 feature can have different initialization calls, one on each
+ * of the different main x86 init sequences, but must also address both entry
+ * points in order to work properly across the board on all supported x86
+ * subarchitectures. Since x86 features can also have dependencies on other
+ * setup code or features, x86 features can at times be subordinate to other
+ * x86 features, or conditions. struct x86_init_fn enables feature developers
+ * to annotate dependency relationships to ensure subsequent init calls only
+ * run once a subordinate's dependencies have run. When needed custom
+ * dependency requirements can also be spelled out through a custom dependency
+ * checker. In order to account for the dual entry point nature of x86-64 Linux
+ * for "paravirtualization yielding" and to make annotations for support for
+ * these explicit each struct x86_init_fn must specify supported
+ * subarchitectures. The earliest x86-64 code can read the subarchitecture
+ * though is after load_idt(), as such the earliest we can currently rely on
+ * subarchitecture for semantics and a common init sequences is on the shared
+ * common x86_64_start_reservations().  Each struct x86_init_fn is associated
+ * with a specific special link order number which has been careflly thought
+ * out by x86 maintainers. You should pick a link order level associated with
+ * the specific directory your code lies in, a respective macro is used to
+ * build association to a link oder with a routine, you should use one of the
+ * provided x86_init_*() macros. You should not use __x86_init() directly.
+ *
+ * x86_init_fn enables strong semantics and dependencies to be defined and
+ * implemented on the full x86 initialization sequence.
+ *
+ * @supp_hardware_subarch: must be set, it represents the bitmask of supported
+ *	subarchitectures.  We require each struct x86_init_fn to have this set
+ *	to require developer considerations for each supported x86
+ *	subarchitecture and to build strong annotations of different possible
+ *	run time states particularly in consideration for the two main
+ *	different entry points for x86 Linux, to account for paravirtualization
+ *	yielding.
+ *
+ *	The subarchitecture is read by the kernel at early boot from the
+ *	struct boot_params hardware_subarch. Support for the subarchitecture
+ *	exists as of x86 boot protocol 2.07. The bootloader would have set up
+ *	the respective hardware_subarch on the boot sector as per
+ *	Documentation/x86/boot.txt.
+ *
+ *	What x86 entry point is used is determined at run time by the
+ *	bootloader. Linux pv_ops was designed to help enable to build one Linux
+ *	binary to support bare metal and different hypervisors.  pv_ops setup
+ *	code however is limited in that all pv_ops setup code is run late in
+ *	the x86 init sequence, during setup_arch(). In fact cpu_has_hypervisor
+ *	only works after early_cpu_init() during setup_arch(). If an x86
+ *	feature requires an earlier determination of what hypervisor was used,
+ *	or if it needs to annotate only support for certain hypervisors, the
+ *	x86 hardware_subarch should be set by the bootloader and
+ *	@supp_hardware_subarch set by the x86 feature. Using hardware_subarch
+ *	enables x86 features to fill the semantic gap between the Linux x86
+ *	entry point used and what pv_ops has to offer through a hypervisor
+ *	agnostic mechanism.
+ *
+ *	Each supported subarchitecture is set using the respective
+ *	X86_SUBARCH_* as a bit in the bitmask. For instance if a feature
+ *	is supported on PC and Xen subarchitectures only you would set this
+ *	bitmask to:
+ *
+ *		BIT(X86_SUBARCH_PC) |
+ *		BIT(X86_SUBARCH_XEN);
+ *
+ * @early_init: required, routine which will run in x86_64_start_reservations()
+ *	after we ensure boot_params.hdr.hardware_subarch is accessible and
+ *	properly set. Memory is not yet available. This the earliest we can
+ *	currently define a common shared callback since all callbacks need to
+ *	check for boot_params.hdr.hardware_subarch and this becomes accessible
+ *	on x86-64 until after load_idt().
+ */
+struct x86_init_fn {
+	__u32 supp_hardware_subarch;
+	void (*early_init)(void);
+};
+
+DECLARE_LINKTABLE(struct x86_init_fn, x86_init_fns);
+
+/* Init order levels, we can start at 0000 but reserve 0000-0999 for now */
+
+/*
+ * X86_INIT_ORDER_EARLY - early kernel init code
+ *
+ * This consists of the first parts of the Linux kernel executed.
+ */
+#define X86_INIT_ORDER_EARLY	1000
+
+/* X86_INIT_ORDER_PLATFORM - platform kernel code
+ *
+ * Code the kernel needs to initialize under arch/x86/platform/
+ * early in boot.
+ */
+#define X86_INIT_ORDER_PLATFORM	3000
+
+#define __x86_init(__level,						\
+		   __supp_hardware_subarch,				\
+		   __early_init)					\
+	static LINKTABLE_INIT_DATA(x86_init_fns, __level)		\
+	__x86_init_fn_##__early_init = {				\
+		.supp_hardware_subarch = __supp_hardware_subarch,	\
+		.early_init = __early_init,				\
+	};
+
+#define x86_init_early(__supp_hardware_subarch,				\
+		       __early_init)					\
+	__x86_init(X86_INIT_ORDER_EARLY, __supp_hardware_subarch,	\
+		   __early_init);
+
+#define x86_init_platform(__supp_hardware_subarch,			\
+		       __early_init)					\
+	__x86_init(__name, X86_INIT_ORDER_PLATFORM, __supp_hardware_subarch,\
+		   __early_init);
+
+#define x86_init_early_all(__early_init)				\
+	x86_init_early(X86_SUBARCH_ALL_SUBARCHS,			\
+		       __early_init);
+
+#define x86_init_early_pc(__early_init)					\
+	x86_init_early(BIT(X86_SUBARCH_PC),				\
+		       __early_init);
+
+#define x86_init_early_xen(__early_init)				\
+	x86_init_early(BIT(X86_SUBARCH_XEN),				\
+		       __early_init);
+/**
+ * x86_init_fn_early_init: call all early_init() callbacks
+ *
+ * This calls all early_init() callbacks on the x86_init_fns linker table.
+ */
+void x86_init_fn_early_init(void);
+
+#endif /* __X86_INIT_TABLES_H */
diff --git a/tools/linker-tables/arch/x86/kernel/alpha.c b/tools/linker-tables/arch/x86/kernel/alpha.c
new file mode 100644
index 000000000000..0f9d45734c33
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/alpha.c
@@ -0,0 +1,9 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_alpha(void) {
+	pr_info("Initializing alpha ...\n");
+	pr_info("Completed initializing alpha !\n");
+}
+
+x86_init_early_pc(early_init_alpha);
diff --git a/tools/linker-tables/arch/x86/kernel/alternative.c b/tools/linker-tables/arch/x86/kernel/alternative.c
new file mode 100644
index 000000000000..8e2495669c92
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/alternative.c
@@ -0,0 +1,31 @@
+#include <asm/x86_init_fn.h>
+
+#include <linux/kernel.h>
+#include <linux/ps_const.h>
+
+void apply_alternatives_linker_tables(void)
+{
+	unsigned int num_consts = LINKTABLE_SIZE(ps_set_const_table);
+	struct ps_set_const *ps_const;
+
+	if (!num_consts)
+		return;
+
+	pr_debug("Number of init entries: %d\n", num_consts);
+
+	linktable_for_each(ps_const, ps_set_const_table) {
+		switch(ps_const->type) {
+		case SET_CONST_U8:
+			*ps_const->count = (__u8) ps_const->func();
+			break;
+		case SET_CONST_U16:
+			*ps_const->count = (__u16) ps_const->func();
+			break;
+		case SET_CONST_U32:
+			*ps_const->count = (__u16) ps_const->func();
+			break;
+		}
+	}
+}
+
+x86_init_early_pc(apply_alternatives_linker_tables);
diff --git a/tools/linker-tables/arch/x86/kernel/beta.c b/tools/linker-tables/arch/x86/kernel/beta.c
new file mode 100644
index 000000000000..2bdbf49d4731
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/beta.c
@@ -0,0 +1,9 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_beta(void) {
+	pr_info("Initializing beta ...\n");
+	pr_info("Completed initializing beta !\n");
+}
+
+x86_init_early_pc(early_init_beta);
diff --git a/tools/linker-tables/arch/x86/kernel/head64.c b/tools/linker-tables/arch/x86/kernel/head64.c
new file mode 100644
index 000000000000..d14dcdfd0ea9
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/head64.c
@@ -0,0 +1,58 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+
+#include <asm/x86_init_fn.h>
+#include <asm/boot.h>
+#include <asm/bootparam.h>
+
+#include <linux/start_kernel.h>
+#include <linux/kasan.h>
+
+void x86_64_start_reservations(void)
+{
+	switch (boot_params.hdr.hardware_subarch) {
+	case X86_SUBARCH_PC:
+		pr_info("Booting bare metal\n");
+		break;
+	case X86_SUBARCH_LGUEST:
+		pr_info("Booting lguest not supported\n");
+		BUG();
+	case X86_SUBARCH_XEN:
+		pr_info("Booting a Xen guest\n");
+		break;
+	case X86_SUBARCH_INTEL_MID:
+		pr_info("Booting Intel MID not supported\n");
+		BUG();
+	case X86_SUBARCH_CE4100:
+		pr_info("Booting Intel CE4100 not supported\n");
+		BUG();
+	default:
+		pr_info("Booting sunsupported x86 hardware subarch\n");
+		BUG();
+	}
+
+	start_kernel();
+}
+
+static void x86_64_start_kernel(void)
+{
+	x86_init_fn_early_init();
+
+	x86_64_start_reservations();
+}
+
+void startup_64(void)
+{
+	pr_info("Initializing x86 bare metal world\n");
+	x86_64_start_kernel();
+}
+
+void setup_arch(void)
+{
+	/* TODO: x86_init_fn_setup_arch(); */
+}
+
+void late_init(void)
+{
+	/* TODO: x86_init_fn_late_init(); */
+}
diff --git a/tools/linker-tables/arch/x86/kernel/init.c b/tools/linker-tables/arch/x86/kernel/init.c
new file mode 100644
index 000000000000..1eed92d1acb2
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/init.c
@@ -0,0 +1,42 @@
+#define pr_fmt(fmt) "x86-init: " fmt
+
+#include <linux/bug.h>
+#include <linux/kernel.h>
+
+#include <asm/x86_init_fn.h>
+#include <asm/bootparam.h>
+#include <asm/boot.h>
+#include <asm/setup.h>
+
+DEFINE_LINKTABLE_INIT_DATA(struct x86_init_fn, x86_init_fns);
+
+static bool x86_init_fn_supports_subarch(struct x86_init_fn *fn)
+{
+	if (!fn->supp_hardware_subarch) {
+		//pr_err("Init sequence fails to declares any supported subarchs: %pF\n", fn->early_init);
+		WARN_ON(1);
+	}
+	if (BIT(boot_params.hdr.hardware_subarch) & fn->supp_hardware_subarch)
+		return true;
+	return false;
+}
+
+void __ref x86_init_fn_early_init(void)
+{
+	struct x86_init_fn *init_fn;
+	unsigned int num_inits = LINKTABLE_SIZE(x86_init_fns);
+
+	if (!num_inits)
+		return;
+
+	pr_debug("Number of init entries: %d\n", num_inits);
+
+	linktable_for_each(init_fn, x86_init_fns) {
+		if (!x86_init_fn_supports_subarch(init_fn))
+			continue;
+
+		//pr_debug("Running early init %pF ...\n", init_fn->early_init);
+		init_fn->early_init();
+		//pr_debug("Completed early init %pF\n", init_fn->early_init);
+	}
+}
diff --git a/tools/linker-tables/arch/x86/kernel/kasan.c b/tools/linker-tables/arch/x86/kernel/kasan.c
new file mode 100644
index 000000000000..c0120676eb9c
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/kasan.c
@@ -0,0 +1,10 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+void kasan_early_init(void) {
+	pr_info("Initializing kasan ...\n");
+	pr_info("Early init for Kasan...\n");
+	pr_info("Completed initializing kasan !\n");
+}
+
+x86_init_early_pc(kasan_early_init);
diff --git a/tools/linker-tables/arch/x86/kernel/kprobes.c b/tools/linker-tables/arch/x86/kernel/kprobes.c
new file mode 100644
index 000000000000..c4e42beae55b
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/kprobes.c
@@ -0,0 +1,51 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <linux/ranges.h>
+#include <linux/kprobes.h>
+
+DEFINE_SECTION_RANGE(kprobes, .text);
+
+void __kprobes test_kprobe_0001(void)
+{
+	pr_info("test_kprobe\n");
+}
+
+void test_kprobe_0002(void)
+{
+	pr_info("test_kprobe\n");
+}
+
+void test_kprobe_addr(const char *test, unsigned long addr, bool should_match)
+{
+	if (SECTION_RANGE_ADDR_WITHIN(kprobes, addr))
+		if (should_match)
+			pr_info("== OK: %s within range!\n", test);
+		else
+			pr_info("== FAIL: %s should not be in range...\n",
+				test);
+	else
+		if (should_match)
+			pr_info("== FAIL: %s should be in range...\n", test);
+		else
+			pr_info("== OK: %s not in range as expected!\n", test);
+}
+
+void early_init_kprobes(void)
+{
+	unsigned long addr;
+
+	pr_info("Initializing kprobes ...\n");
+
+	addr = (unsigned long) &test_kprobe_0001;
+
+	test_kprobe_addr("test_kprobe_0001", addr, true);
+
+	addr = (unsigned long) &test_kprobe_0002;
+
+	test_kprobe_addr("test_kprobe_0002", addr, false);
+
+	pr_info("Completed initializing kprobes !\n");
+}
+
+x86_init_early_all(early_init_kprobes);
diff --git a/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S b/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
new file mode 100644
index 000000000000..783735fb897a
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
@@ -0,0 +1,277 @@
+/* Script for -z combreloc: combine and sort reloc sections */
+/* Copyright (C) 2014 Free Software Foundation, Inc.
+   Copying and distribution of this script, with or without modification,
+   are permitted in any medium without royalty provided the copyright
+   notice and this notice are preserved.  */
+
+#include <asm/section-core.h>
+#include <asm/ranges.h>
+#include <asm/tables.h>
+
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
+	      "elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(_start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
+  .interp         : { *(.interp) }
+  .note.gnu.build-id : { *(.note.gnu.build-id) }
+  .hash           : { *(.hash) }
+  .gnu.hash       : { *(.gnu.hash) }
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+  .rela.dyn       :
+    {
+      *(.rela.init)
+      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+      *(.rela.fini)
+      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+      *(.rela.ctors)
+      *(.rela.dtors)
+      *(.rela.got)
+      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+      *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
+      *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
+      *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
+      *(.rela.ifunc)
+    }
+  .rela.plt       :
+    {
+      *(.rela.plt)
+      PROVIDE_HIDDEN (__rela_iplt_start = .);
+      *(.rela.iplt)
+      PROVIDE_HIDDEN (__rela_iplt_end = .);
+    }
+  .init           :
+  {
+    KEEP (*(SORT_NONE(.init)))
+  }
+  .plt            : { *(.plt) *(.iplt) }
+  .plt.bnd        : { *(.plt.bnd) }
+  .text           :
+  {
+    *(.text.unlikely .text.*_unlikely .text.unlikely.*)
+    *(.text.exit .text.exit.*)
+    *(.text.startup .text.startup.*)
+    *(.text.hot .text.hot.*)
+
+    *(SORT(.text..rng.*))
+    *(SORT(.text..tbl.*))
+
+    *(SORT(.init.text..rng.*))
+    *(SORT(.init.text..tbl.*))
+
+    *(SORT(.initcall..rng.*))
+    *(SORT(.initcall..tbl.*))
+
+    *(SORT(.exit.text..rng.*))
+    *(SORT(.exit.text..tbl.*))
+
+    *(SORT(.exitcall.exit..rng.*))
+    *(SORT(.exitcall.exit..tbl.*))
+
+    *(.text .stub .text.* .gnu.linkonce.t.*)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  }
+  .fini           :
+  {
+    KEEP (*(SORT_NONE(.fini)))
+  }
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+  .rodata         :
+  {
+	*(.rodata)
+
+	*(SORT(.rodata.*))
+
+	*(SORT(.rodata..rng.*))
+	*(SORT(.rodata..tbl.*))
+
+	*(SORT(.init.rodata..rng.*))
+	*(SORT(.init.rodata..tbl.*))
+
+	*(SORT(.ref.rodata..rng.*))
+	*(SORT(.ref.rodata..tbl.*))
+
+	*(.gnu.linkonce.r.*)
+  }
+  .rodata1        : { *(.rodata1) }
+  .eh_frame_hdr : { *(.eh_frame_hdr) }
+  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table
+  .gcc_except_table.*) }
+  /* These sections are generated by the Sun/Oracle C++ compiler.  */
+  .exception_ranges   : ONLY_IF_RO { *(.exception_ranges
+  .exception_ranges*) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  */
+  . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+  /* Exception handling  */
+  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
+  .exception_ranges   : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
+  /* Thread Local Storage sections  */
+  .tdata	  : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+  .preinit_array     :
+  {
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP (*(.preinit_array))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+  }
+  .init_array     :
+  {
+    PROVIDE_HIDDEN (__init_array_start = .);
+    KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
+    KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
+    PROVIDE_HIDDEN (__init_array_end = .);
+  }
+  .fini_array     :
+  {
+    PROVIDE_HIDDEN (__fini_array_start = .);
+    KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
+    KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
+    PROVIDE_HIDDEN (__fini_array_end = .);
+  }
+  .ctors          :
+  {
+    /* gcc uses crtbegin.o to find the start of
+       the constructors, so we make sure it is
+       first.  Because this is a wildcard, it
+       doesn't matter if the user does not
+       actually link against crtbegin.o; the
+       linker won't look for a file to match a
+       wildcard.  The wildcard also means that it
+       doesn't matter which directory crtbegin.o
+       is in.  */
+    KEEP (*crtbegin.o(.ctors))
+    KEEP (*crtbegin?.o(.ctors))
+    /* We don't want to include the .ctor section from
+       the crtend.o file until after the sorted ctors.
+       The .ctor section from the crtend file contains the
+       end of ctors marker and it must be last */
+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+  .dtors          :
+  {
+    KEEP (*crtbegin.o(.dtors))
+    KEEP (*crtbegin?.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  .jcr            : { KEEP (*(.jcr)) }
+  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
+  .dynamic        : { *(.dynamic) }
+  .got            : { *(.got) *(.igot) }
+  . = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
+  .got.plt        : { *(.got.plt)  *(.igot.plt) }
+  .data           :
+  {
+    *(.data .data.* .gnu.linkonce.d.*)
+
+    *(SORT(.data..rng.*))
+    *(SORT(.data..tbl.*))
+
+    *(SORT(.init.data..rng.*))
+    *(SORT(.init.data..tbl.*))
+
+    *(SORT(.ref.rodata..rng.*))
+    *(SORT(.ref.rodata..tbl.*))
+
+    *(SORT(.exit.data..rng.*))
+    *(SORT(.exit.data..tbl.*))
+
+    SORT(CONSTRUCTORS)
+  }
+  .data1          : { *(.data1) }
+  _edata = .; PROVIDE (edata = .);
+  . = .;
+
+  __bss_start = .;
+  .bss            :
+  {
+   *(.dynbss)
+   *(.bss .bss.* .gnu.linkonce.b.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.
+      FIXME: Why do we need it? When there is no .bss section, we don't
+      pad the .data section.  */
+   . = ALIGN(. != 0 ? 64 / 8 : 1);
+  }
+  .lbss   :
+  {
+    *(.dynlbss)
+    *(.lbss .lbss.* .gnu.linkonce.lb.*)
+    *(LARGE_COMMON)
+  }
+  . = ALIGN(64 / 8);
+  . = SEGMENT_START("ldata-segment", .);
+  .lrodata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+  {
+    *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
+  }
+  .ldata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+  {
+    *(.ldata .ldata.* .gnu.linkonce.l.*)
+    . = ALIGN(. != 0 ? 64 / 8 : 1);
+  }
+  . = ALIGN(64 / 8);
+  _end = .; PROVIDE (end = .);
+  . = DATA_SEGMENT_END (.);
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line .debug_line.* .debug_line_end ) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  /* DWARF 3 */
+  .debug_pubtypes 0 : { *(.debug_pubtypes) }
+  .debug_ranges   0 : { *(.debug_ranges) }
+  /* DWARF Extension.  */
+  .debug_macro    0 : { *(.debug_macro) }
+  .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
+}
diff --git a/tools/linker-tables/arch/x86/mm/init.c b/tools/linker-tables/arch/x86/mm/init.c
new file mode 100644
index 000000000000..dbf1a85a4043
--- /dev/null
+++ b/tools/linker-tables/arch/x86/mm/init.c
@@ -0,0 +1,10 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_memory(void) {
+	pr_info("Initializing memory ...\n");
+	sleep(1);
+	pr_info("Completed initializing memory !\n");
+}
+
+x86_init_early_all(early_init_memory);
diff --git a/tools/linker-tables/arch/x86/xen/init.c b/tools/linker-tables/arch/x86/xen/init.c
new file mode 100644
index 000000000000..40ad493daee8
--- /dev/null
+++ b/tools/linker-tables/arch/x86/xen/init.c
@@ -0,0 +1,13 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <asm/x86.h>
+
+void startup_xen(void)
+{
+	pr_info("Initializing Xen guest\n");
+
+	x86_init_fn_early_init();
+
+	x86_64_start_reservations();
+}
diff --git a/tools/linker-tables/drivers/acme.c b/tools/linker-tables/drivers/acme.c
new file mode 100644
index 000000000000..dd321686dd49
--- /dev/null
+++ b/tools/linker-tables/drivers/acme.c
@@ -0,0 +1,32 @@
+#define pr_fmt(fmt) "ACME: " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/workqueue.h>
+
+void *acme_todo(void *arg);
+static DECLARE_WORK(acme_work, acme_todo);
+
+void *acme_todo(void *arg)
+{
+	pr_info("Running scheduled work\n");
+	pthread_exit(NULL);
+}
+
+static int acme_init_driver(void) {
+	pr_info("Initializing ...\n");
+	sleep(2);
+	pr_info("Finished init ... !\n");
+
+	init_work(&acme_work);
+	schedule_work(&acme_work);
+
+	return 0;
+}
+module_init(acme_init_driver);
+
+static void acme_exit(void)
+{
+	cancel_work_sync(&acme_work);
+};
+module_exit(acme_exit);
diff --git a/tools/linker-tables/drivers/synth/common.c b/tools/linker-tables/drivers/synth/common.c
new file mode 100644
index 000000000000..b44d9fcc7a9b
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/common.c
@@ -0,0 +1,16 @@
+int demo_or_1(int arg)
+{
+	switch (arg) {
+	case 1:
+		return 0xDEA00000;
+	case 2:
+		return 0X000D0000;
+	default:
+		return arg * 2;
+	}
+}
+
+int demo_or_2(void)
+{
+	return 0x0000BEEF;
+}
diff --git a/tools/linker-tables/drivers/synth/common.h b/tools/linker-tables/drivers/synth/common.h
new file mode 100644
index 000000000000..92827004f532
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/common.h
@@ -0,0 +1,2 @@
+int demo_or_1(int arg);
+int demo_or_2(void);
diff --git a/tools/linker-tables/drivers/synth/main.c b/tools/linker-tables/drivers/synth/main.c
new file mode 100644
index 000000000000..555cf97a5cbb
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/main.c
@@ -0,0 +1,35 @@
+#define pr_fmt(fmt) "Synthetics: " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ps_const.h>
+
+#include "common.h"
+#include "synth.h"
+
+DEFINE_LINKTABLE_INIT_DATA(struct ps_set_const, ps_set_const_table);
+
+unsigned int get_demo_shr(void)
+{
+	return 16;
+}
+
+static int synth_init(void)
+{
+	int synth_or;
+	int val = 2;
+	const unsigned int reg =  ps_shr(0xDEADBEEF, get_demo_shr);
+
+	synth_or = synth_init_or(val);
+	pr_info("synth_init_or(%d) returns: 0x%08X\n", val, synth_or);
+
+	pr_info("ps_shr(0x%08X, get_demo_shr) returns: 0x%08X\n", 0xDEADBEEF, reg);
+
+	return 0;
+}
+module_init(synth_init);
+
+static void synth_exit(void)
+{
+}
+module_exit(synth_exit);
diff --git a/tools/linker-tables/drivers/synth/or.S b/tools/linker-tables/drivers/synth/or.S
new file mode 100644
index 000000000000..deb963fdae33
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/or.S
@@ -0,0 +1,39 @@
+#include <asm/ranges.h>
+
+	DEFINE_SECTION_RANGE(.text, synth_init_or)
+
+	push_section_rng_level(.text, synth_init_or, "01", )
+	/* err = 0; */
+	pushq %rbp
+	movq %rsp,%rbp
+	pushq %rbx
+	xorq %rbx,%rbx
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "99", )
+	/* return err; */
+	movq %rbx,%rax
+	popq %rbx
+	popq %rbp
+	retq
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "50", )
+	/* err |= demo_or_1(1); */
+	movl $1,%edi
+	call demo_or_1
+	orq %rax,%rbx
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "50", )
+	/* err |= demo_or_1(2); */
+	movl $2,%edi
+	call demo_or_1
+	orq %rax,%rbx
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "50", )
+	/* err |= demo_or_2(); */
+	call demo_or_2
+	orq %rax,%rbx
+	.popsection
diff --git a/tools/linker-tables/drivers/synth/synth.h b/tools/linker-tables/drivers/synth/synth.h
new file mode 100644
index 000000000000..abbb9afac374
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/synth.h
@@ -0,0 +1,2 @@
+/* Synthetic demos go here */
+int synth_init_or(int arg);
diff --git a/tools/linker-tables/drivers/xen-driver.c b/tools/linker-tables/drivers/xen-driver.c
new file mode 100644
index 000000000000..79d229f72818
--- /dev/null
+++ b/tools/linker-tables/drivers/xen-driver.c
@@ -0,0 +1,11 @@
+#include <asm/x86_init_fn.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <xen/xen.h>
+
+static void early_xen_init_driver(void) {
+	pr_info("Initializing xen driver\n");
+	sleep(2);
+}
+
+x86_init_early_xen(early_xen_init_driver);
diff --git a/tools/linker-tables/include/asm-generic/arch_init_fn.h b/tools/linker-tables/include/asm-generic/arch_init_fn.h
new file mode 100644
index 000000000000..61a04a50b453
--- /dev/null
+++ b/tools/linker-tables/include/asm-generic/arch_init_fn.h
@@ -0,0 +1,50 @@
+#ifndef __ARCH_INIT_TABLES_H
+#define __ARCH_INIT_TABLES_H
+
+#include <linux/types.h>
+#include <linux/tables.h>
+#include <linux/init.h>
+
+/**
+ * struct arch_init_fn - architecture-generic kernel init call
+ *
+ * Architectures must initialize a series of things prior to handing off
+ * control to the kernel. This structure can be used if the architecture is
+ * simple and it just needs a basic set of calls on its way up.
+ *
+ * @early_init: required, routine which will run in startup_64(). Memory is
+ * 	not yet available.
+ */
+struct arch_init_fn {
+	void (*early_init)(void);
+};
+
+DECLARE_LINKTABLE(struct arch_init_fn, arch_init_fns);
+
+/* Init order levels, we can start at 0000 but reserve 0000-0999 for now */
+
+/*
+ * ARCH_INIT_ORDER_EARLY - early kernel init code
+ *
+ * This consists of the first parts of the Linux kernel executed.
+ */
+#define ARCH_INIT_ORDER_EARLY	1000
+
+#define __arch_init(__level,						\
+		    __early_init)					\
+	static LINKTABLE_INIT_DATA(arch_init_fns, __level)		\
+	__arch_init_fn_##__early_init = {				\
+		.early_init = __early_init,				\
+	}
+
+#define arch_init_early(__early_init)					\
+	__arch_init(ARCH_INIT_ORDER_EARLY, __early_init)
+
+/**
+ * arch_init_fn_early_init: call all early_init() callbacks
+ *
+ * This calls all early_init() callbacks on the arch_init_fns linker table.
+ */
+void arch_init_fn_early_init(void);
+
+#endif /* __ARCH_INIT_TABLES_H */
diff --git a/tools/linker-tables/include/asm-generic/kprobes.h b/tools/linker-tables/include/asm-generic/kprobes.h
new file mode 100644
index 000000000000..839d2eb464d3
--- /dev/null
+++ b/tools/linker-tables/include/asm-generic/kprobes.h
@@ -0,0 +1,26 @@
+#ifndef _SANDBOX_ASM_GENERIC_KPROBES_H
+#define _SANDBOX_ASM_GENERIC_KPROBES_H
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#ifdef CONFIG_KPROBES
+#include <linux/tables.h>
+#include <asm/ranges.h>
+/*
+ * Blacklist ganerating macro. Specify functions which is not probed
+ * by using this macro.
+ */
+# define __NOKPROBE_SYMBOL(fname)				\
+static LINKTABLE_INIT_DATA(_kprobe_blacklist, all)		\
+	_kbl_addr_##fname = (unsigned long)fname;
+# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
+/* Use this to forbid a kprobes attach on very low level functions */
+# define __kprobes	__LINUX_RANGE(.text, kprobes)
+# define nokprobe_inline	__always_inline
+#else
+# define NOKPROBE_SYMBOL(fname)
+# define __kprobes
+# define nokprobe_inline	inline
+#endif
+#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
+
+#endif /* _SANDBOX_ASM_GENERIC_KPROBES_H */
diff --git a/tools/linker-tables/include/linux/bitops.h b/tools/linker-tables/include/linux/bitops.h
new file mode 100644
index 000000000000..2960e8089ebc
--- /dev/null
+++ b/tools/linker-tables/include/linux/bitops.h
@@ -0,0 +1,6 @@
+#ifndef _LINUX_BITOPS_H
+#define _LINUX_BITOPS_H
+
+#define BIT(nr)		(1UL << (nr))
+
+#endif /* _LINUX_BITOPS_H */
diff --git a/tools/linker-tables/include/linux/init.h b/tools/linker-tables/include/linux/init.h
new file mode 100644
index 000000000000..2691c3697f48
--- /dev/null
+++ b/tools/linker-tables/include/linux/init.h
@@ -0,0 +1,40 @@
+#ifndef _SANDBOX_LINUX_INIT_H
+#define _SANDBOX_LINUX_INIT_H
+
+#include_next <linux/init.h>
+#include <linux/types.h>
+#include <linux/sections.h>
+
+#define __init	__section(.init.text)
+#define __exit	__section(.exit.text)
+
+#ifndef __ASSEMBLY__
+#include <linux/tables.h>
+typedef int (*initcall_t)(void);
+typedef void (*exitcall_t)(void);
+
+DECLARE_LINKTABLE(initcall_t, init_calls);
+DECLARE_LINKTABLE(exitcall_t, exit_calls);
+
+#define __define_initcall(fn, id)					\
+	static LINKTABLE_INIT_DATA(init_calls, id)			\
+	__initcall_##fn##id = fn
+
+#define pure_initcall(fn)			__define_initcall(fn, 0)
+#define core_initcall(fn)			__define_initcall(fn, 1)
+#define postcore_initcall(fn)			__define_initcall(fn, 2)
+#define arch_initcall(fn)			__define_initcall(fn, 3)
+#define subsys_initcall(fn)			__define_initcall(fn, 4)
+#define fs_initcall(fn)				__define_initcall(fn, 5)
+#define device_initcall(fn)			__define_initcall(fn, 6)
+#define late_initcall(fn)			__define_initcall(fn, 7)
+
+#define __initcall(fn)				device_initcall(fn)
+
+#define __exitcall(fn)							\
+	static LINKTABLE_INIT_DATA(exit_calls, any)			\
+	__exitcall_##fn = fn;
+
+#endif
+
+#endif /* _SANDBOX_LINUX_INIT_H */
diff --git a/tools/linker-tables/include/linux/kasan.h b/tools/linker-tables/include/linux/kasan.h
new file mode 100644
index 000000000000..41791187854e
--- /dev/null
+++ b/tools/linker-tables/include/linux/kasan.h
@@ -0,0 +1,5 @@
+#include <linux/types.h>
+
+void kasan_early_init(void);
+int kasan_init(void);
+bool is_kasan_setup(void);
diff --git a/tools/linker-tables/include/linux/kernel.h b/tools/linker-tables/include/linux/kernel.h
new file mode 100644
index 000000000000..e2857c0b5b11
--- /dev/null
+++ b/tools/linker-tables/include/linux/kernel.h
@@ -0,0 +1,2 @@
+#include_next <linux/kernel.h>
+#include <linux/printk.h>
diff --git a/tools/linker-tables/include/linux/kprobes.h b/tools/linker-tables/include/linux/kprobes.h
new file mode 100644
index 000000000000..ecd5a0a69ae6
--- /dev/null
+++ b/tools/linker-tables/include/linux/kprobes.h
@@ -0,0 +1,11 @@
+#ifndef _SANDBOX_LINUX_KPROBES_H
+#define _SANDBOX_LINUX_KPROBES_H
+
+#include <asm/kprobes.h>
+#include <linux/ranges.h>
+
+#ifdef CONFIG_KPROBES
+DECLARE_SECTION_RANGE(kprobes);
+#endif
+
+#endif /* _SANDBOX_LINUX_KPROBES_H */
diff --git a/tools/linker-tables/include/linux/module.h b/tools/linker-tables/include/linux/module.h
new file mode 100644
index 000000000000..b59e55f3f04e
--- /dev/null
+++ b/tools/linker-tables/include/linux/module.h
@@ -0,0 +1,14 @@
+#ifndef _LINUX_MODULE_H
+#define _LINUX_MODULE_H
+
+#include <linux/init.h>
+
+#define module_init(x)  __initcall(x);
+#define module_exit(x)  __exitcall(x);
+
+struct module {
+	int (*init)(void);
+	void (*exit)(void);
+};
+
+#endif /* _LINUX_MODULE_H */
diff --git a/tools/linker-tables/include/linux/mutex.h b/tools/linker-tables/include/linux/mutex.h
new file mode 100644
index 000000000000..a74f951ceb42
--- /dev/null
+++ b/tools/linker-tables/include/linux/mutex.h
@@ -0,0 +1,17 @@
+#ifndef __LINUX_MUTEX_H
+#define __LINUX_MUTEX_H
+
+#include <sys/types.h>
+#include <linux/sched.h>
+#include <pthread.h>
+
+struct mutex {
+	pthread_mutex_t lock;
+};
+
+void mutex_init(struct mutex *lock);
+void mutex_destroy(struct mutex *lock);
+void mutex_lock(struct mutex *lock);
+void mutex_unlock(struct mutex *lock);
+
+#endif /* __LINUX_MUTEX_H */
diff --git a/tools/linker-tables/include/linux/pci.h b/tools/linker-tables/include/linux/pci.h
new file mode 100644
index 000000000000..8518c46631f7
--- /dev/null
+++ b/tools/linker-tables/include/linux/pci.h
@@ -0,0 +1,7 @@
+#include <linux/types.h>
+
+struct pci_fixup {
+	void (*hook)(void);
+};
+
+bool detect_pci(void);
diff --git a/tools/linker-tables/include/linux/printk.h b/tools/linker-tables/include/linux/printk.h
new file mode 100644
index 000000000000..dc137d3421e8
--- /dev/null
+++ b/tools/linker-tables/include/linux/printk.h
@@ -0,0 +1,26 @@
+#ifndef _SANDBOX_KERNEL_PRINTK
+#define _SANDBOX_KERNEL_PRINTK
+
+#ifdef __KERNEL__
+
+#include <stdio.h>
+
+#ifndef pr_fmt
+#define pr_fmt(fmt)	fmt
+#endif
+
+#ifndef pr_info
+#define pr_info(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
+#ifndef pr_err
+#define pr_err(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
+#ifndef pr_debug
+#define pr_debug(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* _SANDBOX_KERNEL_PRINTK */
diff --git a/tools/linker-tables/include/linux/ps_const.h b/tools/linker-tables/include/linux/ps_const.h
new file mode 100644
index 000000000000..5eab3a124e00
--- /dev/null
+++ b/tools/linker-tables/include/linux/ps_const.h
@@ -0,0 +1,46 @@
+#ifndef __PS_CONST
+#define __PS_CONST
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/tables.h>
+
+/* Helpers for partially static settings */
+
+enum ps_static_type {
+	SET_CONST_U8 = 0,
+	SET_CONST_U16,
+	SET_CONST_U32,
+};
+
+struct ps_set_const {
+	unsigned int *count;
+	enum ps_static_type type;
+	unsigned int (*func)(void);
+};
+
+DECLARE_LINKTABLE(struct ps_set_const, ps_set_const_table);
+
+#ifdef CONFIG_HAVE_ARCH_PS_CONST
+#include <asm/ps_const.h>
+#endif
+
+/*
+ * ps_ stands for "partially static", so we "partialloy static shift right"
+ * You can optimize this for your architecture.
+ *
+ * ps_shr(unsigned int in, unsigned char (*func)(void))
+ */
+#ifndef ps_shr
+#define ps_shr(_in, _func)						\
+({									\
+	static unsigned int _count;					\
+	static LINKTABLE_INIT_DATA(ps_set_const_table, 01)		\
+		__ps_shr##__func =					\
+		{ &_count, SET_CONST_U8, (_func) };			\
+									\
+	(_in) >> _count;						\
+})
+#endif /* ps_shr */
+
+#endif /* __PS_CONST */
diff --git a/tools/linker-tables/include/linux/sched.h b/tools/linker-tables/include/linux/sched.h
new file mode 100644
index 000000000000..0fe3526e88bf
--- /dev/null
+++ b/tools/linker-tables/include/linux/sched.h
@@ -0,0 +1,9 @@
+#ifndef _LINUX_SCHED_H
+#define _LINUX_SCHED_H
+
+#include <linux/ranges.h>
+
+DECLARE_SECTION_RANGE(sched_text);
+#define __sched		__LINUX_RANGE(.text, sched_text)
+
+#endif /* _LINUX_SCHED_H */
diff --git a/tools/linker-tables/include/linux/spinlock.h b/tools/linker-tables/include/linux/spinlock.h
new file mode 100644
index 000000000000..e62bc3bc5e6a
--- /dev/null
+++ b/tools/linker-tables/include/linux/spinlock.h
@@ -0,0 +1,13 @@
+#ifndef __LINUX_SPINLOCK_H
+#define __LINUX_SPINLOCK_H
+
+#include <pthread.h>
+
+#define spinlock_t pthread_spinlock_t
+
+void spin_lock_init(spinlock_t *lock);
+void spin_lock_destroy(spinlock_t *lock);
+void spin_lock(spinlock_t *lock);
+void spin_unlock(spinlock_t *lock);
+
+#endif /* __LINUX_SPINLOCK_H */
diff --git a/tools/linker-tables/include/linux/start_kernel.h b/tools/linker-tables/include/linux/start_kernel.h
new file mode 100644
index 000000000000..5c2cb9a5cb0c
--- /dev/null
+++ b/tools/linker-tables/include/linux/start_kernel.h
@@ -0,0 +1 @@
+int start_kernel(void);
diff --git a/tools/linker-tables/include/linux/types.h b/tools/linker-tables/include/linux/types.h
new file mode 100644
index 000000000000..3fc87b2c84e2
--- /dev/null
+++ b/tools/linker-tables/include/linux/types.h
@@ -0,0 +1,13 @@
+#ifndef __LINUX_USER_TYPES_H
+#define __LINUX_USER_TYPES_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+typedef unsigned char __u8;
+typedef unsigned short __u16;
+typedef unsigned int __u32;
+
+#endif /* __LINUX_USER_TYPES_H */
diff --git a/tools/linker-tables/include/linux/workqueue.h b/tools/linker-tables/include/linux/workqueue.h
new file mode 100644
index 000000000000..69e1c6de5051
--- /dev/null
+++ b/tools/linker-tables/include/linux/workqueue.h
@@ -0,0 +1,51 @@
+#ifndef _LINUX_WORKQUEUE_H
+#define _LINUX_WORKQUEUE_H
+
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <pthread.h>
+
+struct work {
+	bool ready;
+
+	pthread_t thread;
+	struct mutex mutex;
+	pthread_cond_t cond;
+
+	void *arg;
+	void *(*work_cb)(void *arg);
+};
+
+#define DECLARE_WORK(_w, _w_cb) \
+struct work _w = { \
+	.work_cb = _w_cb, \
+	.arg = NULL, \
+};
+
+extern void *run_work(void *arg);
+
+static inline void init_work(struct work *w)
+{
+	w->ready = false;
+
+	mutex_init(&w->mutex);
+	pthread_cond_init(&w->cond, NULL);
+
+	pthread_create(&w->thread, NULL, run_work, (void *) w);
+
+	while (1) {
+		mutex_lock(&w->mutex);
+		if (w->ready) {
+			pthread_mutex_unlock(&w->mutex.lock);
+			break;
+		}
+		mutex_unlock(&w->mutex);
+	}
+}
+
+void schedule_work(struct work *w);
+void cancel_work_sync(struct work *w);
+void init_work(struct work *w);
+
+#endif /* _LINUX_WORKQUEUE_H */
diff --git a/tools/linker-tables/include/xen/xen.h b/tools/linker-tables/include/xen/xen.h
new file mode 100644
index 000000000000..782c799a0064
--- /dev/null
+++ b/tools/linker-tables/include/xen/xen.h
@@ -0,0 +1,4 @@
+#include <linux/types.h>
+
+bool booting_xen(void);
+int startup_xen(void);
diff --git a/tools/linker-tables/kernel/locking/mutex.c b/tools/linker-tables/kernel/locking/mutex.c
new file mode 100644
index 000000000000..950e4a18461e
--- /dev/null
+++ b/tools/linker-tables/kernel/locking/mutex.c
@@ -0,0 +1,28 @@
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+
+DEFINE_SECTION_RANGE(sched_text, .text);
+
+void __sched mutex_init(struct mutex *lock)
+{
+	int r;
+
+	r = pthread_mutex_init(&lock->lock, NULL);
+	if (r)
+		BUG_ON(r);
+}
+
+void __sched mutex_destroy(struct mutex *lock)
+{
+	pthread_mutex_destroy(&lock->lock);
+}
+
+void __sched mutex_lock(struct mutex *lock)
+{
+	pthread_mutex_lock(&lock->lock);
+}
+
+void __sched mutex_unlock(struct mutex *lock)
+{
+	pthread_mutex_unlock(&lock->lock);
+}
diff --git a/tools/linker-tables/kernel/locking/spinlock.c b/tools/linker-tables/kernel/locking/spinlock.c
new file mode 100644
index 000000000000..5be2bc7cdece
--- /dev/null
+++ b/tools/linker-tables/kernel/locking/spinlock.c
@@ -0,0 +1,26 @@
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+
+void spin_lock_init(spinlock_t *lock)
+{
+	int r;
+
+	r = pthread_spin_init(lock, PTHREAD_PROCESS_SHARED);
+	if (r)
+		BUG_ON(r);
+}
+
+void spin_lock_destroy(spinlock_t *lock)
+{
+	pthread_spin_destroy(lock);
+}
+
+void spin_lock(spinlock_t *lock)
+{
+	pthread_spin_lock(lock);
+}
+
+void spin_unlock(spinlock_t *lock)
+{
+	pthread_spin_unlock(lock);
+}
diff --git a/tools/linker-tables/kernel/main.c b/tools/linker-tables/kernel/main.c
new file mode 100644
index 000000000000..ad7a19c038bf
--- /dev/null
+++ b/tools/linker-tables/kernel/main.c
@@ -0,0 +1,32 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/x86_init_fn.h>
+#include <asm/x86.h>
+
+DEFINE_LINKTABLE_INIT_DATA(initcall_t, init_calls);
+
+int do_one_initcall(initcall_t fn)
+{
+	int ret;
+
+	ret = fn();
+
+	return ret;
+}
+
+static void do_initcalls(void)
+{
+	initcall_t *fn;
+
+	 linktable_for_each(fn, init_calls)
+		 do_one_initcall(*fn);
+}
+
+void start_kernel(void)
+{
+	pr_info("Calling start_kernel()...\n");
+
+	setup_arch();
+	late_init();
+	do_initcalls();
+}
diff --git a/tools/linker-tables/kernel/workqueue.c b/tools/linker-tables/kernel/workqueue.c
new file mode 100644
index 000000000000..5ba73c7e7c8b
--- /dev/null
+++ b/tools/linker-tables/kernel/workqueue.c
@@ -0,0 +1,43 @@
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <linux/workqueue.h>
+#include <linux/kernel.h>
+
+void schedule_work(struct work *w)
+{
+	mutex_lock(&w->mutex);
+	pthread_cond_signal(&w->cond);
+	mutex_unlock(&w->mutex);
+}
+
+void cancel_work_sync(struct work *w)
+{
+	pthread_exit(NULL);
+}
+
+void *run_work(void *arg)
+{
+	struct work *w;
+	int r;
+
+	w = (struct work *) arg;
+
+	mutex_lock(&w->mutex);
+
+	while (true) {
+		if (!w->ready)
+			w->ready = true;
+		r = pthread_cond_wait(&w->cond, &w->mutex.lock);
+		if (r != 0) {
+			printf("(%s)\n", strerror(r));
+			BUG_ON(r);
+		}
+		w->work_cb(w->arg);
+	}
+
+	mutex_unlock(&w->mutex);
+
+	pthread_exit(NULL);
+}
diff --git a/tools/linker-tables/lib/string.c b/tools/linker-tables/lib/string.c
new file mode 100644
index 000000000000..95631c742f1d
--- /dev/null
+++ b/tools/linker-tables/lib/string.c
@@ -0,0 +1,26 @@
+/*
+ *  linux/lib/string.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  Licensed under GPLv2 - taken from linux-next next-20160803
+ */
+
+#include <linux/kernel.h>
+
+/**
+ * memset - Fill a region of memory with the given value
+ * @s: Pointer to the start of the area.
+ * @c: The byte to fill the area with
+ * @count: The size of the area.
+ *
+ * Do not use memset() to access IO space, use memset_io() instead.
+ */
+void *memset(void *s, int c, size_t count)
+{
+	char *xs = s;
+
+	while (count--)
+		*xs++ = c;
+	return s;
+}
diff --git a/tools/linker-tables/main.c b/tools/linker-tables/main.c
new file mode 100644
index 000000000000..c0b1f4c95112
--- /dev/null
+++ b/tools/linker-tables/main.c
@@ -0,0 +1,20 @@
+#include <linux/string.h>
+#include <xen/xen.h>
+#include <asm/x86.h>
+#include <asm/bootparam.h>
+
+struct boot_params boot_params __attribute__((aligned(16)));
+
+int main(int arg, char *argc[])
+{
+	memset(&boot_params, 0, sizeof(struct boot_params));
+
+	if (arg <= 1)
+		startup_64();
+	else {
+		boot_params.hdr.hardware_subarch = X86_SUBARCH_XEN;
+		startup_xen();
+	}
+
+	return 0;
+}
diff --git a/tools/linker-tables/pci-quirks.c b/tools/linker-tables/pci-quirks.c
new file mode 100644
index 000000000000..2cd1116dd0fc
--- /dev/null
+++ b/tools/linker-tables/pci-quirks.c
@@ -0,0 +1,13 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <linux/pci.h>
+
+DEFINE_LINKTABLE_RO(struct pci_fixup, pci_fixup_early);
+
+static void foo_fixup(void) {
+	pr_info("foo_fixup\n");
+};
+
+LINKTABLE_RO(pci_fixup_early, 50) quirk_foo = {
+	.hook = foo_fixup,
+};
diff --git a/tools/linker-tables/pci.c b/tools/linker-tables/pci.c
new file mode 100644
index 000000000000..7a822c11d9f0
--- /dev/null
+++ b/tools/linker-tables/pci.c
@@ -0,0 +1,29 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <asm/bootparam.h>
+#include <linux/pci.h>
+
+DECLARE_LINKTABLE(struct pci_fixup, pci_fixup_early);
+
+void early_init_pci(void) {
+
+	const struct pci_fixup *fixup;
+	unsigned int tbl_size = LINKTABLE_SIZE(pci_fixup_early);
+
+	pr_info("Initializing pci ...\n");
+
+	pr_info("PCI fixup size: %d\n", tbl_size);
+
+	sleep(1);
+	pr_info("Demo: Using linktable_for_each\n");
+	linktable_for_each(fixup, pci_fixup_early)
+		fixup->hook();
+
+	pr_info("Demo: Using linktable_run_all\n");
+	linktable_run_all(pci_fixup_early, hook,);
+
+	pr_info("Completed initializing pci !\n");
+}
+
+x86_init_early_all(early_init_pci);
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v3 6/6] tools: add userspace linker table sandbox
@ 2017-01-09 15:02           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 15:02 UTC (permalink / raw)
  To: hpa, acme, tglx, mingo, jpoimboe, bp, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Add a userspace sandbox to allow easy experimentation and
test extensions with linker tables, section ranges and the
new section core definitions.

The userspace sandbox tries to mimic the Linux kernel development
flow as much as possible, it however relies on and uses libc. Support
is currently only provided to x86_64.

Demo run:

cd tools/linker-tables
make clean; make;
./demo
Initializing x86 bare metal world
x86-init: Number of init entries: 8
Initializing memory ...
Completed initializing memory !
Initializing pci ...
PCI fixup size: 1
Demo: Using LINKTABLE_FOR_EACH
foo_fixup
Demo: Using LINKTABLE_RUN_ALL
foo_fixup
Completed initializing pci !
Number of init entries: 1
Initializing kprobes ...
= OK: test_kprobe_0001 within range!
= OK: test_kprobe_0002 not in range as expected!
Completed initializing kprobes !
Initializing kasan ...
Early init for Kasan...
Completed initializing kasan !
Initializing beta ...
Completed initializing beta !
Initializing alpha ...
Completed initializing alpha !
Booting bare metal
Calling start_kernel()...
ACME: Initializing ...
ACME: Finished init ... !
Synthetics: synth_init_or(2) returns: 0xDEADBEEF
Synthetics: ps_shr(0xDEADBEEF, get_demo_shr) returns: 0x0000DEAD

v6: rename table macros as suggested by Andy Shevchenko

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clashes with compiler generated
  sections.

o moves tools/include/linux/printk.h to tools
  linker-table/include/linux/printk.h -- we cannot generalize this
  just yet, more work is needed in terms of providing a namespace for
  headers for types of ports of kernel functionality to userspace.

o Adjust code according to the latest discussions for the linker
  tables API (section name macros are now gone).

o Give CONFIG_HAVE_ARCH_PS_CONST for x86 another good 'ol college try,
  still fails, but this is just a demo anyway. We can amend and fix
  make this more optimized for x86 later. Thanks Boris!

v4: this patch is new in this series -- added to the kenrel as
    suggested by Boris, as otherwise it'd be really hard to keep
    an external userspace repository in sync.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/linker-tables.rst           |   4 +-
 MAINTAINERS                                        |   1 +
 include/linux/tables.h                             |   5 +-
 tools/Makefile                                     |   3 +-
 .../arch/x86/include/generated/asm/section-core.h  |   1 +
 tools/arch/x86/include/generated/ranges.h          |   1 +
 tools/arch/x86/include/generated/tables.h          |   1 +
 tools/include/asm-generic/ranges.h                 |  93 +++
 tools/include/asm-generic/section-core.h           | 348 +++++++++++
 tools/include/asm-generic/tables.h                 |  48 ++
 tools/include/linux/ranges.h                       | 183 ++++++
 tools/include/linux/sections.h                     |  87 +++
 tools/include/linux/string.h                       |   1 +
 tools/include/linux/tables.h                       | 684 +++++++++++++++++++++
 tools/linker-tables/.gitignore                     |   2 +
 tools/linker-tables/Makefile                       | 184 ++++++
 tools/linker-tables/README                         | 114 ++++
 tools/linker-tables/arch/x86/include/asm/asm.h     |  17 +
 tools/linker-tables/arch/x86/include/asm/boot.h    |   1 +
 .../linker-tables/arch/x86/include/asm/bootparam.h |  32 +
 tools/linker-tables/arch/x86/include/asm/kprobes.h |   7 +
 .../linker-tables/arch/x86/include/asm/ps_const.h  |  23 +
 tools/linker-tables/arch/x86/include/asm/ranges.h  |   6 +
 .../arch/x86/include/asm/section-core.h            |   1 +
 tools/linker-tables/arch/x86/include/asm/setup.h   |   6 +
 tools/linker-tables/arch/x86/include/asm/tables.h  |   6 +
 tools/linker-tables/arch/x86/include/asm/x86.h     |   4 +
 .../arch/x86/include/asm/x86_init_fn.h             | 169 +++++
 tools/linker-tables/arch/x86/kernel/alpha.c        |   9 +
 tools/linker-tables/arch/x86/kernel/alternative.c  |  31 +
 tools/linker-tables/arch/x86/kernel/beta.c         |   9 +
 tools/linker-tables/arch/x86/kernel/head64.c       |  58 ++
 tools/linker-tables/arch/x86/kernel/init.c         |  42 ++
 tools/linker-tables/arch/x86/kernel/kasan.c        |  10 +
 tools/linker-tables/arch/x86/kernel/kprobes.c      |  51 ++
 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S  | 277 +++++++++
 tools/linker-tables/arch/x86/mm/init.c             |  10 +
 tools/linker-tables/arch/x86/xen/init.c            |  13 +
 tools/linker-tables/drivers/acme.c                 |  32 +
 tools/linker-tables/drivers/synth/common.c         |  16 +
 tools/linker-tables/drivers/synth/common.h         |   2 +
 tools/linker-tables/drivers/synth/main.c           |  35 ++
 tools/linker-tables/drivers/synth/or.S             |  39 ++
 tools/linker-tables/drivers/synth/synth.h          |   2 +
 tools/linker-tables/drivers/xen-driver.c           |  11 +
 .../include/asm-generic/arch_init_fn.h             |  50 ++
 tools/linker-tables/include/asm-generic/kprobes.h  |  26 +
 tools/linker-tables/include/linux/bitops.h         |   6 +
 tools/linker-tables/include/linux/init.h           |  40 ++
 tools/linker-tables/include/linux/kasan.h          |   5 +
 tools/linker-tables/include/linux/kernel.h         |   2 +
 tools/linker-tables/include/linux/kprobes.h        |  11 +
 tools/linker-tables/include/linux/module.h         |  14 +
 tools/linker-tables/include/linux/mutex.h          |  17 +
 tools/linker-tables/include/linux/pci.h            |   7 +
 tools/linker-tables/include/linux/printk.h         |  26 +
 tools/linker-tables/include/linux/ps_const.h       |  46 ++
 tools/linker-tables/include/linux/sched.h          |   9 +
 tools/linker-tables/include/linux/spinlock.h       |  13 +
 tools/linker-tables/include/linux/start_kernel.h   |   1 +
 tools/linker-tables/include/linux/types.h          |  13 +
 tools/linker-tables/include/linux/workqueue.h      |  51 ++
 tools/linker-tables/include/xen/xen.h              |   4 +
 tools/linker-tables/kernel/locking/mutex.c         |  28 +
 tools/linker-tables/kernel/locking/spinlock.c      |  26 +
 tools/linker-tables/kernel/main.c                  |  32 +
 tools/linker-tables/kernel/workqueue.c             |  43 ++
 tools/linker-tables/lib/string.c                   |  26 +
 tools/linker-tables/main.c                         |  20 +
 tools/linker-tables/pci-quirks.c                   |  13 +
 tools/linker-tables/pci.c                          |  29 +
 71 files changed, 3232 insertions(+), 5 deletions(-)
 create mode 100644 tools/arch/x86/include/generated/asm/section-core.h
 create mode 100644 tools/arch/x86/include/generated/ranges.h
 create mode 100644 tools/arch/x86/include/generated/tables.h
 create mode 100644 tools/include/asm-generic/ranges.h
 create mode 100644 tools/include/asm-generic/section-core.h
 create mode 100644 tools/include/asm-generic/tables.h
 create mode 100644 tools/include/linux/ranges.h
 create mode 100644 tools/include/linux/sections.h
 create mode 100644 tools/include/linux/tables.h
 create mode 100644 tools/linker-tables/.gitignore
 create mode 100644 tools/linker-tables/Makefile
 create mode 100644 tools/linker-tables/README
 create mode 100644 tools/linker-tables/arch/x86/include/asm/asm.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/boot.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/bootparam.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/kprobes.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ps_const.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ranges.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/section-core.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/setup.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/tables.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
 create mode 100644 tools/linker-tables/arch/x86/kernel/alpha.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/alternative.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/beta.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/head64.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/init.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kasan.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kprobes.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
 create mode 100644 tools/linker-tables/arch/x86/mm/init.c
 create mode 100644 tools/linker-tables/arch/x86/xen/init.c
 create mode 100644 tools/linker-tables/drivers/acme.c
 create mode 100644 tools/linker-tables/drivers/synth/common.c
 create mode 100644 tools/linker-tables/drivers/synth/common.h
 create mode 100644 tools/linker-tables/drivers/synth/main.c
 create mode 100644 tools/linker-tables/drivers/synth/or.S
 create mode 100644 tools/linker-tables/drivers/synth/synth.h
 create mode 100644 tools/linker-tables/drivers/xen-driver.c
 create mode 100644 tools/linker-tables/include/asm-generic/arch_init_fn.h
 create mode 100644 tools/linker-tables/include/asm-generic/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/bitops.h
 create mode 100644 tools/linker-tables/include/linux/init.h
 create mode 100644 tools/linker-tables/include/linux/kasan.h
 create mode 100644 tools/linker-tables/include/linux/kernel.h
 create mode 100644 tools/linker-tables/include/linux/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/module.h
 create mode 100644 tools/linker-tables/include/linux/mutex.h
 create mode 100644 tools/linker-tables/include/linux/pci.h
 create mode 100644 tools/linker-tables/include/linux/printk.h
 create mode 100644 tools/linker-tables/include/linux/ps_const.h
 create mode 100644 tools/linker-tables/include/linux/sched.h
 create mode 100644 tools/linker-tables/include/linux/spinlock.h
 create mode 100644 tools/linker-tables/include/linux/start_kernel.h
 create mode 100644 tools/linker-tables/include/linux/types.h
 create mode 100644 tools/linker-tables/include/linux/workqueue.h
 create mode 100644 tools/linker-tables/include/xen/xen.h
 create mode 100644 tools/linker-tables/kernel/locking/mutex.c
 create mode 100644 tools/linker-tables/kernel/locking/spinlock.c
 create mode 100644 tools/linker-tables/kernel/main.c
 create mode 100644 tools/linker-tables/kernel/workqueue.c
 create mode 100644 tools/linker-tables/lib/string.c
 create mode 100644 tools/linker-tables/main.c
 create mode 100644 tools/linker-tables/pci-quirks.c
 create mode 100644 tools/linker-tables/pci.c

diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index bc2d9f46cde6..2f2bb1fc0798 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -11,11 +11,11 @@ About Linker tables
 .. kernel-doc:: include/linux/tables.h
    :doc: Introduction
 
-Linker table provenance
+Linker table provenance and userspace testing
 ---------------------------------------------
 
 .. kernel-doc:: include/linux/tables.h
-   :doc: Linker table provenance
+   :doc: Linker table provenance and userspace testing
 
 Benefits of using Linker tables
 ===============diff --git a/MAINTAINERS b/MAINTAINERS
index bbf519da3a78..30105cd3edaf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5415,6 +5415,7 @@ L:	linux-kernel@vger.kernel.org
 S:	Supported
 F:	include/asm-generic/tables.h
 F:	include/linux/tables.h
+F:	tools/linker-tables/
 F:	Documentation/sections/linker-tables.rst
 
 GENERIC PHY FRAMEWORK
diff --git a/include/linux/tables.h b/include/linux/tables.h
index 70a41edfa127..64b864949a02 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -35,12 +35,13 @@
  */
 
 /**
- * DOC: Linker table provenance
+ * DOC: Linker table provenance and userspace testing
  *
  * 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].
+ * userspace linker-table tree [1]. Linux has a similar userspace application
+ * in tools/linker-tables/ to help more easily test adding new extensions.
  *
  * Contrary to iPXE's solution which strives to force compilation of
  * everything using linker tables, Linux's solution allows for developers to be
diff --git a/tools/Makefile b/tools/Makefile
index 00caacd3ed92..ecb2e651c930 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -19,6 +19,7 @@ help:
 	@echo '  kvm_stat               - top-like utility for displaying kvm statistics'
 	@echo '  leds                   - LEDs  tools'
 	@echo '  lguest                 - a minimal 32-bit x86 hypervisor'
+	@echo '  linker-tables		- userspace liker table sandbox and related tools'
 	@echo '  net                    - misc networking tools'
 	@echo '  perf                   - Linux performance measurement and analysis tool'
 	@echo '  selftests              - various kernel selftests'
@@ -86,7 +87,7 @@ tmon: FORCE
 freefall: FORCE
 	$(call descend,laptop/$@)
 
-all: acpi cgroup cpupower gpio hv firewire lguest \
+all: acpi cgroup cpupower gpio hv firewire lguest linker-tables \
 		perf selftests turbostat usb \
 		virtio vm net x86_energy_perf_policy \
 		tmon freefall objtool
diff --git a/tools/arch/x86/include/generated/asm/section-core.h b/tools/arch/x86/include/generated/asm/section-core.h
new file mode 100644
index 000000000000..06be2b1c424f
--- /dev/null
+++ b/tools/arch/x86/include/generated/asm/section-core.h
@@ -0,0 +1 @@
+#include <asm-generic/section-core.h>
diff --git a/tools/arch/x86/include/generated/ranges.h b/tools/arch/x86/include/generated/ranges.h
new file mode 100644
index 000000000000..dac1a9a11367
--- /dev/null
+++ b/tools/arch/x86/include/generated/ranges.h
@@ -0,0 +1 @@
+#include <asm-generic/ranges.h>
diff --git a/tools/arch/x86/include/generated/tables.h b/tools/arch/x86/include/generated/tables.h
new file mode 100644
index 000000000000..d437818275c5
--- /dev/null
+++ b/tools/arch/x86/include/generated/tables.h
@@ -0,0 +1 @@
+#include <asm-generic/tables.h>
diff --git a/tools/include/asm-generic/ranges.h b/tools/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..75c196864f45
--- /dev/null
+++ b/tools/include/asm-generic/ranges.h
@@ -0,0 +1,93 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  any, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       any, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   any, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(#section "..rng.name.any")))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using
+ * 	binutils SORT(), the number is sorted as a string, as such be
+ * 	sure to fill with zeroes any empty digits. For instance if you are
+ * 	using 3 levels of digits for order levels, use 001 for the first entry,
+ * 	0002 for the second, 999 for the last entry. You can use however many
+ * 	digits you need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(#section "..rng.name." #level)))
+
+#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/tools/include/asm-generic/section-core.h b/tools/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..65fb076765f8
--- /dev/null
+++ b/tools/include/asm-generic/section-core.h
@@ -0,0 +1,348 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Linux ELF program specific sections
+ *
+ * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and
+ * definition of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
+ * sections. This chaper is dedicated to documenting Linux program specific
+ * sections and helpers available to make use of these easier to implement and
+ * use.
+ *
+ * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
+ */
+
+/**
+ * DOC: Linux linker script
+ *
+ * Linux uses a custom linker script to build the vmlinux binary, it uses it to
+ * strategically place and define Linux ELF sections.  Each architecture needs
+ * to implement its own linker script, it is expected to reside in
+ * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
+ * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
+ * as well as some helpers documented in this chapter.
+ *
+ * In assembly it is common practice to use dots (``.``) in labels to avoid
+ * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
+ * name but not a C symbol. Historically then, two dots are used (``..``)
+ * have been used in linker scripts when adding program specific sections
+ * when there are concerns to avoid clashes with compiler generated sections.
+ */
+
+/**
+ * DOC: Memory protection
+ *
+ * Linux allows architectures which support memory protection features to
+ * take advantage of them by letting architectures define and enable
+ * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.
+ * mark_rodata_ro() can be used for instance to mark specific sections as
+ * read-only or non-executable.
+ *
+ * Linux typically follows a convention to have the .rodata ELF section follow
+ * after the .text ELF section, it does this to help architectures which
+ * support memory protection to mark both .text and .rodata as read-only in
+ * one shot.
+ *
+ * For more details refer to mark_rodata_ro().
+ */
+
+/**
+ * DOC: .rodata
+ *
+ * ELF section used for data which must be protected from write access.
+ */
+
+/**
+ * DOC: .text
+ *
+ * ELF section name used for code (functions) used during regular
+ * kernel run time.
+ */
+
+/**
+ * DOC: .data
+ *
+ * ELF section used for read-write data.
+ */
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: .init.text
+ *
+ * ELF section for code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+
+/**
+ * DOC: .init.data
+ *
+ * ELF section used for data structures used only during boot or driver
+ * initialization.
+ */
+
+/**
+ * DOC: .init.rodata
+ *
+ * ELF section used for read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+
+/**
+ * DOC: .initcall
+ *
+ * ELF section used for subsystem init calls. There are init levels
+ * representing different functionality in the kernel. For more details
+ * refer to __define_initcall().
+ */
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: .exit.text
+ *
+ * ELF section used to for code (functions) used only during module unload.
+ */
+
+/**
+ * DOC: .exit.data
+ *
+ * ELF section used to for data structures used only during module
+ * unload.
+ */
+
+/**
+ * DOC: .exitcall.exit
+ *
+ * ELF section used for exit routines, order is important and maintained by
+ * link order.
+ */
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: .ref.text
+ *
+ * ELF section used to annotate code (functions) which has been vetteed as
+ * valid for its reference or use of other code (functions) or data structures
+ * which are part of the init sections.
+ */
+
+/**
+ * DOC: .ref.data
+ *
+ * ELF section used for data structures which have been vetteed for its
+ * reference or use of other code (functions) or data structures part of the
+ * init sections.
+ */
+
+/**
+ * DOC: .ref.rodata
+ *
+ * ELF section used to annotate const code (functions) const data structures
+ * which has been vetteed for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections alpha numerically. Linux has historically used 'SORT()' in
+ * ``include/asm-generic/vmlinux.lds.h``, its a well established practice. If
+ * 'SORT()' is used on a section one can provide ordering using a postfix on
+ * each section entry added. For instance if a linker script uses::
+ *
+ *    SORT(.foo.*)
+ *
+ * one can then add entries with explicit ordering using numeric postfixes for
+ * each entry, we refer to these as 'order levels'. Since 'SORT()' sorts alpha
+ * numerically a specific series set of digits must be agreed a-priori which
+ * would give also an idea of the max expected number of entries added to a
+ * section. For instance, if you expect a maximum of 999 entries you can use
+ * 3 digits for a section order level. If you wanted an entry to be ordered
+ * first you could use the postfix '000', if you wanted an entry to follow this
+ * you could use '001', and so on. We could for instance have::
+ *
+ *    .foo.000
+ *    .foo.001
+ *    .foo.002
+ *
+ * Often times one may want the option to specify no order is required for
+ * certain elements added to a section which does use 'SORT()' on the linker
+ * script. You can use any arbitrary string value to to specify no order is
+ * used, so long as its used consistantly. For instance, one possibility is to
+ * use the 'any' postfix.  All entries on the section would then have no
+ * specific ordering::
+ *
+ *    .foo.any
+ *    .foo.any
+ *    .foo.any
+ *
+ * To help establish a convention we reserve the special name 'any' for this
+ * purpose. Developers can use and expect the 'any' postfix string on sections
+ * as a helper to annotate section ordering at link time is not relevant
+ * for entries on a section.
+ */
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section..___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section..__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifndef LINKER_SCRIPT
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align\x16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/tools/include/asm-generic/tables.h b/tools/include/asm-generic/tables.h
new file mode 100644
index 000000000000..16ef40d145fb
--- /dev/null
+++ b/tools/include/asm-generic/tables.h
@@ -0,0 +1,48 @@
+#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..tbl.name.level
+
+/* Some toolchains are buggy, let them override */
+#ifndef SECTION_TBL_RO
+# define SECTION_TBL_RO	.rodata
+#endif
+
+#define SECTION_TBL_RO_STR __stringify(SECTION_TBL_RO)
+
+#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, 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, any, flags)
+#endif
+
+#endif /* _ASM_GENERIC_TABLES_H_ */
diff --git a/tools/include/linux/ranges.h b/tools/include/linux/ranges.h
new file mode 100644
index 000000000000..1e64674f6d7d
--- /dev/null
+++ b/tools/include/linux/ranges.h
@@ -0,0 +1,183 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * SECTION_RANGE_START - get address of start of section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the start address of the section range.
+ * This should give you the address of the first entry.
+ *
+ */
+#define SECTION_RANGE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * SECTION_RANGE_END - get address of end of the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define SECTION_RANGE_END(name)		LINUX_SECTION_END(name)
+
+/**
+ * SECTION_RANGE_SIZE - get number of entries in the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the number of entries in the section range.
+ * Example usage:
+ *
+ *   unsigned int num_ents = LINKTABLE_SIZE(some_fns);
+ */
+#define SECTION_RANGE_SIZE(name)					\
+	((SECTION_RANGE_END(name)) - (SECTION_RANGE_START(name)))
+
+/**
+ * SECTION_RANGE_EMPTY - check if section range has no entries
+ *
+ * @name: name of the section range
+ *
+ * Returns true if the section range is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(some_fns);
+ */
+#define SECTION_RANGE_EMPTY(name)	(SECTION_RANGE_SIZE(name) = 0)
+
+/**
+ * SECTION_RANGE_ADDR_WITHIN - returns true if address is in the section range
+ *
+ * @name: name of the section range
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_RANGE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) SECTION_RANGE_START(name) &&		\
+          addr < (unsigned long) SECTION_RANGE_END(name))
+
+/**
+ * SECTION_RANGE_ALIGNMENT - get the alignment of the section range
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the section range.
+ */
+#define SECTION_RANGE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.")))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.~")))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) SECTION_RANGE_START(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) SECTION_RANGE_END(name)[0] = {}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
diff --git a/tools/include/linux/sections.h b/tools/include/linux/sections.h
new file mode 100644
index 000000000000..6771c727bcd1
--- /dev/null
+++ b/tools/include/linux/sections.h
@@ -0,0 +1,87 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_CORE(section, core, name, level)			\
+	#section ".." #core "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
diff --git a/tools/include/linux/string.h b/tools/include/linux/string.h
index f436d2420a18..a6b12564bbd9 100644
--- a/tools/include/linux/string.h
+++ b/tools/include/linux/string.h
@@ -3,6 +3,7 @@
 
 
 #include <linux/types.h>	/* for size_t */
+#include <string.h>
 
 void *memdup(const void *src, size_t len);
 
diff --git a/tools/include/linux/tables.h b/tools/include/linux/tables.h
new file mode 100644
index 000000000000..64b864949a02
--- /dev/null
+++ b/tools/include/linux/tables.h
@@ -0,0 +1,684 @@
+#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 and userspace testing
+ *
+ * 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]. Linux has a similar userspace application
+ * in tools/linker-tables/ to help more easily test adding new extensions.
+ *
+ * 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(.foo..tbl.*))
+ *
+ * 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: The code bit-rot problem
+ *
+ * Linux provides a rich array of features, enabling each feature
+ * however increases the size of the kernel and there are many
+ * features which users often want disabled. The traditional
+ * solution to this problem is for each feature to have its own
+ * Kconfig symbol, followed by a series of #ifdef statements
+ * in C code and header files, allowing the feature to be compiled
+ * only when desirable. As the variability of Linux increases build
+ * tests can and are often done with random kernel configurations,
+ * allyesconfig, and allmodconfig to help find code issues. This
+ * however doesn't catch all errors and as a consequence code that
+ * is typically not enabled often can suffer from bit-rot over time.
+ */
+
+/**
+ * DOC: The build-all selective-link philosophy
+ *
+ * A code architecture philosophy to help avoid code bit-rot consists
+ * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
+ * by instead having each feature implemented it its own C file, and force
+ * compilation for all features. Only features that are enabled get linked in,
+ * the forced compilation therefore has no size impact on the final result of
+ * the kernel. The practice of having each feature implemented in its own C
+ * file is already prevalent in many subsystems, however #ifdefs are still
+ * typically required during feature initialization. For instance in::
+ *
+ *	#ifdef CONFIG_FOO
+ *	foo_init();
+ *	#endif
+ *
+ * We cannot remove the #ifdef and leave foo_init() as we'd either
+ * need to always enable the feature or add a respective #ifdef in a
+ * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem with linker tables
+ *
+ * Linker tables can be used to further help avoid the code bit-rot problem
+ * when embracing the 'build-all selective-link philosophy' by lifting the
+ * requirement to use of #ifdefs during initialization. With linker tables
+ * initialization sequences can be aggregated into a custom ELF section at
+ * link time, during run time the table can be iterated over and each init
+ * sequence enabled can be called. A feature's init routine is only added to a
+ * table when its respective Kconfig symbols has been enabled and therefore
+ * linked in. Linker tables enable subsystems to completely do away with
+ * #ifdefs if one is comfortable in accepting all subsystem's feature's
+ * structural size implications.
+ *
+ * To further help with this the Linux build system supports two special
+ * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
+ * follow the 'build-all selective-link philosophy' can use these targets for a
+ * feature's kconfig symbol. Using these targets will always require
+ * compilation of the kconfig's objects if the kconfig symbol's dependencies
+ * are met but only link the objects into the kernel, and therefore enable the
+ * feature, if and only if the kconfig symbol has been enabled.
+ *
+ * Not all users or build systems may want to opt-in to compile all objects
+ * following the 'build-all selective-link philosophy', as such the targets
+ * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
+ * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
+ * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
+ * ``obj-y`` and ``lib-y`` respectively.
+ *
+ * Example use::
+ *
+ * 	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+ */
+
+/**
+ * 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_START - get address of start of linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the start address of the linker table.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINKTABLE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * LINKTABLE_END - get address of end of the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define LINKTABLE_END(name)	LINUX_SECTION_END(name)
+
+/**
+ * LINKTABLE_SIZE - get number of entries in the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the number of entries in the linker table.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINKTABLE_SIZE(frobnicator_fns);
+ */
+#define LINKTABLE_SIZE(name)					\
+	((LINKTABLE_END(name)) - (LINKTABLE_START(name)))
+
+/**
+ * LINKTABLE_EMPTY - check if linker table has no entries
+ *
+ * @name: name of linker table
+ *
+ * Returns true if the linker table is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(frobnicator_fns);
+ */
+#define LINKTABLE_EMPTY(name)	(LINKTABLE_SIZE(name) = 0)
+
+/**
+ * LINKTABLE_ADDR_WITHIN - returns true if address is in the linker table
+ *
+ * @name: name of the linker table
+ * @addr: address to query for
+ *
+ * Returns true if the address is part of the linker table.
+ */
+#define LINKTABLE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) LINKTABLE_START(name) &&		\
+          addr < (unsigned long) LINKTABLE_END(name))
+
+/**
+ * LINKTABLE_ALIGNMENT - get the alignment of the linker table
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the linker table.
+ */
+#define LINKTABLE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * 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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_TEXT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE_RO(name, ~) LINKTABLE_END(name)[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_RO(type, name);				\
+	LINKTABLE_INIT_WEAK(name,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT_DATA(name, ~) LINKTABLE_END(name)[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 = LINKTABLE_START(tbl);				\
+	     pointer < LINKTABLE_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 < LINKTABLE_SIZE(tbl); i++)			\
+		(LINKTABLE_START(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 < LINKTABLE_SIZE(tbl); i++)		\
+		err = (LINKTABLE_START(tbl)[i]).func (args);		\
+	err;								\
+})
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_LINKER_TABLES_H */
diff --git a/tools/linker-tables/.gitignore b/tools/linker-tables/.gitignore
new file mode 100644
index 000000000000..8275b0c55385
--- /dev/null
+++ b/tools/linker-tables/.gitignore
@@ -0,0 +1,2 @@
+arch/x86/kernel/vmlinux.lds
+demo
diff --git a/tools/linker-tables/Makefile b/tools/linker-tables/Makefile
new file mode 100644
index 000000000000..9d4e6fb0d176
--- /dev/null
+++ b/tools/linker-tables/Makefile
@@ -0,0 +1,184 @@
+include ../scripts/Makefile.include
+
+all:
+
+include ../scripts/utilities.mak
+
+MAKEFLAGS += --no-print-directory
+
+unexport LC_ALL
+LC_COLLATE=C
+LC_NUMERIC=C
+export LC_COLLATE LC_NUMERIC
+
+ifeq ($(srctree),)
+	srctree := $(patsubst %/,%,$(dir $(shell pwd)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Determined 'srctree' to be $(srctree))
+endif
+
+ifneq ($(objtree),)
+#$(info Determined 'objtree' to be $(objtree))
+endif
+
+ifneq ($(OUTPUT),)
+#$(info Determined 'OUTPUT' to be $(OUTPUT))
+# Adding $(OUTPUT) as a directory to look for source files,
+# because use generated output files as sources dependency
+# for flex/bison parsers.
+VPATH += $(OUTPUT)
+export VPATH
+endif
+
+export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK
+include $(srctree)/tools/build/Makefile.include
+
+ifeq ($(V),1)
+	Q+	NQ=@true
+else
+	Q=@
+	NQ=@echo
+endif
+
+MAKEFLAGS += -r
+
+define allow-override
+  $(if $(or $(findstring environment,$(origin $(1))),\
+            $(findstring command line,$(origin $(1)))),,\
+    $(eval $(1) = $(2)))
+endef
+
+# Allow setting CC and AR and LD, or setting CROSS_COMPILE as a prefix.
+$(call allow-override,CC,$(CROSS_COMPILE)gcc)
+$(call allow-override,AR,$(CROSS_COMPILE)ar)
+$(call allow-override,LD,$(CROSS_COMPILE)ld)
+
+LD += $(EXTRA_LDFLAGS)
+
+include $(srctree)/tools/scripts/Makefile.arch
+
+# Refer to README to learn how to support your architecture
+SUPPORTED_ARCHS = x86
+
+ifeq ($(filter $(ARCH),$(SUPPORTED_ARCHS)),)
+$(error Unsupported arch: $(ARCH))
+endif
+
+CFLAGS += -O2 -g
+CFLAGS += -std=gnu99 -Wall -Werror
+CFLAGS += -lpthread
+CFLAGS += -DCONFIG_KPROBES
+
+# We confine the includes used below to those we know are safe
+# for this type of hack.
+CFLAGS += -D__KERNEL__
+
+# CFLAGS += -DCONFIG_HAVE_ARCH_PS_CONST
+INCLUDES = \
+	   -I include/ \
+	   -I arch/$(ARCH)/include/ \
+	   -I ../include/ \
+	   -I ../arch/$(ARCH)/include/ \
+	   -I ../arch/$(ARCH)/include/generated/
+
+CFLAGS += $(INCLUDES)
+CFLAGS +=-Wl,-Tarch/$(ARCH)/kernel/vmlinux.lds
+
+HEADERS = \
+	  ../../include/asm-generic/section-core.h \
+	  ../../include/asm-generic/ranges.h \
+	  ../../include/asm-generic/tables.h \
+	  ../../include/linux/sections.h \
+	  ../../include/linux/ranges.h \
+	  ../../include/linux/tables.h
+
+__check_headers: $(HEADERS)
+	@$(foreach h, $(HEADERS), \
+		(test -f $(h) && ( \
+			(diff -B $(subst ../,../,$(h)) $(h) >/dev/null) \
+			|| echo "Warning: $(subst ../../,tools/,$(h)) differs from kernel" >&2 ) || true);)
+
+$(OUTPUT)arch/$(ARCH)/kernel/vmlinux.lds: arch/$(ARCH)/kernel/vmlinux.lds.S
+	$(NQ) '  LD  ' $@
+	$(Q)$(CC) $(CFLAGS) $(INCLUDES) -E -P \
+		-D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
+
+# Note, we use obj-y as a convenience factor, the cmd build
+# stuff doesn't allow this magic, it resolves our depds but
+# we still need to provide a series of targets for our objects.
+# We stick to the convenient shorthand we're used to in the
+# kernel. The final object resolution build stuff is handled
+# by tool_target_obj and its caller below. This also enables
+# OUTPUT=foo-path support so you can build externally.
+obj-y += \
+	arch/$(ARCH)/kernel/head64.o \
+	arch/$(ARCH)/mm/init.o \
+	kernel/locking/mutex.o \
+	kernel/locking/spinlock.o \
+	kernel/workqueue.o \
+	kernel/main.o \
+	pci.o \
+	lib/string.o \
+	pci-quirks.o \
+	drivers/acme.o \
+	drivers/synth/main.o \
+	drivers/synth/common.o \
+	drivers/synth/or.s \
+	main.o
+
+ifeq ($(ARCH),x86)
+obj-y += \
+	arch/$(ARCH)/kernel/alternative.o \
+	arch/$(ARCH)/kernel/init.o \
+	arch/$(ARCH)/kernel/kprobes.o \
+	arch/$(ARCH)/kernel/kasan.o \
+	arch/$(ARCH)/kernel/beta.o \
+	arch/$(ARCH)/kernel/alpha.o \
+	arch/$(ARCH)/xen/init.o	\
+	drivers/xen-driver.o
+endif
+
+obj-y-out = $(patsubst %,$(OUTPUT)%,$(obj-y))
+
+__build-dir = $(subst $(OUTPUT),,$(dir $1))
+build-dir   = $(if $(__build-dir),$(__build-dir),.)
+
+build := -f $(srctree)/tools/build/Makefile.build dir=$(build-dir)
+
+define tool_target_obj
+$(1): $(subst .s,.S,$(subst .o,.c,$(patsubst $(OUTPUT)%,%,$(1))))
+	$(Q)$(MAKE) $(build) obj=$(1)
+endef
+
+$(foreach tool_obj, $(obj-y-out), \
+	$(eval $(call tool_target_obj, $(tool_obj))))
+
+$(OUTPUT)demo: $(obj-y-out)
+	$(NQ) '  CC  ' $@
+	$(Q)$(CC) $(obj-y-out) -o $@ $(CPPFLAGS) $(CFLAGS)
+
+CHECK_HEADERS := __check_headers
+PHONY += $(CHECK_HEADERS)
+
+CMD_TARGETS = $(OUTPUT)arch/$(ARCH)/kernel/vmlinux.lds $(OUTPUT)demo
+TARGETS = $(CMD_TARGETS)
+
+all: $(CHECK_HEADERS) all_cmd
+
+all_cmd: $(CMD_TARGETS)
+
+ifeq ($(OUTPUT),)
+clean_dir = ./
+else
+clean_dir = $(OUTPUT)
+endif
+
+clean::
+	$(NQ)  '  CLEAN deps'
+	$(Q)find $(clean_dir) -name \*.o \
+		-o -name \*.s \
+		-o -name \*.o.d \
+		-o -name \*.o.cmd | xargs rm -f
+	$(NQ)  '  CLEAN targets'
+	$(Q)$(foreach f, $(CMD_TARGETS), rm -f $(f);)
diff --git a/tools/linker-tables/README b/tools/linker-tables/README
new file mode 100644
index 000000000000..729241f9e4c4
--- /dev/null
+++ b/tools/linker-tables/README
@@ -0,0 +1,114 @@
+Linux linker table userspace sandbox
+==================
+
+This is a userspace sandbox to allow easy experimentation and
+test extensions with linker tables. It tries to mimic the Linux
+kernel development flow as much as possible, it however relies
+on and uses libc and is nothing but a simple stupid userspace
+application demo.
+
+You can use the sandbox to modify the kernel's linker table
+solution or add use it in creative ways without having to run
+qemu with a real kernel or user mode linux. You can simply try
+to extend this sandbox as you would for a regular userspace
+application.
+
+History
+===+
+This was hacked on first in an external repository, that tree has
+the full set of history of how this work came about. Refer to that
+tree for more details if you are interested in the logic used for
+a lot of decisions made for linker tables:
+
+https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linker-tables.git/
+
+This tree is discontinued now in favor of an upstream solution which
+is kept in sync with the kernel.
+
+Compile
+===+
+Run:
+	make
+
+Clean:
+	make clean
+
+If you need to get object files outside of the source tree:
+
+	make OUTPUT=/tmp/path/
+	make OUTPUT=/tmp/path/ clean
+
+Supported architectures
+===========+
+x86_64
+
+Currently only x86_64 is supported for the demo. It should be
+relatively easy to add more. To add a new architecture you need
+a toolchain available with libc. You then need to generate a
+respective base template custom linker script for userspace
+as is provided on x86 in arch/x86/kernel/vmlinux.lds.S.
+
+A respective architecture tools/arch/$(ARCH)/include/* file for
+each section-core.h, ranges.h, tables.h will need to be provided
+as well. If your architecture's file is generated copy the generated
+file over.
+
+x86 Simulated boots
+=========+
+This programs simulates boot on both bare metal and with the
+Xen PV entry on x86.
+
+Emulate bare metal boot:
+
+./demo
+
+Emulate Xen boot (x86):
+
+./demo -x
+
+Testing new features
+==========
+
+A copy of each kernel header file is maintained in tools/include/,
+as well as a respective generated asm file for each sandbox supported
+architecture. This sandbox has a built in checker for when these files
+get out of sync.
+
+If testing new extensions on the files:
+
+  o section-core
+  o ranges.h
+  o tables.h
+
+You'll want to copy them into tools as well. If you are working on
+using these files you can work within the current directory's namespace,
+including its own set of header files, so tools/linker-tables/include/ and
+each respective tools/linker-tables/arch/$(ARCH)/include/asm/.
+
+Features evaluation
+=========+
+This lists features currently being evaluated in the sandbox, not yet
+present upstream. These make use of the existing set of header files
+without modification.
+
+ o Demo use of initialization on for x86, refer to arch/x86/kernel/init.c
+
+ o Demo use of porting the kernel's init call levels to linker tables, refer
+   to the init_calls linker table use on kernel/main.c
+
+ o Demo use of an asm-generic architecture init family, which could potentially
+   be used to help share initialization sequences on simple architectures.
+   Refer to include/asm-generic/arch_init_fn.h
+
+ o Building synthetic routines with the option to provide enhancements
+   per architecture in asm, refer to drivers/synth/or.S and its use on
+   synth_init_or().
+
+ o User of linker tables for alternatives with consts - refer to
+   use of the ps_set_const_table linker table and its use in
+   arch/x86/kernel/alternative.c
diff --git a/tools/linker-tables/arch/x86/include/asm/asm.h b/tools/linker-tables/arch/x86/include/asm/asm.h
new file mode 100644
index 000000000000..155a52920dfb
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/asm.h
@@ -0,0 +1,17 @@
+#ifndef _ASM_X86_ASM_H
+
+#ifdef __ASSEMBLY__
+# define __ASM_FORM(x)	x
+# define __ASM_FORM_RAW(x)     x
+# define __ASM_FORM_COMMA(x) x,
+#else
+# define __ASM_FORM(x)	" " #x " "
+# define __ASM_FORM_RAW(x)     #x
+# define __ASM_FORM_COMMA(x) " " #x ","
+#endif
+
+# define __ASM_SEL(a,b) __ASM_FORM(b)
+# define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(b)
+#define _ASM_PTR	__ASM_SEL(.long, .quad)
+
+#endif /* _ASM_X86_ASM_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/boot.h b/tools/linker-tables/arch/x86/include/asm/boot.h
new file mode 100644
index 000000000000..af91b94ad5a6
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/boot.h
@@ -0,0 +1 @@
+extern struct boot_params boot_params;
diff --git a/tools/linker-tables/arch/x86/include/asm/bootparam.h b/tools/linker-tables/arch/x86/include/asm/bootparam.h
new file mode 100644
index 000000000000..a7ef34216f7f
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/bootparam.h
@@ -0,0 +1,32 @@
+#ifndef __BOOTPARAM_H
+#define __BOOTPARAM_H
+
+#include <linux/types.h>
+
+struct setup_header {
+	__u32 hardware_subarch;
+} __attribute__((packed));
+
+struct boot_params {
+	struct setup_header hdr;
+} __attribute__((packed));
+
+enum {
+	X86_SUBARCH_PC = 0,
+	X86_SUBARCH_LGUEST,
+	X86_SUBARCH_XEN,
+	X86_SUBARCH_INTEL_MID,
+	X86_SUBARCH_CE4100,
+	X86_NR_SUBARCHS,
+};
+
+#define X86_SUBARCH_ALL_SUBARCHS 	\
+	(				\
+	BIT(X86_SUBARCH_PC) |		\
+	BIT(X86_SUBARCH_LGUEST) |	\
+	BIT(X86_SUBARCH_XEN) |		\
+	BIT(X86_SUBARCH_INTEL_MID) |	\
+	BIT(X86_SUBARCH_CE4100)		\
+	)
+
+#endif /* __BOOTPARAM_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/kprobes.h b/tools/linker-tables/arch/x86/include/asm/kprobes.h
new file mode 100644
index 000000000000..f702fc359efe
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/kprobes.h
@@ -0,0 +1,7 @@
+#ifndef _SANDBOX_ASM_X86_KPROBES_H
+#define _SANDBOX_ASM_X86_KPROBES_H
+
+/* This is all we need for the demo */
+#include <asm-generic/kprobes.h>
+
+#endif /* _SANDBOX_ASM_X86_KPROBES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/ps_const.h b/tools/linker-tables/arch/x86/include/asm/ps_const.h
new file mode 100644
index 000000000000..3847f03fca92
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/ps_const.h
@@ -0,0 +1,23 @@
+#ifndef __X86_PS_CONST
+#define __X86_PS_CONST
+
+#include <linux/stringify.h>
+#include <linux/tables.h>
+#include <asm/asm.h>
+
+#define ps_shr(in, _func)						\
+({									\
+	 __typeof__(in) _count;						\
+									\
+	asm volatile(							\
+		"shr %P[_in],%[_count]\n"				\
+		"1:\n"							\
+		push_section_tbl(.init.data, ps_set_const_table, 01,)	\
+		_ASM_PTR "1b-1, %P2, %P3\n"				\
+		".popsection\n"						\
+		: [_count] "=g" (_count)				\
+		: [_in] "i" (in), "i" (SET_CONST_U8), "i" (_func));	\
+	(_count);							\
+})
+
+#endif /* __X86_PS_CONST */
diff --git a/tools/linker-tables/arch/x86/include/asm/ranges.h b/tools/linker-tables/arch/x86/include/asm/ranges.h
new file mode 100644
index 000000000000..823789d2b010
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/ranges.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_RANGES_H
+#define _ASM_X86_RANGES_H
+
+#include <asm-generic/ranges.h>
+
+#endif  /* _ASM_X86_RANGES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/section-core.h b/tools/linker-tables/arch/x86/include/asm/section-core.h
new file mode 100644
index 000000000000..06be2b1c424f
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/section-core.h
@@ -0,0 +1 @@
+#include <asm-generic/section-core.h>
diff --git a/tools/linker-tables/arch/x86/include/asm/setup.h b/tools/linker-tables/arch/x86/include/asm/setup.h
new file mode 100644
index 000000000000..366c36bd2910
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/setup.h
@@ -0,0 +1,6 @@
+#ifndef __LINUX_X86_USER_SETUP_H
+#define __LINUX_X86_USER_SETUP_H
+
+/* I'm lazy */
+
+#endif /* __LINUX_X86_USER_SETUP_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/tables.h b/tools/linker-tables/arch/x86/include/asm/tables.h
new file mode 100644
index 000000000000..797df3407ee1
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/tables.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_TABLES_H
+#define _ASM_X86_TABLES_H
+
+#include <asm-generic/tables.h>
+
+#endif  /* _ASM_X86_RANGES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/x86.h b/tools/linker-tables/arch/x86/include/asm/x86.h
new file mode 100644
index 000000000000..680c1141e0de
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/x86.h
@@ -0,0 +1,4 @@
+int startup_64(void);
+int x86_64_start_reservations(void);
+void setup_arch(void);
+void late_init(void);
diff --git a/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h b/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
new file mode 100644
index 000000000000..afece8ce6dd4
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
@@ -0,0 +1,169 @@
+#ifndef __X86_INIT_TABLES_H
+#define __X86_INIT_TABLES_H
+
+#include <linux/types.h>
+#include <linux/tables.h>
+
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <asm/bootparam.h>
+
+/**
+ * struct x86_init_fn - x86 generic kernel init call
+ *
+ * Linux x86 features vary in complexity, features may require work done at
+ * different levels of the full x86 init sequence. Today there are also two
+ * different possible entry points for Linux on x86, one for bare metal, KVM
+ * and Xen HVM, and another for Xen PV guests / dom0.  Assuming a bootloader
+ * has set up 64-bit mode, roughly the x86 init sequence follows this path:
+ *
+ * Bare metal, KVM, Xen HVM                      Xen PV / dom0
+ *       startup_64()                             startup_xen()
+ *              \                                     /
+ *      x86_64_start_kernel()                 xen_start_kernel()
+ *                           \               /
+ *                      x86_64_start_reservations()
+ *                                   |
+ *                              start_kernel()
+ *                              [   ...        ]
+ *                              [ setup_arch() ]
+ *                              [   ...        ]
+ *                                  init
+ *
+ * x86_64_start_kernel() and xen_start_kernel() are the respective first C code
+ * entry starting points. The different entry points exist to enable Xen to
+ * skip a lot of hardware setup already done and managed on behalf of the
+ * hypervisor, we refer to this as "paravirtualization yielding". The different
+ * levels of init calls on the x86 init sequence exist to account for these
+ * slight differences and requirements. These different entry points also share
+ * a common entry x86 specific path, x86_64_start_reservations().
+ *
+ * A generic x86 feature can have different initialization calls, one on each
+ * of the different main x86 init sequences, but must also address both entry
+ * points in order to work properly across the board on all supported x86
+ * subarchitectures. Since x86 features can also have dependencies on other
+ * setup code or features, x86 features can at times be subordinate to other
+ * x86 features, or conditions. struct x86_init_fn enables feature developers
+ * to annotate dependency relationships to ensure subsequent init calls only
+ * run once a subordinate's dependencies have run. When needed custom
+ * dependency requirements can also be spelled out through a custom dependency
+ * checker. In order to account for the dual entry point nature of x86-64 Linux
+ * for "paravirtualization yielding" and to make annotations for support for
+ * these explicit each struct x86_init_fn must specify supported
+ * subarchitectures. The earliest x86-64 code can read the subarchitecture
+ * though is after load_idt(), as such the earliest we can currently rely on
+ * subarchitecture for semantics and a common init sequences is on the shared
+ * common x86_64_start_reservations().  Each struct x86_init_fn is associated
+ * with a specific special link order number which has been careflly thought
+ * out by x86 maintainers. You should pick a link order level associated with
+ * the specific directory your code lies in, a respective macro is used to
+ * build association to a link oder with a routine, you should use one of the
+ * provided x86_init_*() macros. You should not use __x86_init() directly.
+ *
+ * x86_init_fn enables strong semantics and dependencies to be defined and
+ * implemented on the full x86 initialization sequence.
+ *
+ * @supp_hardware_subarch: must be set, it represents the bitmask of supported
+ *	subarchitectures.  We require each struct x86_init_fn to have this set
+ *	to require developer considerations for each supported x86
+ *	subarchitecture and to build strong annotations of different possible
+ *	run time states particularly in consideration for the two main
+ *	different entry points for x86 Linux, to account for paravirtualization
+ *	yielding.
+ *
+ *	The subarchitecture is read by the kernel at early boot from the
+ *	struct boot_params hardware_subarch. Support for the subarchitecture
+ *	exists as of x86 boot protocol 2.07. The bootloader would have set up
+ *	the respective hardware_subarch on the boot sector as per
+ *	Documentation/x86/boot.txt.
+ *
+ *	What x86 entry point is used is determined at run time by the
+ *	bootloader. Linux pv_ops was designed to help enable to build one Linux
+ *	binary to support bare metal and different hypervisors.  pv_ops setup
+ *	code however is limited in that all pv_ops setup code is run late in
+ *	the x86 init sequence, during setup_arch(). In fact cpu_has_hypervisor
+ *	only works after early_cpu_init() during setup_arch(). If an x86
+ *	feature requires an earlier determination of what hypervisor was used,
+ *	or if it needs to annotate only support for certain hypervisors, the
+ *	x86 hardware_subarch should be set by the bootloader and
+ *	@supp_hardware_subarch set by the x86 feature. Using hardware_subarch
+ *	enables x86 features to fill the semantic gap between the Linux x86
+ *	entry point used and what pv_ops has to offer through a hypervisor
+ *	agnostic mechanism.
+ *
+ *	Each supported subarchitecture is set using the respective
+ *	X86_SUBARCH_* as a bit in the bitmask. For instance if a feature
+ *	is supported on PC and Xen subarchitectures only you would set this
+ *	bitmask to:
+ *
+ *		BIT(X86_SUBARCH_PC) |
+ *		BIT(X86_SUBARCH_XEN);
+ *
+ * @early_init: required, routine which will run in x86_64_start_reservations()
+ *	after we ensure boot_params.hdr.hardware_subarch is accessible and
+ *	properly set. Memory is not yet available. This the earliest we can
+ *	currently define a common shared callback since all callbacks need to
+ *	check for boot_params.hdr.hardware_subarch and this becomes accessible
+ *	on x86-64 until after load_idt().
+ */
+struct x86_init_fn {
+	__u32 supp_hardware_subarch;
+	void (*early_init)(void);
+};
+
+DECLARE_LINKTABLE(struct x86_init_fn, x86_init_fns);
+
+/* Init order levels, we can start at 0000 but reserve 0000-0999 for now */
+
+/*
+ * X86_INIT_ORDER_EARLY - early kernel init code
+ *
+ * This consists of the first parts of the Linux kernel executed.
+ */
+#define X86_INIT_ORDER_EARLY	1000
+
+/* X86_INIT_ORDER_PLATFORM - platform kernel code
+ *
+ * Code the kernel needs to initialize under arch/x86/platform/
+ * early in boot.
+ */
+#define X86_INIT_ORDER_PLATFORM	3000
+
+#define __x86_init(__level,						\
+		   __supp_hardware_subarch,				\
+		   __early_init)					\
+	static LINKTABLE_INIT_DATA(x86_init_fns, __level)		\
+	__x86_init_fn_##__early_init = {				\
+		.supp_hardware_subarch = __supp_hardware_subarch,	\
+		.early_init = __early_init,				\
+	};
+
+#define x86_init_early(__supp_hardware_subarch,				\
+		       __early_init)					\
+	__x86_init(X86_INIT_ORDER_EARLY, __supp_hardware_subarch,	\
+		   __early_init);
+
+#define x86_init_platform(__supp_hardware_subarch,			\
+		       __early_init)					\
+	__x86_init(__name, X86_INIT_ORDER_PLATFORM, __supp_hardware_subarch,\
+		   __early_init);
+
+#define x86_init_early_all(__early_init)				\
+	x86_init_early(X86_SUBARCH_ALL_SUBARCHS,			\
+		       __early_init);
+
+#define x86_init_early_pc(__early_init)					\
+	x86_init_early(BIT(X86_SUBARCH_PC),				\
+		       __early_init);
+
+#define x86_init_early_xen(__early_init)				\
+	x86_init_early(BIT(X86_SUBARCH_XEN),				\
+		       __early_init);
+/**
+ * x86_init_fn_early_init: call all early_init() callbacks
+ *
+ * This calls all early_init() callbacks on the x86_init_fns linker table.
+ */
+void x86_init_fn_early_init(void);
+
+#endif /* __X86_INIT_TABLES_H */
diff --git a/tools/linker-tables/arch/x86/kernel/alpha.c b/tools/linker-tables/arch/x86/kernel/alpha.c
new file mode 100644
index 000000000000..0f9d45734c33
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/alpha.c
@@ -0,0 +1,9 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_alpha(void) {
+	pr_info("Initializing alpha ...\n");
+	pr_info("Completed initializing alpha !\n");
+}
+
+x86_init_early_pc(early_init_alpha);
diff --git a/tools/linker-tables/arch/x86/kernel/alternative.c b/tools/linker-tables/arch/x86/kernel/alternative.c
new file mode 100644
index 000000000000..8e2495669c92
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/alternative.c
@@ -0,0 +1,31 @@
+#include <asm/x86_init_fn.h>
+
+#include <linux/kernel.h>
+#include <linux/ps_const.h>
+
+void apply_alternatives_linker_tables(void)
+{
+	unsigned int num_consts = LINKTABLE_SIZE(ps_set_const_table);
+	struct ps_set_const *ps_const;
+
+	if (!num_consts)
+		return;
+
+	pr_debug("Number of init entries: %d\n", num_consts);
+
+	linktable_for_each(ps_const, ps_set_const_table) {
+		switch(ps_const->type) {
+		case SET_CONST_U8:
+			*ps_const->count = (__u8) ps_const->func();
+			break;
+		case SET_CONST_U16:
+			*ps_const->count = (__u16) ps_const->func();
+			break;
+		case SET_CONST_U32:
+			*ps_const->count = (__u16) ps_const->func();
+			break;
+		}
+	}
+}
+
+x86_init_early_pc(apply_alternatives_linker_tables);
diff --git a/tools/linker-tables/arch/x86/kernel/beta.c b/tools/linker-tables/arch/x86/kernel/beta.c
new file mode 100644
index 000000000000..2bdbf49d4731
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/beta.c
@@ -0,0 +1,9 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_beta(void) {
+	pr_info("Initializing beta ...\n");
+	pr_info("Completed initializing beta !\n");
+}
+
+x86_init_early_pc(early_init_beta);
diff --git a/tools/linker-tables/arch/x86/kernel/head64.c b/tools/linker-tables/arch/x86/kernel/head64.c
new file mode 100644
index 000000000000..d14dcdfd0ea9
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/head64.c
@@ -0,0 +1,58 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+
+#include <asm/x86_init_fn.h>
+#include <asm/boot.h>
+#include <asm/bootparam.h>
+
+#include <linux/start_kernel.h>
+#include <linux/kasan.h>
+
+void x86_64_start_reservations(void)
+{
+	switch (boot_params.hdr.hardware_subarch) {
+	case X86_SUBARCH_PC:
+		pr_info("Booting bare metal\n");
+		break;
+	case X86_SUBARCH_LGUEST:
+		pr_info("Booting lguest not supported\n");
+		BUG();
+	case X86_SUBARCH_XEN:
+		pr_info("Booting a Xen guest\n");
+		break;
+	case X86_SUBARCH_INTEL_MID:
+		pr_info("Booting Intel MID not supported\n");
+		BUG();
+	case X86_SUBARCH_CE4100:
+		pr_info("Booting Intel CE4100 not supported\n");
+		BUG();
+	default:
+		pr_info("Booting sunsupported x86 hardware subarch\n");
+		BUG();
+	}
+
+	start_kernel();
+}
+
+static void x86_64_start_kernel(void)
+{
+	x86_init_fn_early_init();
+
+	x86_64_start_reservations();
+}
+
+void startup_64(void)
+{
+	pr_info("Initializing x86 bare metal world\n");
+	x86_64_start_kernel();
+}
+
+void setup_arch(void)
+{
+	/* TODO: x86_init_fn_setup_arch(); */
+}
+
+void late_init(void)
+{
+	/* TODO: x86_init_fn_late_init(); */
+}
diff --git a/tools/linker-tables/arch/x86/kernel/init.c b/tools/linker-tables/arch/x86/kernel/init.c
new file mode 100644
index 000000000000..1eed92d1acb2
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/init.c
@@ -0,0 +1,42 @@
+#define pr_fmt(fmt) "x86-init: " fmt
+
+#include <linux/bug.h>
+#include <linux/kernel.h>
+
+#include <asm/x86_init_fn.h>
+#include <asm/bootparam.h>
+#include <asm/boot.h>
+#include <asm/setup.h>
+
+DEFINE_LINKTABLE_INIT_DATA(struct x86_init_fn, x86_init_fns);
+
+static bool x86_init_fn_supports_subarch(struct x86_init_fn *fn)
+{
+	if (!fn->supp_hardware_subarch) {
+		//pr_err("Init sequence fails to declares any supported subarchs: %pF\n", fn->early_init);
+		WARN_ON(1);
+	}
+	if (BIT(boot_params.hdr.hardware_subarch) & fn->supp_hardware_subarch)
+		return true;
+	return false;
+}
+
+void __ref x86_init_fn_early_init(void)
+{
+	struct x86_init_fn *init_fn;
+	unsigned int num_inits = LINKTABLE_SIZE(x86_init_fns);
+
+	if (!num_inits)
+		return;
+
+	pr_debug("Number of init entries: %d\n", num_inits);
+
+	linktable_for_each(init_fn, x86_init_fns) {
+		if (!x86_init_fn_supports_subarch(init_fn))
+			continue;
+
+		//pr_debug("Running early init %pF ...\n", init_fn->early_init);
+		init_fn->early_init();
+		//pr_debug("Completed early init %pF\n", init_fn->early_init);
+	}
+}
diff --git a/tools/linker-tables/arch/x86/kernel/kasan.c b/tools/linker-tables/arch/x86/kernel/kasan.c
new file mode 100644
index 000000000000..c0120676eb9c
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/kasan.c
@@ -0,0 +1,10 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+void kasan_early_init(void) {
+	pr_info("Initializing kasan ...\n");
+	pr_info("Early init for Kasan...\n");
+	pr_info("Completed initializing kasan !\n");
+}
+
+x86_init_early_pc(kasan_early_init);
diff --git a/tools/linker-tables/arch/x86/kernel/kprobes.c b/tools/linker-tables/arch/x86/kernel/kprobes.c
new file mode 100644
index 000000000000..c4e42beae55b
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/kprobes.c
@@ -0,0 +1,51 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <linux/ranges.h>
+#include <linux/kprobes.h>
+
+DEFINE_SECTION_RANGE(kprobes, .text);
+
+void __kprobes test_kprobe_0001(void)
+{
+	pr_info("test_kprobe\n");
+}
+
+void test_kprobe_0002(void)
+{
+	pr_info("test_kprobe\n");
+}
+
+void test_kprobe_addr(const char *test, unsigned long addr, bool should_match)
+{
+	if (SECTION_RANGE_ADDR_WITHIN(kprobes, addr))
+		if (should_match)
+			pr_info("= OK: %s within range!\n", test);
+		else
+			pr_info("= FAIL: %s should not be in range...\n",
+				test);
+	else
+		if (should_match)
+			pr_info("= FAIL: %s should be in range...\n", test);
+		else
+			pr_info("= OK: %s not in range as expected!\n", test);
+}
+
+void early_init_kprobes(void)
+{
+	unsigned long addr;
+
+	pr_info("Initializing kprobes ...\n");
+
+	addr = (unsigned long) &test_kprobe_0001;
+
+	test_kprobe_addr("test_kprobe_0001", addr, true);
+
+	addr = (unsigned long) &test_kprobe_0002;
+
+	test_kprobe_addr("test_kprobe_0002", addr, false);
+
+	pr_info("Completed initializing kprobes !\n");
+}
+
+x86_init_early_all(early_init_kprobes);
diff --git a/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S b/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
new file mode 100644
index 000000000000..783735fb897a
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
@@ -0,0 +1,277 @@
+/* Script for -z combreloc: combine and sort reloc sections */
+/* Copyright (C) 2014 Free Software Foundation, Inc.
+   Copying and distribution of this script, with or without modification,
+   are permitted in any medium without royalty provided the copyright
+   notice and this notice are preserved.  */
+
+#include <asm/section-core.h>
+#include <asm/ranges.h>
+#include <asm/tables.h>
+
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
+	      "elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(_start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
+  .interp         : { *(.interp) }
+  .note.gnu.build-id : { *(.note.gnu.build-id) }
+  .hash           : { *(.hash) }
+  .gnu.hash       : { *(.gnu.hash) }
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+  .rela.dyn       :
+    {
+      *(.rela.init)
+      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+      *(.rela.fini)
+      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+      *(.rela.ctors)
+      *(.rela.dtors)
+      *(.rela.got)
+      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+      *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
+      *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
+      *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
+      *(.rela.ifunc)
+    }
+  .rela.plt       :
+    {
+      *(.rela.plt)
+      PROVIDE_HIDDEN (__rela_iplt_start = .);
+      *(.rela.iplt)
+      PROVIDE_HIDDEN (__rela_iplt_end = .);
+    }
+  .init           :
+  {
+    KEEP (*(SORT_NONE(.init)))
+  }
+  .plt            : { *(.plt) *(.iplt) }
+  .plt.bnd        : { *(.plt.bnd) }
+  .text           :
+  {
+    *(.text.unlikely .text.*_unlikely .text.unlikely.*)
+    *(.text.exit .text.exit.*)
+    *(.text.startup .text.startup.*)
+    *(.text.hot .text.hot.*)
+
+    *(SORT(.text..rng.*))
+    *(SORT(.text..tbl.*))
+
+    *(SORT(.init.text..rng.*))
+    *(SORT(.init.text..tbl.*))
+
+    *(SORT(.initcall..rng.*))
+    *(SORT(.initcall..tbl.*))
+
+    *(SORT(.exit.text..rng.*))
+    *(SORT(.exit.text..tbl.*))
+
+    *(SORT(.exitcall.exit..rng.*))
+    *(SORT(.exitcall.exit..tbl.*))
+
+    *(.text .stub .text.* .gnu.linkonce.t.*)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  }
+  .fini           :
+  {
+    KEEP (*(SORT_NONE(.fini)))
+  }
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+  .rodata         :
+  {
+	*(.rodata)
+
+	*(SORT(.rodata.*))
+
+	*(SORT(.rodata..rng.*))
+	*(SORT(.rodata..tbl.*))
+
+	*(SORT(.init.rodata..rng.*))
+	*(SORT(.init.rodata..tbl.*))
+
+	*(SORT(.ref.rodata..rng.*))
+	*(SORT(.ref.rodata..tbl.*))
+
+	*(.gnu.linkonce.r.*)
+  }
+  .rodata1        : { *(.rodata1) }
+  .eh_frame_hdr : { *(.eh_frame_hdr) }
+  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table
+  .gcc_except_table.*) }
+  /* These sections are generated by the Sun/Oracle C++ compiler.  */
+  .exception_ranges   : ONLY_IF_RO { *(.exception_ranges
+  .exception_ranges*) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  */
+  . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+  /* Exception handling  */
+  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
+  .exception_ranges   : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
+  /* Thread Local Storage sections  */
+  .tdata	  : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+  .preinit_array     :
+  {
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP (*(.preinit_array))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+  }
+  .init_array     :
+  {
+    PROVIDE_HIDDEN (__init_array_start = .);
+    KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
+    KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
+    PROVIDE_HIDDEN (__init_array_end = .);
+  }
+  .fini_array     :
+  {
+    PROVIDE_HIDDEN (__fini_array_start = .);
+    KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
+    KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
+    PROVIDE_HIDDEN (__fini_array_end = .);
+  }
+  .ctors          :
+  {
+    /* gcc uses crtbegin.o to find the start of
+       the constructors, so we make sure it is
+       first.  Because this is a wildcard, it
+       doesn't matter if the user does not
+       actually link against crtbegin.o; the
+       linker won't look for a file to match a
+       wildcard.  The wildcard also means that it
+       doesn't matter which directory crtbegin.o
+       is in.  */
+    KEEP (*crtbegin.o(.ctors))
+    KEEP (*crtbegin?.o(.ctors))
+    /* We don't want to include the .ctor section from
+       the crtend.o file until after the sorted ctors.
+       The .ctor section from the crtend file contains the
+       end of ctors marker and it must be last */
+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+  .dtors          :
+  {
+    KEEP (*crtbegin.o(.dtors))
+    KEEP (*crtbegin?.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  .jcr            : { KEEP (*(.jcr)) }
+  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
+  .dynamic        : { *(.dynamic) }
+  .got            : { *(.got) *(.igot) }
+  . = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
+  .got.plt        : { *(.got.plt)  *(.igot.plt) }
+  .data           :
+  {
+    *(.data .data.* .gnu.linkonce.d.*)
+
+    *(SORT(.data..rng.*))
+    *(SORT(.data..tbl.*))
+
+    *(SORT(.init.data..rng.*))
+    *(SORT(.init.data..tbl.*))
+
+    *(SORT(.ref.rodata..rng.*))
+    *(SORT(.ref.rodata..tbl.*))
+
+    *(SORT(.exit.data..rng.*))
+    *(SORT(.exit.data..tbl.*))
+
+    SORT(CONSTRUCTORS)
+  }
+  .data1          : { *(.data1) }
+  _edata = .; PROVIDE (edata = .);
+  . = .;
+
+  __bss_start = .;
+  .bss            :
+  {
+   *(.dynbss)
+   *(.bss .bss.* .gnu.linkonce.b.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.
+      FIXME: Why do we need it? When there is no .bss section, we don't
+      pad the .data section.  */
+   . = ALIGN(. != 0 ? 64 / 8 : 1);
+  }
+  .lbss   :
+  {
+    *(.dynlbss)
+    *(.lbss .lbss.* .gnu.linkonce.lb.*)
+    *(LARGE_COMMON)
+  }
+  . = ALIGN(64 / 8);
+  . = SEGMENT_START("ldata-segment", .);
+  .lrodata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+  {
+    *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
+  }
+  .ldata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+  {
+    *(.ldata .ldata.* .gnu.linkonce.l.*)
+    . = ALIGN(. != 0 ? 64 / 8 : 1);
+  }
+  . = ALIGN(64 / 8);
+  _end = .; PROVIDE (end = .);
+  . = DATA_SEGMENT_END (.);
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line .debug_line.* .debug_line_end ) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  /* DWARF 3 */
+  .debug_pubtypes 0 : { *(.debug_pubtypes) }
+  .debug_ranges   0 : { *(.debug_ranges) }
+  /* DWARF Extension.  */
+  .debug_macro    0 : { *(.debug_macro) }
+  .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
+}
diff --git a/tools/linker-tables/arch/x86/mm/init.c b/tools/linker-tables/arch/x86/mm/init.c
new file mode 100644
index 000000000000..dbf1a85a4043
--- /dev/null
+++ b/tools/linker-tables/arch/x86/mm/init.c
@@ -0,0 +1,10 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_memory(void) {
+	pr_info("Initializing memory ...\n");
+	sleep(1);
+	pr_info("Completed initializing memory !\n");
+}
+
+x86_init_early_all(early_init_memory);
diff --git a/tools/linker-tables/arch/x86/xen/init.c b/tools/linker-tables/arch/x86/xen/init.c
new file mode 100644
index 000000000000..40ad493daee8
--- /dev/null
+++ b/tools/linker-tables/arch/x86/xen/init.c
@@ -0,0 +1,13 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <asm/x86.h>
+
+void startup_xen(void)
+{
+	pr_info("Initializing Xen guest\n");
+
+	x86_init_fn_early_init();
+
+	x86_64_start_reservations();
+}
diff --git a/tools/linker-tables/drivers/acme.c b/tools/linker-tables/drivers/acme.c
new file mode 100644
index 000000000000..dd321686dd49
--- /dev/null
+++ b/tools/linker-tables/drivers/acme.c
@@ -0,0 +1,32 @@
+#define pr_fmt(fmt) "ACME: " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/workqueue.h>
+
+void *acme_todo(void *arg);
+static DECLARE_WORK(acme_work, acme_todo);
+
+void *acme_todo(void *arg)
+{
+	pr_info("Running scheduled work\n");
+	pthread_exit(NULL);
+}
+
+static int acme_init_driver(void) {
+	pr_info("Initializing ...\n");
+	sleep(2);
+	pr_info("Finished init ... !\n");
+
+	init_work(&acme_work);
+	schedule_work(&acme_work);
+
+	return 0;
+}
+module_init(acme_init_driver);
+
+static void acme_exit(void)
+{
+	cancel_work_sync(&acme_work);
+};
+module_exit(acme_exit);
diff --git a/tools/linker-tables/drivers/synth/common.c b/tools/linker-tables/drivers/synth/common.c
new file mode 100644
index 000000000000..b44d9fcc7a9b
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/common.c
@@ -0,0 +1,16 @@
+int demo_or_1(int arg)
+{
+	switch (arg) {
+	case 1:
+		return 0xDEA00000;
+	case 2:
+		return 0X000D0000;
+	default:
+		return arg * 2;
+	}
+}
+
+int demo_or_2(void)
+{
+	return 0x0000BEEF;
+}
diff --git a/tools/linker-tables/drivers/synth/common.h b/tools/linker-tables/drivers/synth/common.h
new file mode 100644
index 000000000000..92827004f532
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/common.h
@@ -0,0 +1,2 @@
+int demo_or_1(int arg);
+int demo_or_2(void);
diff --git a/tools/linker-tables/drivers/synth/main.c b/tools/linker-tables/drivers/synth/main.c
new file mode 100644
index 000000000000..555cf97a5cbb
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/main.c
@@ -0,0 +1,35 @@
+#define pr_fmt(fmt) "Synthetics: " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ps_const.h>
+
+#include "common.h"
+#include "synth.h"
+
+DEFINE_LINKTABLE_INIT_DATA(struct ps_set_const, ps_set_const_table);
+
+unsigned int get_demo_shr(void)
+{
+	return 16;
+}
+
+static int synth_init(void)
+{
+	int synth_or;
+	int val = 2;
+	const unsigned int reg =  ps_shr(0xDEADBEEF, get_demo_shr);
+
+	synth_or = synth_init_or(val);
+	pr_info("synth_init_or(%d) returns: 0x%08X\n", val, synth_or);
+
+	pr_info("ps_shr(0x%08X, get_demo_shr) returns: 0x%08X\n", 0xDEADBEEF, reg);
+
+	return 0;
+}
+module_init(synth_init);
+
+static void synth_exit(void)
+{
+}
+module_exit(synth_exit);
diff --git a/tools/linker-tables/drivers/synth/or.S b/tools/linker-tables/drivers/synth/or.S
new file mode 100644
index 000000000000..deb963fdae33
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/or.S
@@ -0,0 +1,39 @@
+#include <asm/ranges.h>
+
+	DEFINE_SECTION_RANGE(.text, synth_init_or)
+
+	push_section_rng_level(.text, synth_init_or, "01", )
+	/* err = 0; */
+	pushq %rbp
+	movq %rsp,%rbp
+	pushq %rbx
+	xorq %rbx,%rbx
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "99", )
+	/* return err; */
+	movq %rbx,%rax
+	popq %rbx
+	popq %rbp
+	retq
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "50", )
+	/* err |= demo_or_1(1); */
+	movl $1,%edi
+	call demo_or_1
+	orq %rax,%rbx
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "50", )
+	/* err |= demo_or_1(2); */
+	movl $2,%edi
+	call demo_or_1
+	orq %rax,%rbx
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "50", )
+	/* err |= demo_or_2(); */
+	call demo_or_2
+	orq %rax,%rbx
+	.popsection
diff --git a/tools/linker-tables/drivers/synth/synth.h b/tools/linker-tables/drivers/synth/synth.h
new file mode 100644
index 000000000000..abbb9afac374
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/synth.h
@@ -0,0 +1,2 @@
+/* Synthetic demos go here */
+int synth_init_or(int arg);
diff --git a/tools/linker-tables/drivers/xen-driver.c b/tools/linker-tables/drivers/xen-driver.c
new file mode 100644
index 000000000000..79d229f72818
--- /dev/null
+++ b/tools/linker-tables/drivers/xen-driver.c
@@ -0,0 +1,11 @@
+#include <asm/x86_init_fn.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <xen/xen.h>
+
+static void early_xen_init_driver(void) {
+	pr_info("Initializing xen driver\n");
+	sleep(2);
+}
+
+x86_init_early_xen(early_xen_init_driver);
diff --git a/tools/linker-tables/include/asm-generic/arch_init_fn.h b/tools/linker-tables/include/asm-generic/arch_init_fn.h
new file mode 100644
index 000000000000..61a04a50b453
--- /dev/null
+++ b/tools/linker-tables/include/asm-generic/arch_init_fn.h
@@ -0,0 +1,50 @@
+#ifndef __ARCH_INIT_TABLES_H
+#define __ARCH_INIT_TABLES_H
+
+#include <linux/types.h>
+#include <linux/tables.h>
+#include <linux/init.h>
+
+/**
+ * struct arch_init_fn - architecture-generic kernel init call
+ *
+ * Architectures must initialize a series of things prior to handing off
+ * control to the kernel. This structure can be used if the architecture is
+ * simple and it just needs a basic set of calls on its way up.
+ *
+ * @early_init: required, routine which will run in startup_64(). Memory is
+ * 	not yet available.
+ */
+struct arch_init_fn {
+	void (*early_init)(void);
+};
+
+DECLARE_LINKTABLE(struct arch_init_fn, arch_init_fns);
+
+/* Init order levels, we can start at 0000 but reserve 0000-0999 for now */
+
+/*
+ * ARCH_INIT_ORDER_EARLY - early kernel init code
+ *
+ * This consists of the first parts of the Linux kernel executed.
+ */
+#define ARCH_INIT_ORDER_EARLY	1000
+
+#define __arch_init(__level,						\
+		    __early_init)					\
+	static LINKTABLE_INIT_DATA(arch_init_fns, __level)		\
+	__arch_init_fn_##__early_init = {				\
+		.early_init = __early_init,				\
+	}
+
+#define arch_init_early(__early_init)					\
+	__arch_init(ARCH_INIT_ORDER_EARLY, __early_init)
+
+/**
+ * arch_init_fn_early_init: call all early_init() callbacks
+ *
+ * This calls all early_init() callbacks on the arch_init_fns linker table.
+ */
+void arch_init_fn_early_init(void);
+
+#endif /* __ARCH_INIT_TABLES_H */
diff --git a/tools/linker-tables/include/asm-generic/kprobes.h b/tools/linker-tables/include/asm-generic/kprobes.h
new file mode 100644
index 000000000000..839d2eb464d3
--- /dev/null
+++ b/tools/linker-tables/include/asm-generic/kprobes.h
@@ -0,0 +1,26 @@
+#ifndef _SANDBOX_ASM_GENERIC_KPROBES_H
+#define _SANDBOX_ASM_GENERIC_KPROBES_H
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#ifdef CONFIG_KPROBES
+#include <linux/tables.h>
+#include <asm/ranges.h>
+/*
+ * Blacklist ganerating macro. Specify functions which is not probed
+ * by using this macro.
+ */
+# define __NOKPROBE_SYMBOL(fname)				\
+static LINKTABLE_INIT_DATA(_kprobe_blacklist, all)		\
+	_kbl_addr_##fname = (unsigned long)fname;
+# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
+/* Use this to forbid a kprobes attach on very low level functions */
+# define __kprobes	__LINUX_RANGE(.text, kprobes)
+# define nokprobe_inline	__always_inline
+#else
+# define NOKPROBE_SYMBOL(fname)
+# define __kprobes
+# define nokprobe_inline	inline
+#endif
+#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
+
+#endif /* _SANDBOX_ASM_GENERIC_KPROBES_H */
diff --git a/tools/linker-tables/include/linux/bitops.h b/tools/linker-tables/include/linux/bitops.h
new file mode 100644
index 000000000000..2960e8089ebc
--- /dev/null
+++ b/tools/linker-tables/include/linux/bitops.h
@@ -0,0 +1,6 @@
+#ifndef _LINUX_BITOPS_H
+#define _LINUX_BITOPS_H
+
+#define BIT(nr)		(1UL << (nr))
+
+#endif /* _LINUX_BITOPS_H */
diff --git a/tools/linker-tables/include/linux/init.h b/tools/linker-tables/include/linux/init.h
new file mode 100644
index 000000000000..2691c3697f48
--- /dev/null
+++ b/tools/linker-tables/include/linux/init.h
@@ -0,0 +1,40 @@
+#ifndef _SANDBOX_LINUX_INIT_H
+#define _SANDBOX_LINUX_INIT_H
+
+#include_next <linux/init.h>
+#include <linux/types.h>
+#include <linux/sections.h>
+
+#define __init	__section(.init.text)
+#define __exit	__section(.exit.text)
+
+#ifndef __ASSEMBLY__
+#include <linux/tables.h>
+typedef int (*initcall_t)(void);
+typedef void (*exitcall_t)(void);
+
+DECLARE_LINKTABLE(initcall_t, init_calls);
+DECLARE_LINKTABLE(exitcall_t, exit_calls);
+
+#define __define_initcall(fn, id)					\
+	static LINKTABLE_INIT_DATA(init_calls, id)			\
+	__initcall_##fn##id = fn
+
+#define pure_initcall(fn)			__define_initcall(fn, 0)
+#define core_initcall(fn)			__define_initcall(fn, 1)
+#define postcore_initcall(fn)			__define_initcall(fn, 2)
+#define arch_initcall(fn)			__define_initcall(fn, 3)
+#define subsys_initcall(fn)			__define_initcall(fn, 4)
+#define fs_initcall(fn)				__define_initcall(fn, 5)
+#define device_initcall(fn)			__define_initcall(fn, 6)
+#define late_initcall(fn)			__define_initcall(fn, 7)
+
+#define __initcall(fn)				device_initcall(fn)
+
+#define __exitcall(fn)							\
+	static LINKTABLE_INIT_DATA(exit_calls, any)			\
+	__exitcall_##fn = fn;
+
+#endif
+
+#endif /* _SANDBOX_LINUX_INIT_H */
diff --git a/tools/linker-tables/include/linux/kasan.h b/tools/linker-tables/include/linux/kasan.h
new file mode 100644
index 000000000000..41791187854e
--- /dev/null
+++ b/tools/linker-tables/include/linux/kasan.h
@@ -0,0 +1,5 @@
+#include <linux/types.h>
+
+void kasan_early_init(void);
+int kasan_init(void);
+bool is_kasan_setup(void);
diff --git a/tools/linker-tables/include/linux/kernel.h b/tools/linker-tables/include/linux/kernel.h
new file mode 100644
index 000000000000..e2857c0b5b11
--- /dev/null
+++ b/tools/linker-tables/include/linux/kernel.h
@@ -0,0 +1,2 @@
+#include_next <linux/kernel.h>
+#include <linux/printk.h>
diff --git a/tools/linker-tables/include/linux/kprobes.h b/tools/linker-tables/include/linux/kprobes.h
new file mode 100644
index 000000000000..ecd5a0a69ae6
--- /dev/null
+++ b/tools/linker-tables/include/linux/kprobes.h
@@ -0,0 +1,11 @@
+#ifndef _SANDBOX_LINUX_KPROBES_H
+#define _SANDBOX_LINUX_KPROBES_H
+
+#include <asm/kprobes.h>
+#include <linux/ranges.h>
+
+#ifdef CONFIG_KPROBES
+DECLARE_SECTION_RANGE(kprobes);
+#endif
+
+#endif /* _SANDBOX_LINUX_KPROBES_H */
diff --git a/tools/linker-tables/include/linux/module.h b/tools/linker-tables/include/linux/module.h
new file mode 100644
index 000000000000..b59e55f3f04e
--- /dev/null
+++ b/tools/linker-tables/include/linux/module.h
@@ -0,0 +1,14 @@
+#ifndef _LINUX_MODULE_H
+#define _LINUX_MODULE_H
+
+#include <linux/init.h>
+
+#define module_init(x)  __initcall(x);
+#define module_exit(x)  __exitcall(x);
+
+struct module {
+	int (*init)(void);
+	void (*exit)(void);
+};
+
+#endif /* _LINUX_MODULE_H */
diff --git a/tools/linker-tables/include/linux/mutex.h b/tools/linker-tables/include/linux/mutex.h
new file mode 100644
index 000000000000..a74f951ceb42
--- /dev/null
+++ b/tools/linker-tables/include/linux/mutex.h
@@ -0,0 +1,17 @@
+#ifndef __LINUX_MUTEX_H
+#define __LINUX_MUTEX_H
+
+#include <sys/types.h>
+#include <linux/sched.h>
+#include <pthread.h>
+
+struct mutex {
+	pthread_mutex_t lock;
+};
+
+void mutex_init(struct mutex *lock);
+void mutex_destroy(struct mutex *lock);
+void mutex_lock(struct mutex *lock);
+void mutex_unlock(struct mutex *lock);
+
+#endif /* __LINUX_MUTEX_H */
diff --git a/tools/linker-tables/include/linux/pci.h b/tools/linker-tables/include/linux/pci.h
new file mode 100644
index 000000000000..8518c46631f7
--- /dev/null
+++ b/tools/linker-tables/include/linux/pci.h
@@ -0,0 +1,7 @@
+#include <linux/types.h>
+
+struct pci_fixup {
+	void (*hook)(void);
+};
+
+bool detect_pci(void);
diff --git a/tools/linker-tables/include/linux/printk.h b/tools/linker-tables/include/linux/printk.h
new file mode 100644
index 000000000000..dc137d3421e8
--- /dev/null
+++ b/tools/linker-tables/include/linux/printk.h
@@ -0,0 +1,26 @@
+#ifndef _SANDBOX_KERNEL_PRINTK
+#define _SANDBOX_KERNEL_PRINTK
+
+#ifdef __KERNEL__
+
+#include <stdio.h>
+
+#ifndef pr_fmt
+#define pr_fmt(fmt)	fmt
+#endif
+
+#ifndef pr_info
+#define pr_info(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
+#ifndef pr_err
+#define pr_err(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
+#ifndef pr_debug
+#define pr_debug(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* _SANDBOX_KERNEL_PRINTK */
diff --git a/tools/linker-tables/include/linux/ps_const.h b/tools/linker-tables/include/linux/ps_const.h
new file mode 100644
index 000000000000..5eab3a124e00
--- /dev/null
+++ b/tools/linker-tables/include/linux/ps_const.h
@@ -0,0 +1,46 @@
+#ifndef __PS_CONST
+#define __PS_CONST
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/tables.h>
+
+/* Helpers for partially static settings */
+
+enum ps_static_type {
+	SET_CONST_U8 = 0,
+	SET_CONST_U16,
+	SET_CONST_U32,
+};
+
+struct ps_set_const {
+	unsigned int *count;
+	enum ps_static_type type;
+	unsigned int (*func)(void);
+};
+
+DECLARE_LINKTABLE(struct ps_set_const, ps_set_const_table);
+
+#ifdef CONFIG_HAVE_ARCH_PS_CONST
+#include <asm/ps_const.h>
+#endif
+
+/*
+ * ps_ stands for "partially static", so we "partialloy static shift right"
+ * You can optimize this for your architecture.
+ *
+ * ps_shr(unsigned int in, unsigned char (*func)(void))
+ */
+#ifndef ps_shr
+#define ps_shr(_in, _func)						\
+({									\
+	static unsigned int _count;					\
+	static LINKTABLE_INIT_DATA(ps_set_const_table, 01)		\
+		__ps_shr##__func =					\
+		{ &_count, SET_CONST_U8, (_func) };			\
+									\
+	(_in) >> _count;						\
+})
+#endif /* ps_shr */
+
+#endif /* __PS_CONST */
diff --git a/tools/linker-tables/include/linux/sched.h b/tools/linker-tables/include/linux/sched.h
new file mode 100644
index 000000000000..0fe3526e88bf
--- /dev/null
+++ b/tools/linker-tables/include/linux/sched.h
@@ -0,0 +1,9 @@
+#ifndef _LINUX_SCHED_H
+#define _LINUX_SCHED_H
+
+#include <linux/ranges.h>
+
+DECLARE_SECTION_RANGE(sched_text);
+#define __sched		__LINUX_RANGE(.text, sched_text)
+
+#endif /* _LINUX_SCHED_H */
diff --git a/tools/linker-tables/include/linux/spinlock.h b/tools/linker-tables/include/linux/spinlock.h
new file mode 100644
index 000000000000..e62bc3bc5e6a
--- /dev/null
+++ b/tools/linker-tables/include/linux/spinlock.h
@@ -0,0 +1,13 @@
+#ifndef __LINUX_SPINLOCK_H
+#define __LINUX_SPINLOCK_H
+
+#include <pthread.h>
+
+#define spinlock_t pthread_spinlock_t
+
+void spin_lock_init(spinlock_t *lock);
+void spin_lock_destroy(spinlock_t *lock);
+void spin_lock(spinlock_t *lock);
+void spin_unlock(spinlock_t *lock);
+
+#endif /* __LINUX_SPINLOCK_H */
diff --git a/tools/linker-tables/include/linux/start_kernel.h b/tools/linker-tables/include/linux/start_kernel.h
new file mode 100644
index 000000000000..5c2cb9a5cb0c
--- /dev/null
+++ b/tools/linker-tables/include/linux/start_kernel.h
@@ -0,0 +1 @@
+int start_kernel(void);
diff --git a/tools/linker-tables/include/linux/types.h b/tools/linker-tables/include/linux/types.h
new file mode 100644
index 000000000000..3fc87b2c84e2
--- /dev/null
+++ b/tools/linker-tables/include/linux/types.h
@@ -0,0 +1,13 @@
+#ifndef __LINUX_USER_TYPES_H
+#define __LINUX_USER_TYPES_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+typedef unsigned char __u8;
+typedef unsigned short __u16;
+typedef unsigned int __u32;
+
+#endif /* __LINUX_USER_TYPES_H */
diff --git a/tools/linker-tables/include/linux/workqueue.h b/tools/linker-tables/include/linux/workqueue.h
new file mode 100644
index 000000000000..69e1c6de5051
--- /dev/null
+++ b/tools/linker-tables/include/linux/workqueue.h
@@ -0,0 +1,51 @@
+#ifndef _LINUX_WORKQUEUE_H
+#define _LINUX_WORKQUEUE_H
+
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <pthread.h>
+
+struct work {
+	bool ready;
+
+	pthread_t thread;
+	struct mutex mutex;
+	pthread_cond_t cond;
+
+	void *arg;
+	void *(*work_cb)(void *arg);
+};
+
+#define DECLARE_WORK(_w, _w_cb) \
+struct work _w = { \
+	.work_cb = _w_cb, \
+	.arg = NULL, \
+};
+
+extern void *run_work(void *arg);
+
+static inline void init_work(struct work *w)
+{
+	w->ready = false;
+
+	mutex_init(&w->mutex);
+	pthread_cond_init(&w->cond, NULL);
+
+	pthread_create(&w->thread, NULL, run_work, (void *) w);
+
+	while (1) {
+		mutex_lock(&w->mutex);
+		if (w->ready) {
+			pthread_mutex_unlock(&w->mutex.lock);
+			break;
+		}
+		mutex_unlock(&w->mutex);
+	}
+}
+
+void schedule_work(struct work *w);
+void cancel_work_sync(struct work *w);
+void init_work(struct work *w);
+
+#endif /* _LINUX_WORKQUEUE_H */
diff --git a/tools/linker-tables/include/xen/xen.h b/tools/linker-tables/include/xen/xen.h
new file mode 100644
index 000000000000..782c799a0064
--- /dev/null
+++ b/tools/linker-tables/include/xen/xen.h
@@ -0,0 +1,4 @@
+#include <linux/types.h>
+
+bool booting_xen(void);
+int startup_xen(void);
diff --git a/tools/linker-tables/kernel/locking/mutex.c b/tools/linker-tables/kernel/locking/mutex.c
new file mode 100644
index 000000000000..950e4a18461e
--- /dev/null
+++ b/tools/linker-tables/kernel/locking/mutex.c
@@ -0,0 +1,28 @@
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+
+DEFINE_SECTION_RANGE(sched_text, .text);
+
+void __sched mutex_init(struct mutex *lock)
+{
+	int r;
+
+	r = pthread_mutex_init(&lock->lock, NULL);
+	if (r)
+		BUG_ON(r);
+}
+
+void __sched mutex_destroy(struct mutex *lock)
+{
+	pthread_mutex_destroy(&lock->lock);
+}
+
+void __sched mutex_lock(struct mutex *lock)
+{
+	pthread_mutex_lock(&lock->lock);
+}
+
+void __sched mutex_unlock(struct mutex *lock)
+{
+	pthread_mutex_unlock(&lock->lock);
+}
diff --git a/tools/linker-tables/kernel/locking/spinlock.c b/tools/linker-tables/kernel/locking/spinlock.c
new file mode 100644
index 000000000000..5be2bc7cdece
--- /dev/null
+++ b/tools/linker-tables/kernel/locking/spinlock.c
@@ -0,0 +1,26 @@
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+
+void spin_lock_init(spinlock_t *lock)
+{
+	int r;
+
+	r = pthread_spin_init(lock, PTHREAD_PROCESS_SHARED);
+	if (r)
+		BUG_ON(r);
+}
+
+void spin_lock_destroy(spinlock_t *lock)
+{
+	pthread_spin_destroy(lock);
+}
+
+void spin_lock(spinlock_t *lock)
+{
+	pthread_spin_lock(lock);
+}
+
+void spin_unlock(spinlock_t *lock)
+{
+	pthread_spin_unlock(lock);
+}
diff --git a/tools/linker-tables/kernel/main.c b/tools/linker-tables/kernel/main.c
new file mode 100644
index 000000000000..ad7a19c038bf
--- /dev/null
+++ b/tools/linker-tables/kernel/main.c
@@ -0,0 +1,32 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/x86_init_fn.h>
+#include <asm/x86.h>
+
+DEFINE_LINKTABLE_INIT_DATA(initcall_t, init_calls);
+
+int do_one_initcall(initcall_t fn)
+{
+	int ret;
+
+	ret = fn();
+
+	return ret;
+}
+
+static void do_initcalls(void)
+{
+	initcall_t *fn;
+
+	 linktable_for_each(fn, init_calls)
+		 do_one_initcall(*fn);
+}
+
+void start_kernel(void)
+{
+	pr_info("Calling start_kernel()...\n");
+
+	setup_arch();
+	late_init();
+	do_initcalls();
+}
diff --git a/tools/linker-tables/kernel/workqueue.c b/tools/linker-tables/kernel/workqueue.c
new file mode 100644
index 000000000000..5ba73c7e7c8b
--- /dev/null
+++ b/tools/linker-tables/kernel/workqueue.c
@@ -0,0 +1,43 @@
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <linux/workqueue.h>
+#include <linux/kernel.h>
+
+void schedule_work(struct work *w)
+{
+	mutex_lock(&w->mutex);
+	pthread_cond_signal(&w->cond);
+	mutex_unlock(&w->mutex);
+}
+
+void cancel_work_sync(struct work *w)
+{
+	pthread_exit(NULL);
+}
+
+void *run_work(void *arg)
+{
+	struct work *w;
+	int r;
+
+	w = (struct work *) arg;
+
+	mutex_lock(&w->mutex);
+
+	while (true) {
+		if (!w->ready)
+			w->ready = true;
+		r = pthread_cond_wait(&w->cond, &w->mutex.lock);
+		if (r != 0) {
+			printf("(%s)\n", strerror(r));
+			BUG_ON(r);
+		}
+		w->work_cb(w->arg);
+	}
+
+	mutex_unlock(&w->mutex);
+
+	pthread_exit(NULL);
+}
diff --git a/tools/linker-tables/lib/string.c b/tools/linker-tables/lib/string.c
new file mode 100644
index 000000000000..95631c742f1d
--- /dev/null
+++ b/tools/linker-tables/lib/string.c
@@ -0,0 +1,26 @@
+/*
+ *  linux/lib/string.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  Licensed under GPLv2 - taken from linux-next next-20160803
+ */
+
+#include <linux/kernel.h>
+
+/**
+ * memset - Fill a region of memory with the given value
+ * @s: Pointer to the start of the area.
+ * @c: The byte to fill the area with
+ * @count: The size of the area.
+ *
+ * Do not use memset() to access IO space, use memset_io() instead.
+ */
+void *memset(void *s, int c, size_t count)
+{
+	char *xs = s;
+
+	while (count--)
+		*xs++ = c;
+	return s;
+}
diff --git a/tools/linker-tables/main.c b/tools/linker-tables/main.c
new file mode 100644
index 000000000000..c0b1f4c95112
--- /dev/null
+++ b/tools/linker-tables/main.c
@@ -0,0 +1,20 @@
+#include <linux/string.h>
+#include <xen/xen.h>
+#include <asm/x86.h>
+#include <asm/bootparam.h>
+
+struct boot_params boot_params __attribute__((aligned(16)));
+
+int main(int arg, char *argc[])
+{
+	memset(&boot_params, 0, sizeof(struct boot_params));
+
+	if (arg <= 1)
+		startup_64();
+	else {
+		boot_params.hdr.hardware_subarch = X86_SUBARCH_XEN;
+		startup_xen();
+	}
+
+	return 0;
+}
diff --git a/tools/linker-tables/pci-quirks.c b/tools/linker-tables/pci-quirks.c
new file mode 100644
index 000000000000..2cd1116dd0fc
--- /dev/null
+++ b/tools/linker-tables/pci-quirks.c
@@ -0,0 +1,13 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <linux/pci.h>
+
+DEFINE_LINKTABLE_RO(struct pci_fixup, pci_fixup_early);
+
+static void foo_fixup(void) {
+	pr_info("foo_fixup\n");
+};
+
+LINKTABLE_RO(pci_fixup_early, 50) quirk_foo = {
+	.hook = foo_fixup,
+};
diff --git a/tools/linker-tables/pci.c b/tools/linker-tables/pci.c
new file mode 100644
index 000000000000..7a822c11d9f0
--- /dev/null
+++ b/tools/linker-tables/pci.c
@@ -0,0 +1,29 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <asm/bootparam.h>
+#include <linux/pci.h>
+
+DECLARE_LINKTABLE(struct pci_fixup, pci_fixup_early);
+
+void early_init_pci(void) {
+
+	const struct pci_fixup *fixup;
+	unsigned int tbl_size = LINKTABLE_SIZE(pci_fixup_early);
+
+	pr_info("Initializing pci ...\n");
+
+	pr_info("PCI fixup size: %d\n", tbl_size);
+
+	sleep(1);
+	pr_info("Demo: Using linktable_for_each\n");
+	linktable_for_each(fixup, pci_fixup_early)
+		fixup->hook();
+
+	pr_info("Demo: Using linktable_run_all\n");
+	linktable_run_all(pci_fixup_early, hook,);
+
+	pr_info("Completed initializing pci !\n");
+}
+
+x86_init_early_all(early_init_pci);
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* Re: [PATCH v6 00/14] linux: generalize sections, ranges and linker tables
  2017-01-09 14:58       ` Luis R. Rodriguez
  (?)
@ 2017-01-09 16:27         ` Andy Shevchenko
  -1 siblings, 0 replies; 480+ messages in thread
From: Andy Shevchenko @ 2017-01-09 16:27 UTC (permalink / raw)
  To: Luis R. Rodriguez, hpa, acme, tglx, mingo, jpoimboe, bp, npiggin,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt

On Mon, 2017-01-09 at 06:58 -0800, Luis R. Rodriguez wrote:
> This v6 addresses Andy Shevchenko's feedback from the v5 series [0] to
> use
> lowercase on a few of the tables.h macros. No other changes have been
> done to
> this series. As I had mentioned on the last cover-letter the v5 series
> had
> gone through a lot of testing both compile and run time, with the
> linktable
> test driver forced-enabled as a debug measure to try to capture errors
> as
> many architectures as possible:
> 
>     alpha      arc        arcv2       arm       arm64       blackfin  
>   c6x                                                                 
>                                     
>     cris       crisv32    frv         h8300     hexagon     i386      
>   ia64                                                                
>                                     
>     m32r       m68k       m68k_nommu  metag     microblaze  mips_22   
>   mips_24                                                             
>                                     
>     mips_25    mn10300    nios2       openrisc  parisc      parisc64  
>   powerpc                                                             
>                                     
>     s390       score      sh          sparc32   sparc64     tile      
>   um                                                                  
>                                     
>     unicore32  x86_64     xtensa                                      
>                                                                       
>                                     
> 
> The only architecture that was not tested was avr32 and that is
> because
> linux-next fails to compile on it. I'd like to greatly thank Guenter
> Roeck for
> his help with testing.

We have a real board here. I would try to check if you provide a git url
to your stuff.

I can confirm that breakage happened like in last couple of month.
v4.10-rc3 can't be compiled either.

> 
> The debug patch which force enables the test driver is not submitted
> for
> upstream inclusion but is kept as part of the public tree for those
> curious,
> its the last patch [1]. This tree is based on linux-next tag next-
> 20170109.
> 
> [0] https://lkml.kernel.org/r/20161222023811.21246-1-mcgrof@kernel.org
> [1] https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-
> next.git/log/?h 170109-linker-tables-v6

Series is fine to me

FWIW:
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> 
> Luis R. Rodriguez (14):
>   generic-sections: add section core helpers
>   xtensa: skip adding literal when SORT() is used
>   ranges.h: add helpers to build and identify Linux section ranges
>   tables.h: add linker table support
>   kbuild: enable option to force compile force-obj-y and force-lib-y
>   firmware/Makefile: force recompilation if makefile changes
>   firmware: port built-in section to linker table
>   jump_label: move guard #endif down where it belongs
>   jump_label: port __jump_table to linker tables
>   dynamic_debug: port to use linker tables
>   kprobes: move kprobe declarations to asm-generic/kprobes.h
>   kprobes: port .kprobes.text to section range
>   kprobes: port blacklist kprobes to linker table
>   lib: add linker tables test driver
> 
>  Documentation/index.rst                   |   1 +
>  Documentation/kbuild/makefiles.txt        |  36 ++
>  Documentation/sections/background.rst     | 105 ++++
>  Documentation/sections/conf.py            |   4 +
>  Documentation/sections/index.rst          |  19 +
>  Documentation/sections/linker-tables.rst  | 227 +++++++++
>  Documentation/sections/ranges.rst         |  74 +++
>  Documentation/sections/section-core.rst   | 153 ++++++
>  MAINTAINERS                               |  32 ++
>  arch/alpha/include/asm/Kbuild             |   4 +
>  arch/arc/include/asm/Kbuild               |   3 +
>  arch/arc/include/asm/kprobes.h            |   6 +-
>  arch/arc/kernel/vmlinux.lds.S             |   1 -
>  arch/arm/include/asm/Kbuild               |   3 +
>  arch/arm/include/asm/jump_label.h         |   6 +-
>  arch/arm/include/asm/kprobes.h            |   4 +
>  arch/arm/kernel/entry-armv.S              |   3 +-
>  arch/arm/kernel/vmlinux-xip.lds.S         |   1 -
>  arch/arm/kernel/vmlinux.lds.S             |   1 -
>  arch/arm/probes/decode.h                  |   1 +
>  arch/arm64/include/asm/Kbuild             |   3 +
>  arch/arm64/include/asm/jump_label.h       |   6 +-
>  arch/arm64/include/asm/kprobes.h          |   4 +
>  arch/arm64/kernel/armv8_deprecated.c      |   1 +
>  arch/arm64/kernel/insn.c                  |   1 +
>  arch/arm64/kernel/probes/decode-insn.h    |   2 +
>  arch/arm64/kernel/probes/kprobes.c        |   4 +-
>  arch/arm64/kernel/vmlinux.lds.S           |   1 -
>  arch/avr32/include/asm/Kbuild             |   3 +
>  arch/avr32/include/asm/kprobes.h          |   7 +-
>  arch/avr32/kernel/entry-avr32b.S          |  13 +-
>  arch/avr32/kernel/vmlinux.lds.S           |   1 -
>  arch/blackfin/include/asm/Kbuild          |   4 +
>  arch/blackfin/kernel/vmlinux.lds.S        |   1 -
>  arch/c6x/include/asm/Kbuild               |   3 +
>  arch/c6x/include/asm/tables.h             |  26 +
>  arch/c6x/kernel/vmlinux.lds.S             |   1 -
>  arch/cris/include/asm/Kbuild              |   4 +
>  arch/frv/include/asm/Kbuild               |   4 +
>  arch/h8300/include/asm/Kbuild             |   4 +
>  arch/hexagon/include/asm/Kbuild           |   4 +
>  arch/hexagon/kernel/vmlinux.lds.S         |   1 -
>  arch/ia64/include/asm/Kbuild              |   3 +
>  arch/ia64/include/asm/kprobes.h           |  12 +-
>  arch/ia64/kernel/jprobes.S                |   3 +-
>  arch/ia64/kernel/vmlinux.lds.S            |   1 -
>  arch/ia64/lib/flush.S                     |   6 +-
>  arch/m32r/include/asm/Kbuild              |   4 +
>  arch/m68k/include/asm/Kbuild              |   4 +
>  arch/metag/include/asm/Kbuild             |   4 +
>  arch/metag/kernel/vmlinux.lds.S           |   1 -
>  arch/microblaze/include/asm/Kbuild        |   4 +
>  arch/microblaze/kernel/vmlinux.lds.S      |   1 -
>  arch/mips/include/asm/Kbuild              |   3 +
>  arch/mips/include/asm/jump_label.h        |   6 +-
>  arch/mips/include/asm/kprobes.h           |   6 +-
>  arch/mips/kernel/vmlinux.lds.S            |   1 -
>  arch/mn10300/include/asm/Kbuild           |   3 +
>  arch/mn10300/include/asm/kprobes.h        |   7 +-
>  arch/mn10300/kernel/vmlinux.lds.S         |   1 -
>  arch/nios2/include/asm/Kbuild             |   4 +
>  arch/nios2/kernel/vmlinux.lds.S           |   1 -
>  arch/openrisc/include/asm/Kbuild          |   4 +
>  arch/openrisc/kernel/vmlinux.lds.S        |   1 -
>  arch/parisc/include/asm/Kbuild            |   4 +
>  arch/parisc/kernel/vmlinux.lds.S          |   1 -
>  arch/powerpc/include/asm/Kbuild           |   3 +
>  arch/powerpc/include/asm/jump_label.h     |   8 +-
>  arch/powerpc/include/asm/kprobes.h        |   3 +
>  arch/powerpc/include/asm/ppc_asm.h        |   3 +-
>  arch/powerpc/kernel/vmlinux.lds.S         |   3 +-
>  arch/s390/include/asm/Kbuild              |   3 +
>  arch/s390/include/asm/jump_label.h        |   6 +-
>  arch/s390/include/asm/kprobes.h           |   7 +-
>  arch/s390/kernel/entry.S                  |   5 +-
>  arch/s390/kernel/kprobes.c                |   6 +-
>  arch/s390/kernel/mcount.S                 |   3 +-
>  arch/s390/kernel/vmlinux.lds.S            |   1 -
>  arch/score/include/asm/Kbuild             |   4 +
>  arch/score/kernel/vmlinux.lds.S           |   1 -
>  arch/sh/include/asm/Kbuild                |   3 +
>  arch/sh/include/asm/kprobes.h             |   5 +-
>  arch/sh/kernel/vmlinux.lds.S              |   1 -
>  arch/sparc/include/asm/Kbuild             |   3 +
>  arch/sparc/include/asm/jump_label.h       |   6 +-
>  arch/sparc/include/asm/kprobes.h          |  10 +-
>  arch/sparc/kernel/vmlinux.lds.S           |   1 -
>  arch/sparc/mm/ultra.S                     |   3 +-
>  arch/tile/include/asm/Kbuild              |   3 +
>  arch/tile/include/asm/jump_label.h        |   5 +-
>  arch/tile/include/asm/kprobes.h           |   6 +-
>  arch/tile/kernel/vmlinux.lds.S            |   1 -
>  arch/um/include/asm/Kbuild                |   4 +
>  arch/unicore32/include/asm/Kbuild         |   3 +
>  arch/unicore32/include/asm/section-core.h |  19 +
>  arch/x86/include/asm/Kbuild               |   3 +
>  arch/x86/include/asm/asm.h                |   4 +-
>  arch/x86/include/asm/jump_label.h         |  10 +-
>  arch/x86/include/asm/kprobes.h            |   9 +-
>  arch/x86/kernel/cpu/microcode/core.c      |   8 +-
>  arch/x86/kernel/kprobes/core.c            |  11 +-
>  arch/x86/kernel/vmlinux.lds.S             |   1 -
>  arch/x86/tools/relocs.c                   |   4 +
>  arch/xtensa/include/asm/Kbuild            |   4 +
>  arch/xtensa/kernel/Makefile               |   8 +-
>  drivers/base/firmware_class.c             |  12 +-
>  firmware/Makefile                         |   6 +-
>  include/asm-generic/kprobes.h             |  26 +
>  include/asm-generic/ranges.h              |  93 ++++
>  include/asm-generic/section-core.h        | 348 +++++++++++++
>  include/asm-generic/sections.h            |   4 +-
>  include/asm-generic/tables.h              |  48 ++
>  include/asm-generic/vmlinux.lds.h         |  47 +-
>  include/linux/compiler.h                  |   8 -
>  include/linux/dynamic_debug.h             |   5 +-
>  include/linux/init.h                      |  89 +++-
>  include/linux/jump_label.h                |   8 +-
>  include/linux/kprobes.h                   |  24 +-
>  include/linux/ranges.h                    | 183 +++++++
>  include/linux/sections.h                  |  87 ++++
>  include/linux/tables.h                    | 683
> +++++++++++++++++++++++++
>  init/Kconfig                              |  22 +
>  kernel/jump_label.c                       |  17 +-
>  kernel/kprobes.c                          |  17 +-
>  lib/Kconfig.debug                         |   6 +
>  lib/Makefile                              |   1 +
>  lib/dynamic_debug.c                       |  13 +-
>  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 ++
>  scripts/Makefile.build                    |   7 +-
>  scripts/Makefile.clean                    |   2 +
>  scripts/Makefile.lib                      |  11 +
>  scripts/mod/modpost.c                     |   2 +-
>  scripts/module-common.lds                 |   2 +
>  scripts/recordmcount.c                    |   2 +-
>  scripts/recordmcount.pl                   |   2 +-
>  tools/objtool/special.c                   |   2 +-
>  143 files changed, 3632 insertions(+), 200 deletions(-)
>  create mode 100644 Documentation/sections/background.rst
>  create mode 100644 Documentation/sections/conf.py
>  create mode 100644 Documentation/sections/index.rst
>  create mode 100644 Documentation/sections/linker-tables.rst
>  create mode 100644 Documentation/sections/ranges.rst
>  create mode 100644 Documentation/sections/section-core.rst
>  create mode 100644 arch/c6x/include/asm/tables.h
>  create mode 100644 arch/unicore32/include/asm/section-core.h
>  create mode 100644 include/asm-generic/kprobes.h
>  create mode 100644 include/asm-generic/ranges.h
>  create mode 100644 include/asm-generic/section-core.h
>  create mode 100644 include/asm-generic/tables.h
>  create mode 100644 include/linux/ranges.h
>  create mode 100644 include/linux/sections.h
>  create mode 100644 include/linux/tables.h
>  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
> 

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v6 00/14] linux: generalize sections, ranges and linker tables
@ 2017-01-09 16:27         ` Andy Shevchenko
  0 siblings, 0 replies; 480+ messages in thread
From: Andy Shevchenko @ 2017-01-09 16:27 UTC (permalink / raw)
  To: Luis R. Rodriguez, hpa, acme, tglx, mingo, jpoimboe, bp, npiggin,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, jani.nikula,
	will.deacon, rusty, rostedt, ak

On Mon, 2017-01-09 at 06:58 -0800, Luis R. Rodriguez wrote:
> This v6 addresses Andy Shevchenko's feedback from the v5 series [0] to
> use
> lowercase on a few of the tables.h macros. No other changes have been
> done to
> this series. As I had mentioned on the last cover-letter the v5 series
> had
> gone through a lot of testing both compile and run time, with the
> linktable
> test driver forced-enabled as a debug measure to try to capture errors
> as
> many architectures as possible:
> 
>     alpha      arc        arcv2       arm       arm64       blackfin  
>   c6x                                                                 
>                                     
>     cris       crisv32    frv         h8300     hexagon     i386      
>   ia64                                                                
>                                     
>     m32r       m68k       m68k_nommu  metag     microblaze  mips_22   
>   mips_24                                                             
>                                     
>     mips_25    mn10300    nios2       openrisc  parisc      parisc64  
>   powerpc                                                             
>                                     
>     s390       score      sh          sparc32   sparc64     tile      
>   um                                                                  
>                                     
>     unicore32  x86_64     xtensa                                      
>                                                                       
>                                     
> 
> The only architecture that was not tested was avr32 and that is
> because
> linux-next fails to compile on it. I'd like to greatly thank Guenter
> Roeck for
> his help with testing.

We have a real board here. I would try to check if you provide a git url
to your stuff.

I can confirm that breakage happened like in last couple of month.
v4.10-rc3 can't be compiled either.

> 
> The debug patch which force enables the test driver is not submitted
> for
> upstream inclusion but is kept as part of the public tree for those
> curious,
> its the last patch [1]. This tree is based on linux-next tag next-
> 20170109.
> 
> [0] https://lkml.kernel.org/r/20161222023811.21246-1-mcgrof@kernel.org
> [1] https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-
> next.git/log/?h=20170109-linker-tables-v6

Series is fine to me

FWIW:
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> 
> Luis R. Rodriguez (14):
>   generic-sections: add section core helpers
>   xtensa: skip adding literal when SORT() is used
>   ranges.h: add helpers to build and identify Linux section ranges
>   tables.h: add linker table support
>   kbuild: enable option to force compile force-obj-y and force-lib-y
>   firmware/Makefile: force recompilation if makefile changes
>   firmware: port built-in section to linker table
>   jump_label: move guard #endif down where it belongs
>   jump_label: port __jump_table to linker tables
>   dynamic_debug: port to use linker tables
>   kprobes: move kprobe declarations to asm-generic/kprobes.h
>   kprobes: port .kprobes.text to section range
>   kprobes: port blacklist kprobes to linker table
>   lib: add linker tables test driver
> 
>  Documentation/index.rst                   |   1 +
>  Documentation/kbuild/makefiles.txt        |  36 ++
>  Documentation/sections/background.rst     | 105 ++++
>  Documentation/sections/conf.py            |   4 +
>  Documentation/sections/index.rst          |  19 +
>  Documentation/sections/linker-tables.rst  | 227 +++++++++
>  Documentation/sections/ranges.rst         |  74 +++
>  Documentation/sections/section-core.rst   | 153 ++++++
>  MAINTAINERS                               |  32 ++
>  arch/alpha/include/asm/Kbuild             |   4 +
>  arch/arc/include/asm/Kbuild               |   3 +
>  arch/arc/include/asm/kprobes.h            |   6 +-
>  arch/arc/kernel/vmlinux.lds.S             |   1 -
>  arch/arm/include/asm/Kbuild               |   3 +
>  arch/arm/include/asm/jump_label.h         |   6 +-
>  arch/arm/include/asm/kprobes.h            |   4 +
>  arch/arm/kernel/entry-armv.S              |   3 +-
>  arch/arm/kernel/vmlinux-xip.lds.S         |   1 -
>  arch/arm/kernel/vmlinux.lds.S             |   1 -
>  arch/arm/probes/decode.h                  |   1 +
>  arch/arm64/include/asm/Kbuild             |   3 +
>  arch/arm64/include/asm/jump_label.h       |   6 +-
>  arch/arm64/include/asm/kprobes.h          |   4 +
>  arch/arm64/kernel/armv8_deprecated.c      |   1 +
>  arch/arm64/kernel/insn.c                  |   1 +
>  arch/arm64/kernel/probes/decode-insn.h    |   2 +
>  arch/arm64/kernel/probes/kprobes.c        |   4 +-
>  arch/arm64/kernel/vmlinux.lds.S           |   1 -
>  arch/avr32/include/asm/Kbuild             |   3 +
>  arch/avr32/include/asm/kprobes.h          |   7 +-
>  arch/avr32/kernel/entry-avr32b.S          |  13 +-
>  arch/avr32/kernel/vmlinux.lds.S           |   1 -
>  arch/blackfin/include/asm/Kbuild          |   4 +
>  arch/blackfin/kernel/vmlinux.lds.S        |   1 -
>  arch/c6x/include/asm/Kbuild               |   3 +
>  arch/c6x/include/asm/tables.h             |  26 +
>  arch/c6x/kernel/vmlinux.lds.S             |   1 -
>  arch/cris/include/asm/Kbuild              |   4 +
>  arch/frv/include/asm/Kbuild               |   4 +
>  arch/h8300/include/asm/Kbuild             |   4 +
>  arch/hexagon/include/asm/Kbuild           |   4 +
>  arch/hexagon/kernel/vmlinux.lds.S         |   1 -
>  arch/ia64/include/asm/Kbuild              |   3 +
>  arch/ia64/include/asm/kprobes.h           |  12 +-
>  arch/ia64/kernel/jprobes.S                |   3 +-
>  arch/ia64/kernel/vmlinux.lds.S            |   1 -
>  arch/ia64/lib/flush.S                     |   6 +-
>  arch/m32r/include/asm/Kbuild              |   4 +
>  arch/m68k/include/asm/Kbuild              |   4 +
>  arch/metag/include/asm/Kbuild             |   4 +
>  arch/metag/kernel/vmlinux.lds.S           |   1 -
>  arch/microblaze/include/asm/Kbuild        |   4 +
>  arch/microblaze/kernel/vmlinux.lds.S      |   1 -
>  arch/mips/include/asm/Kbuild              |   3 +
>  arch/mips/include/asm/jump_label.h        |   6 +-
>  arch/mips/include/asm/kprobes.h           |   6 +-
>  arch/mips/kernel/vmlinux.lds.S            |   1 -
>  arch/mn10300/include/asm/Kbuild           |   3 +
>  arch/mn10300/include/asm/kprobes.h        |   7 +-
>  arch/mn10300/kernel/vmlinux.lds.S         |   1 -
>  arch/nios2/include/asm/Kbuild             |   4 +
>  arch/nios2/kernel/vmlinux.lds.S           |   1 -
>  arch/openrisc/include/asm/Kbuild          |   4 +
>  arch/openrisc/kernel/vmlinux.lds.S        |   1 -
>  arch/parisc/include/asm/Kbuild            |   4 +
>  arch/parisc/kernel/vmlinux.lds.S          |   1 -
>  arch/powerpc/include/asm/Kbuild           |   3 +
>  arch/powerpc/include/asm/jump_label.h     |   8 +-
>  arch/powerpc/include/asm/kprobes.h        |   3 +
>  arch/powerpc/include/asm/ppc_asm.h        |   3 +-
>  arch/powerpc/kernel/vmlinux.lds.S         |   3 +-
>  arch/s390/include/asm/Kbuild              |   3 +
>  arch/s390/include/asm/jump_label.h        |   6 +-
>  arch/s390/include/asm/kprobes.h           |   7 +-
>  arch/s390/kernel/entry.S                  |   5 +-
>  arch/s390/kernel/kprobes.c                |   6 +-
>  arch/s390/kernel/mcount.S                 |   3 +-
>  arch/s390/kernel/vmlinux.lds.S            |   1 -
>  arch/score/include/asm/Kbuild             |   4 +
>  arch/score/kernel/vmlinux.lds.S           |   1 -
>  arch/sh/include/asm/Kbuild                |   3 +
>  arch/sh/include/asm/kprobes.h             |   5 +-
>  arch/sh/kernel/vmlinux.lds.S              |   1 -
>  arch/sparc/include/asm/Kbuild             |   3 +
>  arch/sparc/include/asm/jump_label.h       |   6 +-
>  arch/sparc/include/asm/kprobes.h          |  10 +-
>  arch/sparc/kernel/vmlinux.lds.S           |   1 -
>  arch/sparc/mm/ultra.S                     |   3 +-
>  arch/tile/include/asm/Kbuild              |   3 +
>  arch/tile/include/asm/jump_label.h        |   5 +-
>  arch/tile/include/asm/kprobes.h           |   6 +-
>  arch/tile/kernel/vmlinux.lds.S            |   1 -
>  arch/um/include/asm/Kbuild                |   4 +
>  arch/unicore32/include/asm/Kbuild         |   3 +
>  arch/unicore32/include/asm/section-core.h |  19 +
>  arch/x86/include/asm/Kbuild               |   3 +
>  arch/x86/include/asm/asm.h                |   4 +-
>  arch/x86/include/asm/jump_label.h         |  10 +-
>  arch/x86/include/asm/kprobes.h            |   9 +-
>  arch/x86/kernel/cpu/microcode/core.c      |   8 +-
>  arch/x86/kernel/kprobes/core.c            |  11 +-
>  arch/x86/kernel/vmlinux.lds.S             |   1 -
>  arch/x86/tools/relocs.c                   |   4 +
>  arch/xtensa/include/asm/Kbuild            |   4 +
>  arch/xtensa/kernel/Makefile               |   8 +-
>  drivers/base/firmware_class.c             |  12 +-
>  firmware/Makefile                         |   6 +-
>  include/asm-generic/kprobes.h             |  26 +
>  include/asm-generic/ranges.h              |  93 ++++
>  include/asm-generic/section-core.h        | 348 +++++++++++++
>  include/asm-generic/sections.h            |   4 +-
>  include/asm-generic/tables.h              |  48 ++
>  include/asm-generic/vmlinux.lds.h         |  47 +-
>  include/linux/compiler.h                  |   8 -
>  include/linux/dynamic_debug.h             |   5 +-
>  include/linux/init.h                      |  89 +++-
>  include/linux/jump_label.h                |   8 +-
>  include/linux/kprobes.h                   |  24 +-
>  include/linux/ranges.h                    | 183 +++++++
>  include/linux/sections.h                  |  87 ++++
>  include/linux/tables.h                    | 683
> +++++++++++++++++++++++++
>  init/Kconfig                              |  22 +
>  kernel/jump_label.c                       |  17 +-
>  kernel/kprobes.c                          |  17 +-
>  lib/Kconfig.debug                         |   6 +
>  lib/Makefile                              |   1 +
>  lib/dynamic_debug.c                       |  13 +-
>  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 ++
>  scripts/Makefile.build                    |   7 +-
>  scripts/Makefile.clean                    |   2 +
>  scripts/Makefile.lib                      |  11 +
>  scripts/mod/modpost.c                     |   2 +-
>  scripts/module-common.lds                 |   2 +
>  scripts/recordmcount.c                    |   2 +-
>  scripts/recordmcount.pl                   |   2 +-
>  tools/objtool/special.c                   |   2 +-
>  143 files changed, 3632 insertions(+), 200 deletions(-)
>  create mode 100644 Documentation/sections/background.rst
>  create mode 100644 Documentation/sections/conf.py
>  create mode 100644 Documentation/sections/index.rst
>  create mode 100644 Documentation/sections/linker-tables.rst
>  create mode 100644 Documentation/sections/ranges.rst
>  create mode 100644 Documentation/sections/section-core.rst
>  create mode 100644 arch/c6x/include/asm/tables.h
>  create mode 100644 arch/unicore32/include/asm/section-core.h
>  create mode 100644 include/asm-generic/kprobes.h
>  create mode 100644 include/asm-generic/ranges.h
>  create mode 100644 include/asm-generic/section-core.h
>  create mode 100644 include/asm-generic/tables.h
>  create mode 100644 include/linux/ranges.h
>  create mode 100644 include/linux/sections.h
>  create mode 100644 include/linux/tables.h
>  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
> 

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v6 00/14] linux: generalize sections, ranges and linker tables
@ 2017-01-09 16:27         ` Andy Shevchenko
  0 siblings, 0 replies; 480+ messages in thread
From: Andy Shevchenko @ 2017-01-09 16:27 UTC (permalink / raw)
  To: Luis R. Rodriguez, hpa, acme, tglx, mingo, jpoimboe, bp, npiggin,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley

On Mon, 2017-01-09 at 06:58 -0800, Luis R. Rodriguez wrote:
> This v6 addresses Andy Shevchenko's feedback from the v5 series [0] to
> use
> lowercase on a few of the tables.h macros. No other changes have been
> done to
> this series. As I had mentioned on the last cover-letter the v5 series
> had
> gone through a lot of testing both compile and run time, with the
> linktable
> test driver forced-enabled as a debug measure to try to capture errors
> as
> many architectures as possible:
> 
>     alpha      arc        arcv2       arm       arm64       blackfin  
>   c6x                                                                 
>                                     
>     cris       crisv32    frv         h8300     hexagon     i386      
>   ia64                                                                
>                                     
>     m32r       m68k       m68k_nommu  metag     microblaze  mips_22   
>   mips_24                                                             
>                                     
>     mips_25    mn10300    nios2       openrisc  parisc      parisc64  
>   powerpc                                                             
>                                     
>     s390       score      sh          sparc32   sparc64     tile      
>   um                                                                  
>                                     
>     unicore32  x86_64     xtensa                                      
>                                                                       
>                                     
> 
> The only architecture that was not tested was avr32 and that is
> because
> linux-next fails to compile on it. I'd like to greatly thank Guenter
> Roeck for
> his help with testing.

We have a real board here. I would try to check if you provide a git url
to your stuff.

I can confirm that breakage happened like in last couple of month.
v4.10-rc3 can't be compiled either.

> 
> The debug patch which force enables the test driver is not submitted
> for
> upstream inclusion but is kept as part of the public tree for those
> curious,
> its the last patch [1]. This tree is based on linux-next tag next-
> 20170109.
> 
> [0] https://lkml.kernel.org/r/20161222023811.21246-1-mcgrof@kernel.org
> [1] https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-
> next.git/log/?h=20170109-linker-tables-v6

Series is fine to me

FWIW:
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> 
> Luis R. Rodriguez (14):
>   generic-sections: add section core helpers
>   xtensa: skip adding literal when SORT() is used
>   ranges.h: add helpers to build and identify Linux section ranges
>   tables.h: add linker table support
>   kbuild: enable option to force compile force-obj-y and force-lib-y
>   firmware/Makefile: force recompilation if makefile changes
>   firmware: port built-in section to linker table
>   jump_label: move guard #endif down where it belongs
>   jump_label: port __jump_table to linker tables
>   dynamic_debug: port to use linker tables
>   kprobes: move kprobe declarations to asm-generic/kprobes.h
>   kprobes: port .kprobes.text to section range
>   kprobes: port blacklist kprobes to linker table
>   lib: add linker tables test driver
> 
>  Documentation/index.rst                   |   1 +
>  Documentation/kbuild/makefiles.txt        |  36 ++
>  Documentation/sections/background.rst     | 105 ++++
>  Documentation/sections/conf.py            |   4 +
>  Documentation/sections/index.rst          |  19 +
>  Documentation/sections/linker-tables.rst  | 227 +++++++++
>  Documentation/sections/ranges.rst         |  74 +++
>  Documentation/sections/section-core.rst   | 153 ++++++
>  MAINTAINERS                               |  32 ++
>  arch/alpha/include/asm/Kbuild             |   4 +
>  arch/arc/include/asm/Kbuild               |   3 +
>  arch/arc/include/asm/kprobes.h            |   6 +-
>  arch/arc/kernel/vmlinux.lds.S             |   1 -
>  arch/arm/include/asm/Kbuild               |   3 +
>  arch/arm/include/asm/jump_label.h         |   6 +-
>  arch/arm/include/asm/kprobes.h            |   4 +
>  arch/arm/kernel/entry-armv.S              |   3 +-
>  arch/arm/kernel/vmlinux-xip.lds.S         |   1 -
>  arch/arm/kernel/vmlinux.lds.S             |   1 -
>  arch/arm/probes/decode.h                  |   1 +
>  arch/arm64/include/asm/Kbuild             |   3 +
>  arch/arm64/include/asm/jump_label.h       |   6 +-
>  arch/arm64/include/asm/kprobes.h          |   4 +
>  arch/arm64/kernel/armv8_deprecated.c      |   1 +
>  arch/arm64/kernel/insn.c                  |   1 +
>  arch/arm64/kernel/probes/decode-insn.h    |   2 +
>  arch/arm64/kernel/probes/kprobes.c        |   4 +-
>  arch/arm64/kernel/vmlinux.lds.S           |   1 -
>  arch/avr32/include/asm/Kbuild             |   3 +
>  arch/avr32/include/asm/kprobes.h          |   7 +-
>  arch/avr32/kernel/entry-avr32b.S          |  13 +-
>  arch/avr32/kernel/vmlinux.lds.S           |   1 -
>  arch/blackfin/include/asm/Kbuild          |   4 +
>  arch/blackfin/kernel/vmlinux.lds.S        |   1 -
>  arch/c6x/include/asm/Kbuild               |   3 +
>  arch/c6x/include/asm/tables.h             |  26 +
>  arch/c6x/kernel/vmlinux.lds.S             |   1 -
>  arch/cris/include/asm/Kbuild              |   4 +
>  arch/frv/include/asm/Kbuild               |   4 +
>  arch/h8300/include/asm/Kbuild             |   4 +
>  arch/hexagon/include/asm/Kbuild           |   4 +
>  arch/hexagon/kernel/vmlinux.lds.S         |   1 -
>  arch/ia64/include/asm/Kbuild              |   3 +
>  arch/ia64/include/asm/kprobes.h           |  12 +-
>  arch/ia64/kernel/jprobes.S                |   3 +-
>  arch/ia64/kernel/vmlinux.lds.S            |   1 -
>  arch/ia64/lib/flush.S                     |   6 +-
>  arch/m32r/include/asm/Kbuild              |   4 +
>  arch/m68k/include/asm/Kbuild              |   4 +
>  arch/metag/include/asm/Kbuild             |   4 +
>  arch/metag/kernel/vmlinux.lds.S           |   1 -
>  arch/microblaze/include/asm/Kbuild        |   4 +
>  arch/microblaze/kernel/vmlinux.lds.S      |   1 -
>  arch/mips/include/asm/Kbuild              |   3 +
>  arch/mips/include/asm/jump_label.h        |   6 +-
>  arch/mips/include/asm/kprobes.h           |   6 +-
>  arch/mips/kernel/vmlinux.lds.S            |   1 -
>  arch/mn10300/include/asm/Kbuild           |   3 +
>  arch/mn10300/include/asm/kprobes.h        |   7 +-
>  arch/mn10300/kernel/vmlinux.lds.S         |   1 -
>  arch/nios2/include/asm/Kbuild             |   4 +
>  arch/nios2/kernel/vmlinux.lds.S           |   1 -
>  arch/openrisc/include/asm/Kbuild          |   4 +
>  arch/openrisc/kernel/vmlinux.lds.S        |   1 -
>  arch/parisc/include/asm/Kbuild            |   4 +
>  arch/parisc/kernel/vmlinux.lds.S          |   1 -
>  arch/powerpc/include/asm/Kbuild           |   3 +
>  arch/powerpc/include/asm/jump_label.h     |   8 +-
>  arch/powerpc/include/asm/kprobes.h        |   3 +
>  arch/powerpc/include/asm/ppc_asm.h        |   3 +-
>  arch/powerpc/kernel/vmlinux.lds.S         |   3 +-
>  arch/s390/include/asm/Kbuild              |   3 +
>  arch/s390/include/asm/jump_label.h        |   6 +-
>  arch/s390/include/asm/kprobes.h           |   7 +-
>  arch/s390/kernel/entry.S                  |   5 +-
>  arch/s390/kernel/kprobes.c                |   6 +-
>  arch/s390/kernel/mcount.S                 |   3 +-
>  arch/s390/kernel/vmlinux.lds.S            |   1 -
>  arch/score/include/asm/Kbuild             |   4 +
>  arch/score/kernel/vmlinux.lds.S           |   1 -
>  arch/sh/include/asm/Kbuild                |   3 +
>  arch/sh/include/asm/kprobes.h             |   5 +-
>  arch/sh/kernel/vmlinux.lds.S              |   1 -
>  arch/sparc/include/asm/Kbuild             |   3 +
>  arch/sparc/include/asm/jump_label.h       |   6 +-
>  arch/sparc/include/asm/kprobes.h          |  10 +-
>  arch/sparc/kernel/vmlinux.lds.S           |   1 -
>  arch/sparc/mm/ultra.S                     |   3 +-
>  arch/tile/include/asm/Kbuild              |   3 +
>  arch/tile/include/asm/jump_label.h        |   5 +-
>  arch/tile/include/asm/kprobes.h           |   6 +-
>  arch/tile/kernel/vmlinux.lds.S            |   1 -
>  arch/um/include/asm/Kbuild                |   4 +
>  arch/unicore32/include/asm/Kbuild         |   3 +
>  arch/unicore32/include/asm/section-core.h |  19 +
>  arch/x86/include/asm/Kbuild               |   3 +
>  arch/x86/include/asm/asm.h                |   4 +-
>  arch/x86/include/asm/jump_label.h         |  10 +-
>  arch/x86/include/asm/kprobes.h            |   9 +-
>  arch/x86/kernel/cpu/microcode/core.c      |   8 +-
>  arch/x86/kernel/kprobes/core.c            |  11 +-
>  arch/x86/kernel/vmlinux.lds.S             |   1 -
>  arch/x86/tools/relocs.c                   |   4 +
>  arch/xtensa/include/asm/Kbuild            |   4 +
>  arch/xtensa/kernel/Makefile               |   8 +-
>  drivers/base/firmware_class.c             |  12 +-
>  firmware/Makefile                         |   6 +-
>  include/asm-generic/kprobes.h             |  26 +
>  include/asm-generic/ranges.h              |  93 ++++
>  include/asm-generic/section-core.h        | 348 +++++++++++++
>  include/asm-generic/sections.h            |   4 +-
>  include/asm-generic/tables.h              |  48 ++
>  include/asm-generic/vmlinux.lds.h         |  47 +-
>  include/linux/compiler.h                  |   8 -
>  include/linux/dynamic_debug.h             |   5 +-
>  include/linux/init.h                      |  89 +++-
>  include/linux/jump_label.h                |   8 +-
>  include/linux/kprobes.h                   |  24 +-
>  include/linux/ranges.h                    | 183 +++++++
>  include/linux/sections.h                  |  87 ++++
>  include/linux/tables.h                    | 683
> +++++++++++++++++++++++++
>  init/Kconfig                              |  22 +
>  kernel/jump_label.c                       |  17 +-
>  kernel/kprobes.c                          |  17 +-
>  lib/Kconfig.debug                         |   6 +
>  lib/Makefile                              |   1 +
>  lib/dynamic_debug.c                       |  13 +-
>  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 ++
>  scripts/Makefile.build                    |   7 +-
>  scripts/Makefile.clean                    |   2 +
>  scripts/Makefile.lib                      |  11 +
>  scripts/mod/modpost.c                     |   2 +-
>  scripts/module-common.lds                 |   2 +
>  scripts/recordmcount.c                    |   2 +-
>  scripts/recordmcount.pl                   |   2 +-
>  tools/objtool/special.c                   |   2 +-
>  143 files changed, 3632 insertions(+), 200 deletions(-)
>  create mode 100644 Documentation/sections/background.rst
>  create mode 100644 Documentation/sections/conf.py
>  create mode 100644 Documentation/sections/index.rst
>  create mode 100644 Documentation/sections/linker-tables.rst
>  create mode 100644 Documentation/sections/ranges.rst
>  create mode 100644 Documentation/sections/section-core.rst
>  create mode 100644 arch/c6x/include/asm/tables.h
>  create mode 100644 arch/unicore32/include/asm/section-core.h
>  create mode 100644 include/asm-generic/kprobes.h
>  create mode 100644 include/asm-generic/ranges.h
>  create mode 100644 include/asm-generic/section-core.h
>  create mode 100644 include/asm-generic/tables.h
>  create mode 100644 include/linux/ranges.h
>  create mode 100644 include/linux/sections.h
>  create mode 100644 include/linux/tables.h
>  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
> 

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v6 00/14] linux: generalize sections, ranges and linker tables
  2017-01-09 16:27         ` Andy Shevchenko
  (?)
  (?)
@ 2017-01-09 16:36         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 16:36 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: One Thousand Gnomes, dalias, linux-ia64, Jiri Kosina,
	Benjamin Herrenschmidt, Ming Lei, Heiko Carstens,
	platform-driver-x86, James Bottomley, Paul Gortmaker,
	Paul Mackerras, Michael Ellerman, H. Peter Anvin,
	Masami Hiramatsu, Wang Nan, Mauro Carvalho Chehab, linux-arch,
	markus.heiser, sparclinux, xen-devel, Russell King, linux-sh,
	Will Deacon

On Mon, Jan 9, 2017 at 10:27 AM, Andy Shevchenko
<andriy.shevchenko@linux.intel.com> wrote:
> On Mon, 2017-01-09 at 06:58 -0800, Luis R. Rodriguez wrote:
>> The only architecture that was not tested was avr32 and that is
>> because linux-next fails to compile on it. I'd like to greatly thank Guenter
>> Roeck for his help with testing.
>
> We have a real board here. I would try to check if you provide a git url
> to your stuff.

I provided the git URL below, I will highlight it below again.

> I can confirm that breakage happened like in last couple of month.
> v4.10-rc3 can't be compiled either.

You mean an avr32 board ?

>> The debug patch which force enables the test driver is not submitted
>> for
>> upstream inclusion but is kept as part of the public tree for those
>> curious,
>> its the last patch [1]. This tree is based on linux-next tag next-
>> 20170109.
>>
>> [0] https://lkml.kernel.org/r/20161222023811.21246-1-mcgrof@kernel.org
>> [1] https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-
>> next.git/log/?h=20170109-linker-tables-v6

Here is the git tree, note last patch is a debug patch which was not
submitted, it force enables the debug test linktable patch, you do
want that for your testing though.

> Series is fine to me
>
> FWIW:
> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

Great thanks for the review!

  Luis

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v6 00/14] linux: generalize sections, ranges and linker tables
  2017-01-09 16:27         ` Andy Shevchenko
                           ` (2 preceding siblings ...)
  (?)
@ 2017-01-09 17:12         ` Shevchenko, Andriy
  2017-01-09 17:16           ` Luis R. Rodriguez
  2017-01-09 18:29             ` Andy Shevchenko
  -1 siblings, 2 replies; 480+ messages in thread
From: Shevchenko, Andriy @ 2017-01-09 17:12 UTC (permalink / raw)
  To: dalias, masami.hiramatsu.pt, tglx, jbaron, heiko.carstens,
	jpoimboe, realmz6, hpa, acme, mingo, ananth, mcgrof, bp,
	mhiramat, Keshavamurthy, Anil S, davem, npiggin, linux
  Cc: xen-devel, gnomes, x86, linux-ia64, linux-sh, catalin.marinas,
	ming.lei, linux, platform-driver-x86, James.Bottomley, jcmvbkbc,
	paulus, sparclinux, jolsa, linux-arch, markus.heiser@darmarit.de

On Mon, 2017-01-09 at 18:27 +0200, Andy Shevchenko wrote:
> On Mon, 2017-01-09 at 06:58 -0800, Luis R. Rodriguez wrote:

> > The only architecture that was not tested was avr32 and that is
> > because
> > linux-next fails to compile on it. I'd like to greatly thank Guenter
> > Roeck for
> > his help with testing.
> 
> We have a real board here. I would try to check if you provide a git
> url
> to your stuff.
> 
> I can confirm that breakage happened like in last couple of month.
> v4.10-rc3 can't be compiled either.

The culprit commit is

commit 3a0af8fd61f90920f6fa04e4f1e9a6a73c1b4fd2
Author: Thomas Graf <tgraf@suug.ch>
Date:   Wed Nov 30 17:10:10 2016 +0100

    bpf: BPF for lightweight tunnel infrastructure

-- 
Andy Shevchenko <andriy.shevchenko@intel.com>
Intel Finland Oy - BIC 0357606-4 - Westendinkatu 7, 02160 Espoo
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v6 00/14] linux: generalize sections, ranges and linker tables
  2017-01-09 17:12         ` Shevchenko, Andriy
@ 2017-01-09 17:16           ` Luis R. Rodriguez
  2017-01-09 18:29             ` Andy Shevchenko
  1 sibling, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-09 17:16 UTC (permalink / raw)
  To: Shevchenko, Andriy, Thomas Graf
  Cc: xen-devel, gnomes, dalias, linux-ia64, wangnan0, catalin.marinas,
	ming.lei, heiko.carstens, x86, platform-driver-x86,
	James.Bottomley@HansenPartnership.com, jcmvbkbc, paulus, hpa,
	masami.hiramatsu.pt, luto, mchehab@osg.samsung.com

On Mon, Jan 9, 2017 at 11:12 AM, Shevchenko, Andriy
<andriy.shevchenko@intel.com> wrote:
> On Mon, 2017-01-09 at 18:27 +0200, Andy Shevchenko wrote:
>> On Mon, 2017-01-09 at 06:58 -0800, Luis R. Rodriguez wrote:
>
>> > The only architecture that was not tested was avr32 and that is
>> > because
>> > linux-next fails to compile on it. I'd like to greatly thank Guenter
>> > Roeck for
>> > his help with testing.
>>
>> We have a real board here. I would try to check if you provide a git
>> url
>> to your stuff.
>>
>> I can confirm that breakage happened like in last couple of month.
>> v4.10-rc3 can't be compiled either.
>
> The culprit commit is
>
> commit 3a0af8fd61f90920f6fa04e4f1e9a6a73c1b4fd2
> Author: Thomas Graf <tgraf@suug.ch>
> Date:   Wed Nov 30 17:10:10 2016 +0100
>
>     bpf: BPF for lightweight tunnel infrastructure

OK I guess you folks can take it on in a separate thread, please feel
free to Cc me.

  Luis

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v6 00/14] linux: generalize sections, ranges and linker tables
  2017-01-09 17:12         ` Shevchenko, Andriy
  2017-01-09 17:16           ` Luis R. Rodriguez
@ 2017-01-09 18:29             ` Andy Shevchenko
  1 sibling, 0 replies; 480+ messages in thread
From: Andy Shevchenko @ 2017-01-09 18:29 UTC (permalink / raw)
  To: Luis R. Rodriguez, hpa, acme, tglx, mingo, jpoimboe, bp, npiggin,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm

On Mon, 2017-01-09 at 19:12 +0200, Andy Shevchenko wrote:
> On Mon, 2017-01-09 at 18:27 +0200, Andy Shevchenko wrote:
> > On Mon, 2017-01-09 at 06:58 -0800, Luis R. Rodriguez wrote:
> > > The only architecture that was not tested was avr32 and that is
> > > because
> > > linux-next fails to compile on it. I'd like to greatly thank
> > > Guenter
> > > Roeck for
> > > his help with testing.
> > 
> > We have a real board here. I would try to check if you provide a git
> > url
> > to your stuff.
> > 
> > I can confirm that breakage happened like in last couple of month.
> > v4.10-rc3 can't be compiled either.
> 
> The culprit commit is
> 
> commit 3a0af8fd61f90920f6fa04e4f1e9a6a73c1b4fd2
> Author: Thomas Graf <tgraf@suug.ch>
> Date:   Wed Nov 30 17:10:10 2016 +0100
> 
>     bpf: BPF for lightweight tunnel infrastructure
> 

This makes modules closer to each other, so,
net/socket.c:348: relocation truncated to fit: R_AVR32_11H_PCREL against
`.text'+2930

But still the module is too big for AVR to do some jumps.

Here I stop investigating it. I had been proposed to get rid of avr32
completely, burden to support is just increasing (no Buildroot support,
no Gcc support, what else do we need?) for no value.

diff --git a/net/core/Makefile b/net/core/Makefile
index f6761b6e3b29..91b7d27bf2c6 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -2,13 +2,13 @@
 # Makefile for the Linux networking core.
 #
 
-obj-y := sock.o request_sock.o skbuff.o datagram.o stream.o scm.o \
+obj-y := filter.o sock.o request_sock.o skbuff.o datagram.o stream.o
scm.o \
         gen_stats.o gen_estimator.o net_namespace.o secure_seq.o
flow_dissector.o
 
 obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
 
 obj-y               += dev.o ethtool.o dev_addr_lists.o dst.o
netevent.o \
-                       neighbour.o rtnetlink.o utils.o link_watch.o
filter.o \
+                       neighbour.o rtnetlink.o utils.o link_watch.o \
                        sock_diag.o dev_ioctl.o tso.o sock_reuseport.o
 
 obj-$(CONFIG_XFRM) += flow.o
-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* Re: [PATCH v6 00/14] linux: generalize sections, ranges and linker tables
@ 2017-01-09 18:29             ` Andy Shevchenko
  0 siblings, 0 replies; 480+ messages in thread
From: Andy Shevchenko @ 2017-01-09 18:29 UTC (permalink / raw)
  To: Luis R. Rodriguez, hpa, acme, tglx, mingo, jpoimboe, bp, npiggin,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm

On Mon, 2017-01-09 at 19:12 +0200, Andy Shevchenko wrote:
> On Mon, 2017-01-09 at 18:27 +0200, Andy Shevchenko wrote:
> > On Mon, 2017-01-09 at 06:58 -0800, Luis R. Rodriguez wrote:
> > > The only architecture that was not tested was avr32 and that is
> > > because
> > > linux-next fails to compile on it. I'd like to greatly thank
> > > Guenter
> > > Roeck for
> > > his help with testing.
> > 
> > We have a real board here. I would try to check if you provide a git
> > url
> > to your stuff.
> > 
> > I can confirm that breakage happened like in last couple of month.
> > v4.10-rc3 can't be compiled either.
> 
> The culprit commit is
> 
> commit 3a0af8fd61f90920f6fa04e4f1e9a6a73c1b4fd2
> Author: Thomas Graf <tgraf@suug.ch>
> Date:   Wed Nov 30 17:10:10 2016 +0100
> 
>     bpf: BPF for lightweight tunnel infrastructure
> 

This makes modules closer to each other, so,
net/socket.c:348: relocation truncated to fit: R_AVR32_11H_PCREL against
`.text'+2930

But still the module is too big for AVR to do some jumps.

Here I stop investigating it. I had been proposed to get rid of avr32
completely, burden to support is just increasing (no Buildroot support,
no Gcc support, what else do we need?) for no value.

diff --git a/net/core/Makefile b/net/core/Makefile
index f6761b6e3b29..91b7d27bf2c6 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -2,13 +2,13 @@
 # Makefile for the Linux networking core.
 #
 
-obj-y := sock.o request_sock.o skbuff.o datagram.o stream.o scm.o \
+obj-y := filter.o sock.o request_sock.o skbuff.o datagram.o stream.o
scm.o \
         gen_stats.o gen_estimator.o net_namespace.o secure_seq.o
flow_dissector.o
 
 obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
 
 obj-y               += dev.o ethtool.o dev_addr_lists.o dst.o
netevent.o \
-                       neighbour.o rtnetlink.o utils.o link_watch.o
filter.o \
+                       neighbour.o rtnetlink.o utils.o link_watch.o \
                        sock_diag.o dev_ioctl.o tso.o sock_reuseport.o
 
 obj-$(CONFIG_XFRM) += flow.o
-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* Re: [PATCH v6 00/14] linux: generalize sections, ranges and linker tables
@ 2017-01-09 18:29             ` Andy Shevchenko
  0 siblings, 0 replies; 480+ messages in thread
From: Andy Shevchenko @ 2017-01-09 18:29 UTC (permalink / raw)
  To: Luis R. Rodriguez, hpa, acme, tglx, mingo, jpoimboe, bp, npiggin,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley

On Mon, 2017-01-09 at 19:12 +0200, Andy Shevchenko wrote:
> On Mon, 2017-01-09 at 18:27 +0200, Andy Shevchenko wrote:
> > On Mon, 2017-01-09 at 06:58 -0800, Luis R. Rodriguez wrote:
> > > The only architecture that was not tested was avr32 and that is
> > > because
> > > linux-next fails to compile on it. I'd like to greatly thank
> > > Guenter
> > > Roeck for
> > > his help with testing.
> > 
> > We have a real board here. I would try to check if you provide a git
> > url
> > to your stuff.
> > 
> > I can confirm that breakage happened like in last couple of month.
> > v4.10-rc3 can't be compiled either.
> 
> The culprit commit is
> 
> commit 3a0af8fd61f90920f6fa04e4f1e9a6a73c1b4fd2
> Author: Thomas Graf <tgraf@suug.ch>
> Date:   Wed Nov 30 17:10:10 2016 +0100
> 
>     bpf: BPF for lightweight tunnel infrastructure
> 

This makes modules closer to each other, so,
net/socket.c:348: relocation truncated to fit: R_AVR32_11H_PCREL against
`.text'+2930

But still the module is too big for AVR to do some jumps.

Here I stop investigating it. I had been proposed to get rid of avr32
completely, burden to support is just increasing (no Buildroot support,
no Gcc support, what else do we need?) for no value.

diff --git a/net/core/Makefile b/net/core/Makefile
index f6761b6e3b29..91b7d27bf2c6 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -2,13 +2,13 @@
 # Makefile for the Linux networking core.
 #
 
-obj-y := sock.o request_sock.o skbuff.o datagram.o stream.o scm.o \
+obj-y := filter.o sock.o request_sock.o skbuff.o datagram.o stream.o
scm.o \
         gen_stats.o gen_estimator.o net_namespace.o secure_seq.o
flow_dissector.o
 
 obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
 
 obj-y               += dev.o ethtool.o dev_addr_lists.o dst.o
netevent.o \
-                       neighbour.o rtnetlink.o utils.o link_watch.o
filter.o \
+                       neighbour.o rtnetlink.o utils.o link_watch.o \
                        sock_diag.o dev_ioctl.o tso.o sock_reuseport.o
 
 obj-$(CONFIG_XFRM) += flow.o
-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* Re: [PATCH v6 00/14] linux: generalize sections, ranges and linker tables
  2017-01-09 18:29             ` Andy Shevchenko
  (?)
@ 2017-01-11 14:37               ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-11 14:37 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Luis R. Rodriguez, hpa, acme, tglx, mingo, jpoimboe, bp, npiggin,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, gregkh, rusty, gnomes, alan, dwmw2,
	arnd, ming.lei, linux-arch, benh, pebolle, fontana, david.vr

On Mon, Jan 09, 2017 at 08:29:15PM +0200, Andy Shevchenko wrote:
> On Mon, 2017-01-09 at 19:12 +0200, Andy Shevchenko wrote:
> > On Mon, 2017-01-09 at 18:27 +0200, Andy Shevchenko wrote:
> > > On Mon, 2017-01-09 at 06:58 -0800, Luis R. Rodriguez wrote:
> > > > The only architecture that was not tested was avr32 and that is
> > > > because
> > > > linux-next fails to compile on it. I'd like to greatly thank
> > > > Guenter
> > > > Roeck for
> > > > his help with testing.
> > > 
> > > We have a real board here. I would try to check if you provide a git
> > > url
> > > to your stuff.
> > > 
> > > I can confirm that breakage happened like in last couple of month.
> > > v4.10-rc3 can't be compiled either.
> > 
> > The culprit commit is
> > 
> > commit 3a0af8fd61f90920f6fa04e4f1e9a6a73c1b4fd2
> > Author: Thomas Graf <tgraf@suug.ch>
> > Date:   Wed Nov 30 17:10:10 2016 +0100
> > 
> >     bpf: BPF for lightweight tunnel infrastructure
> > 
> 
> This makes modules closer to each other, so,
> net/socket.c:348: relocation truncated to fit: R_AVR32_11H_PCREL against
> `.text'+2930
> 
> But still the module is too big for AVR to do some jumps.

Well I've reverted your patch and tested on avr32 and all tests
worked successfully. Thanks to Guenter again for helping with his
testbed once again!

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v6 00/14] linux: generalize sections, ranges and linker tables
@ 2017-01-11 14:37               ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-11 14:37 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Luis R. Rodriguez, hpa, acme, tglx, mingo, jpoimboe, bp, npiggin,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, gregkh, rusty, gnomes, alan, dwmw2,
	arnd, ming.lei, linux-arch, benh, pebolle, fontana, david.vr

On Mon, Jan 09, 2017 at 08:29:15PM +0200, Andy Shevchenko wrote:
> On Mon, 2017-01-09 at 19:12 +0200, Andy Shevchenko wrote:
> > On Mon, 2017-01-09 at 18:27 +0200, Andy Shevchenko wrote:
> > > On Mon, 2017-01-09 at 06:58 -0800, Luis R. Rodriguez wrote:
> > > > The only architecture that was not tested was avr32 and that is
> > > > because
> > > > linux-next fails to compile on it. I'd like to greatly thank
> > > > Guenter
> > > > Roeck for
> > > > his help with testing.
> > > 
> > > We have a real board here. I would try to check if you provide a git
> > > url
> > > to your stuff.
> > > 
> > > I can confirm that breakage happened like in last couple of month.
> > > v4.10-rc3 can't be compiled either.
> > 
> > The culprit commit is
> > 
> > commit 3a0af8fd61f90920f6fa04e4f1e9a6a73c1b4fd2
> > Author: Thomas Graf <tgraf@suug.ch>
> > Date:   Wed Nov 30 17:10:10 2016 +0100
> > 
> >     bpf: BPF for lightweight tunnel infrastructure
> > 
> 
> This makes modules closer to each other, so,
> net/socket.c:348: relocation truncated to fit: R_AVR32_11H_PCREL against
> `.text'+2930
> 
> But still the module is too big for AVR to do some jumps.

Well I've reverted your patch and tested on avr32 and all tests
worked successfully. Thanks to Guenter again for helping with his
testbed once again!

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v6 00/14] linux: generalize sections, ranges and linker tables
@ 2017-01-11 14:37               ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-11 14:37 UTC (permalink / raw)
  To: Andy Shevchenko, Guenter Roeck
  Cc: Luis R. Rodriguez, hpa, acme, tglx, mingo, jpoimboe, bp, npiggin,
	mhiramat, masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, paul.gortmaker,
	xen-devel, ak, pali.rohar, dvhart, platform-driver-x86, mmarek,
	linux, jkosina, korea.drzix, linux-kbuild, tony.luck, akpm,
	linux-ia64, linux-arm-kernel, linux-sh, sparclinux,
	catalin.marinas, will.deacon, rostedt, jani.nikula, mchehab,
	markus.heiser, jolsa, msalter, chris, jcmvbkbc, linux-xtensa,
	adrian.hunter, dsahern, namhyung, wangnan0, dmitry.torokhov,
	joro, paulus, mpe, James.Bottomley

On Mon, Jan 09, 2017 at 08:29:15PM +0200, Andy Shevchenko wrote:
> On Mon, 2017-01-09 at 19:12 +0200, Andy Shevchenko wrote:
> > On Mon, 2017-01-09 at 18:27 +0200, Andy Shevchenko wrote:
> > > On Mon, 2017-01-09 at 06:58 -0800, Luis R. Rodriguez wrote:
> > > > The only architecture that was not tested was avr32 and that is
> > > > because
> > > > linux-next fails to compile on it. I'd like to greatly thank
> > > > Guenter
> > > > Roeck for
> > > > his help with testing.
> > > 
> > > We have a real board here. I would try to check if you provide a git
> > > url
> > > to your stuff.
> > > 
> > > I can confirm that breakage happened like in last couple of month.
> > > v4.10-rc3 can't be compiled either.
> > 
> > The culprit commit is
> > 
> > commit 3a0af8fd61f90920f6fa04e4f1e9a6a73c1b4fd2
> > Author: Thomas Graf <tgraf@suug.ch>
> > Date:   Wed Nov 30 17:10:10 2016 +0100
> > 
> >     bpf: BPF for lightweight tunnel infrastructure
> > 
> 
> This makes modules closer to each other, so,
> net/socket.c:348: relocation truncated to fit: R_AVR32_11H_PCREL against
> `.text'+2930
> 
> But still the module is too big for AVR to do some jumps.

Well I've reverted your patch and tested on avr32 and all tests
worked successfully. Thanks to Guenter again for helping with his
testbed once again!

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v7 00/14] linux: generalize sections, ranges and linker tables
  2017-01-09 14:58       ` Luis R. Rodriguez
  (?)
@ 2017-01-15 21:10         ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This v7 addresses spelling / minor checkpatch complaints, as requested.
checkpatch still complains but the remaining complaints are not valid for
the code in question.

A respective userspace sandbox for the kernel's tools/ follows this series.
A branch based on linux-next tag next-20170113 is available [0], if you use that
you should drop the last patch, that is used to force 0-day to test the
linker table test driver enabled on all architectures.

Even though the changes made are minor I've re-tested this on all archs again,
and all is good.

[0] https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h 170113-linker-tables-v7-try2

Luis R. Rodriguez (14):
  generic-sections: add section core helpers
  xtensa: skip adding literal when SORT() is used
  ranges.h: add helpers to build and identify Linux section ranges
  tables.h: add linker table support
  kbuild: enable option to force compile force-obj-y and force-lib-y
  firmware/Makefile: force recompilation if makefile changes
  firmware: port built-in section to linker table
  jump_label: move guard #endif down where it belongs
  jump_label: port __jump_table to linker tables
  dynamic_debug: port to use linker tables
  kprobes: move kprobe declarations to asm-generic/kprobes.h
  kprobes: port .kprobes.text to section range
  kprobes: port blacklist kprobes to linker table
  lib: add linker tables test driver

 Documentation/index.rst                   |   1 +
 Documentation/kbuild/makefiles.txt        |  36 ++
 Documentation/sections/background.rst     | 105 ++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  19 +
 Documentation/sections/linker-tables.rst  | 227 +++++++++
 Documentation/sections/ranges.rst         |  74 +++
 Documentation/sections/section-core.rst   | 153 ++++++
 MAINTAINERS                               |  33 ++
 arch/alpha/include/asm/Kbuild             |   4 +
 arch/arc/include/asm/Kbuild               |   3 +
 arch/arc/include/asm/kprobes.h            |   6 +-
 arch/arc/kernel/vmlinux.lds.S             |   1 -
 arch/arm/include/asm/Kbuild               |   3 +
 arch/arm/include/asm/jump_label.h         |   6 +-
 arch/arm/include/asm/kprobes.h            |   4 +
 arch/arm/kernel/entry-armv.S              |   3 +-
 arch/arm/kernel/vmlinux-xip.lds.S         |   1 -
 arch/arm/kernel/vmlinux.lds.S             |   1 -
 arch/arm/probes/decode.h                  |   1 +
 arch/arm64/include/asm/Kbuild             |   3 +
 arch/arm64/include/asm/jump_label.h       |   6 +-
 arch/arm64/include/asm/kprobes.h          |   4 +
 arch/arm64/kernel/armv8_deprecated.c      |   1 +
 arch/arm64/kernel/insn.c                  |   1 +
 arch/arm64/kernel/probes/decode-insn.h    |   2 +
 arch/arm64/kernel/probes/kprobes.c        |   4 +-
 arch/arm64/kernel/vmlinux.lds.S           |   1 -
 arch/avr32/include/asm/Kbuild             |   3 +
 arch/avr32/include/asm/kprobes.h          |   7 +-
 arch/avr32/kernel/entry-avr32b.S          |  13 +-
 arch/avr32/kernel/vmlinux.lds.S           |   1 -
 arch/blackfin/include/asm/Kbuild          |   4 +
 arch/blackfin/kernel/vmlinux.lds.S        |   1 -
 arch/c6x/include/asm/Kbuild               |   3 +
 arch/c6x/include/asm/tables.h             |  26 +
 arch/c6x/kernel/vmlinux.lds.S             |   1 -
 arch/cris/include/asm/Kbuild              |   4 +
 arch/frv/include/asm/Kbuild               |   4 +
 arch/h8300/include/asm/Kbuild             |   4 +
 arch/hexagon/include/asm/Kbuild           |   4 +
 arch/hexagon/kernel/vmlinux.lds.S         |   1 -
 arch/ia64/include/asm/Kbuild              |   3 +
 arch/ia64/include/asm/kprobes.h           |  12 +-
 arch/ia64/kernel/jprobes.S                |   3 +-
 arch/ia64/kernel/vmlinux.lds.S            |   1 -
 arch/ia64/lib/flush.S                     |   6 +-
 arch/m32r/include/asm/Kbuild              |   4 +
 arch/m68k/include/asm/Kbuild              |   4 +
 arch/metag/include/asm/Kbuild             |   4 +
 arch/metag/kernel/vmlinux.lds.S           |   1 -
 arch/microblaze/include/asm/Kbuild        |   4 +
 arch/microblaze/kernel/vmlinux.lds.S      |   1 -
 arch/mips/include/asm/Kbuild              |   3 +
 arch/mips/include/asm/jump_label.h        |   6 +-
 arch/mips/include/asm/kprobes.h           |   6 +-
 arch/mips/kernel/vmlinux.lds.S            |   1 -
 arch/mn10300/include/asm/Kbuild           |   3 +
 arch/mn10300/include/asm/kprobes.h        |   7 +-
 arch/mn10300/kernel/vmlinux.lds.S         |   1 -
 arch/nios2/include/asm/Kbuild             |   4 +
 arch/nios2/kernel/vmlinux.lds.S           |   1 -
 arch/openrisc/include/asm/Kbuild          |   4 +
 arch/openrisc/kernel/vmlinux.lds.S        |   1 -
 arch/parisc/include/asm/Kbuild            |   4 +
 arch/parisc/kernel/vmlinux.lds.S          |   1 -
 arch/powerpc/include/asm/Kbuild           |   3 +
 arch/powerpc/include/asm/jump_label.h     |   8 +-
 arch/powerpc/include/asm/kprobes.h        |   3 +
 arch/powerpc/include/asm/ppc_asm.h        |   3 +-
 arch/powerpc/kernel/vmlinux.lds.S         |   3 +-
 arch/s390/include/asm/Kbuild              |   3 +
 arch/s390/include/asm/jump_label.h        |   6 +-
 arch/s390/include/asm/kprobes.h           |   7 +-
 arch/s390/kernel/entry.S                  |   5 +-
 arch/s390/kernel/kprobes.c                |   6 +-
 arch/s390/kernel/mcount.S                 |   3 +-
 arch/s390/kernel/vmlinux.lds.S            |   1 -
 arch/score/include/asm/Kbuild             |   4 +
 arch/score/kernel/vmlinux.lds.S           |   1 -
 arch/sh/include/asm/Kbuild                |   3 +
 arch/sh/include/asm/kprobes.h             |   5 +-
 arch/sh/kernel/vmlinux.lds.S              |   1 -
 arch/sparc/include/asm/Kbuild             |   3 +
 arch/sparc/include/asm/jump_label.h       |   6 +-
 arch/sparc/include/asm/kprobes.h          |  10 +-
 arch/sparc/kernel/vmlinux.lds.S           |   1 -
 arch/sparc/mm/ultra.S                     |   3 +-
 arch/tile/include/asm/Kbuild              |   3 +
 arch/tile/include/asm/jump_label.h        |   5 +-
 arch/tile/include/asm/kprobes.h           |   6 +-
 arch/tile/kernel/vmlinux.lds.S            |   1 -
 arch/um/include/asm/Kbuild                |   4 +
 arch/unicore32/include/asm/Kbuild         |   3 +
 arch/unicore32/include/asm/section-core.h |  19 +
 arch/x86/include/asm/Kbuild               |   3 +
 arch/x86/include/asm/asm.h                |   4 +-
 arch/x86/include/asm/jump_label.h         |  10 +-
 arch/x86/include/asm/kprobes.h            |   9 +-
 arch/x86/kernel/cpu/microcode/core.c      |   8 +-
 arch/x86/kernel/kprobes/core.c            |  11 +-
 arch/x86/kernel/vmlinux.lds.S             |   1 -
 arch/x86/tools/relocs.c                   |   4 +
 arch/xtensa/include/asm/Kbuild            |   4 +
 arch/xtensa/kernel/Makefile               |   8 +-
 drivers/base/firmware_class.c             |  12 +-
 firmware/Makefile                         |   6 +-
 include/asm-generic/kprobes.h             |  26 +
 include/asm-generic/ranges.h              |  93 ++++
 include/asm-generic/section-core.h        | 348 +++++++++++++
 include/asm-generic/sections.h            |   4 +-
 include/asm-generic/tables.h              |  48 ++
 include/asm-generic/vmlinux.lds.h         |  47 +-
 include/linux/compiler.h                  |   8 -
 include/linux/dynamic_debug.h             |   5 +-
 include/linux/init.h                      |  89 +++-
 include/linux/jump_label.h                |   8 +-
 include/linux/kprobes.h                   |  24 +-
 include/linux/ranges.h                    | 183 +++++++
 include/linux/sections.h                  |  87 ++++
 include/linux/tables.h                    | 683 +++++++++++++++++++++++++
 init/Kconfig                              |  22 +
 kernel/jump_label.c                       |  17 +-
 kernel/kprobes.c                          |  17 +-
 lib/Kconfig.debug                         |   6 +
 lib/Makefile                              |   1 +
 lib/dynamic_debug.c                       |  13 +-
 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 ++
 scripts/Makefile.build                    |   7 +-
 scripts/Makefile.clean                    |   2 +
 scripts/Makefile.lib                      |  11 +
 scripts/mod/modpost.c                     |   2 +-
 scripts/module-common.lds                 |   2 +
 scripts/recordmcount.c                    |   2 +-
 scripts/recordmcount.pl                   |   2 +-
 tools/objtool/special.c                   |   2 +-
 143 files changed, 3633 insertions(+), 200 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/linker-tables.rst
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/c6x/include/asm/tables.h
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/kprobes.h
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/asm-generic/tables.h
 create mode 100644 include/linux/ranges.h
 create mode 100644 include/linux/sections.h
 create mode 100644 include/linux/tables.h
 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

-- 
2.11.0


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v7 00/14] linux: generalize sections, ranges and linker tables
@ 2017-01-15 21:10         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This v7 addresses spelling / minor checkpatch complaints, as requested.
checkpatch still complains but the remaining complaints are not valid for
the code in question.

A respective userspace sandbox for the kernel's tools/ follows this series.
A branch based on linux-next tag next-20170113 is available [0], if you use that
you should drop the last patch, that is used to force 0-day to test the
linker table test driver enabled on all architectures.

Even though the changes made are minor I've re-tested this on all archs again,
and all is good.

[0] https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h=20170113-linker-tables-v7-try2

Luis R. Rodriguez (14):
  generic-sections: add section core helpers
  xtensa: skip adding literal when SORT() is used
  ranges.h: add helpers to build and identify Linux section ranges
  tables.h: add linker table support
  kbuild: enable option to force compile force-obj-y and force-lib-y
  firmware/Makefile: force recompilation if makefile changes
  firmware: port built-in section to linker table
  jump_label: move guard #endif down where it belongs
  jump_label: port __jump_table to linker tables
  dynamic_debug: port to use linker tables
  kprobes: move kprobe declarations to asm-generic/kprobes.h
  kprobes: port .kprobes.text to section range
  kprobes: port blacklist kprobes to linker table
  lib: add linker tables test driver

 Documentation/index.rst                   |   1 +
 Documentation/kbuild/makefiles.txt        |  36 ++
 Documentation/sections/background.rst     | 105 ++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  19 +
 Documentation/sections/linker-tables.rst  | 227 +++++++++
 Documentation/sections/ranges.rst         |  74 +++
 Documentation/sections/section-core.rst   | 153 ++++++
 MAINTAINERS                               |  33 ++
 arch/alpha/include/asm/Kbuild             |   4 +
 arch/arc/include/asm/Kbuild               |   3 +
 arch/arc/include/asm/kprobes.h            |   6 +-
 arch/arc/kernel/vmlinux.lds.S             |   1 -
 arch/arm/include/asm/Kbuild               |   3 +
 arch/arm/include/asm/jump_label.h         |   6 +-
 arch/arm/include/asm/kprobes.h            |   4 +
 arch/arm/kernel/entry-armv.S              |   3 +-
 arch/arm/kernel/vmlinux-xip.lds.S         |   1 -
 arch/arm/kernel/vmlinux.lds.S             |   1 -
 arch/arm/probes/decode.h                  |   1 +
 arch/arm64/include/asm/Kbuild             |   3 +
 arch/arm64/include/asm/jump_label.h       |   6 +-
 arch/arm64/include/asm/kprobes.h          |   4 +
 arch/arm64/kernel/armv8_deprecated.c      |   1 +
 arch/arm64/kernel/insn.c                  |   1 +
 arch/arm64/kernel/probes/decode-insn.h    |   2 +
 arch/arm64/kernel/probes/kprobes.c        |   4 +-
 arch/arm64/kernel/vmlinux.lds.S           |   1 -
 arch/avr32/include/asm/Kbuild             |   3 +
 arch/avr32/include/asm/kprobes.h          |   7 +-
 arch/avr32/kernel/entry-avr32b.S          |  13 +-
 arch/avr32/kernel/vmlinux.lds.S           |   1 -
 arch/blackfin/include/asm/Kbuild          |   4 +
 arch/blackfin/kernel/vmlinux.lds.S        |   1 -
 arch/c6x/include/asm/Kbuild               |   3 +
 arch/c6x/include/asm/tables.h             |  26 +
 arch/c6x/kernel/vmlinux.lds.S             |   1 -
 arch/cris/include/asm/Kbuild              |   4 +
 arch/frv/include/asm/Kbuild               |   4 +
 arch/h8300/include/asm/Kbuild             |   4 +
 arch/hexagon/include/asm/Kbuild           |   4 +
 arch/hexagon/kernel/vmlinux.lds.S         |   1 -
 arch/ia64/include/asm/Kbuild              |   3 +
 arch/ia64/include/asm/kprobes.h           |  12 +-
 arch/ia64/kernel/jprobes.S                |   3 +-
 arch/ia64/kernel/vmlinux.lds.S            |   1 -
 arch/ia64/lib/flush.S                     |   6 +-
 arch/m32r/include/asm/Kbuild              |   4 +
 arch/m68k/include/asm/Kbuild              |   4 +
 arch/metag/include/asm/Kbuild             |   4 +
 arch/metag/kernel/vmlinux.lds.S           |   1 -
 arch/microblaze/include/asm/Kbuild        |   4 +
 arch/microblaze/kernel/vmlinux.lds.S      |   1 -
 arch/mips/include/asm/Kbuild              |   3 +
 arch/mips/include/asm/jump_label.h        |   6 +-
 arch/mips/include/asm/kprobes.h           |   6 +-
 arch/mips/kernel/vmlinux.lds.S            |   1 -
 arch/mn10300/include/asm/Kbuild           |   3 +
 arch/mn10300/include/asm/kprobes.h        |   7 +-
 arch/mn10300/kernel/vmlinux.lds.S         |   1 -
 arch/nios2/include/asm/Kbuild             |   4 +
 arch/nios2/kernel/vmlinux.lds.S           |   1 -
 arch/openrisc/include/asm/Kbuild          |   4 +
 arch/openrisc/kernel/vmlinux.lds.S        |   1 -
 arch/parisc/include/asm/Kbuild            |   4 +
 arch/parisc/kernel/vmlinux.lds.S          |   1 -
 arch/powerpc/include/asm/Kbuild           |   3 +
 arch/powerpc/include/asm/jump_label.h     |   8 +-
 arch/powerpc/include/asm/kprobes.h        |   3 +
 arch/powerpc/include/asm/ppc_asm.h        |   3 +-
 arch/powerpc/kernel/vmlinux.lds.S         |   3 +-
 arch/s390/include/asm/Kbuild              |   3 +
 arch/s390/include/asm/jump_label.h        |   6 +-
 arch/s390/include/asm/kprobes.h           |   7 +-
 arch/s390/kernel/entry.S                  |   5 +-
 arch/s390/kernel/kprobes.c                |   6 +-
 arch/s390/kernel/mcount.S                 |   3 +-
 arch/s390/kernel/vmlinux.lds.S            |   1 -
 arch/score/include/asm/Kbuild             |   4 +
 arch/score/kernel/vmlinux.lds.S           |   1 -
 arch/sh/include/asm/Kbuild                |   3 +
 arch/sh/include/asm/kprobes.h             |   5 +-
 arch/sh/kernel/vmlinux.lds.S              |   1 -
 arch/sparc/include/asm/Kbuild             |   3 +
 arch/sparc/include/asm/jump_label.h       |   6 +-
 arch/sparc/include/asm/kprobes.h          |  10 +-
 arch/sparc/kernel/vmlinux.lds.S           |   1 -
 arch/sparc/mm/ultra.S                     |   3 +-
 arch/tile/include/asm/Kbuild              |   3 +
 arch/tile/include/asm/jump_label.h        |   5 +-
 arch/tile/include/asm/kprobes.h           |   6 +-
 arch/tile/kernel/vmlinux.lds.S            |   1 -
 arch/um/include/asm/Kbuild                |   4 +
 arch/unicore32/include/asm/Kbuild         |   3 +
 arch/unicore32/include/asm/section-core.h |  19 +
 arch/x86/include/asm/Kbuild               |   3 +
 arch/x86/include/asm/asm.h                |   4 +-
 arch/x86/include/asm/jump_label.h         |  10 +-
 arch/x86/include/asm/kprobes.h            |   9 +-
 arch/x86/kernel/cpu/microcode/core.c      |   8 +-
 arch/x86/kernel/kprobes/core.c            |  11 +-
 arch/x86/kernel/vmlinux.lds.S             |   1 -
 arch/x86/tools/relocs.c                   |   4 +
 arch/xtensa/include/asm/Kbuild            |   4 +
 arch/xtensa/kernel/Makefile               |   8 +-
 drivers/base/firmware_class.c             |  12 +-
 firmware/Makefile                         |   6 +-
 include/asm-generic/kprobes.h             |  26 +
 include/asm-generic/ranges.h              |  93 ++++
 include/asm-generic/section-core.h        | 348 +++++++++++++
 include/asm-generic/sections.h            |   4 +-
 include/asm-generic/tables.h              |  48 ++
 include/asm-generic/vmlinux.lds.h         |  47 +-
 include/linux/compiler.h                  |   8 -
 include/linux/dynamic_debug.h             |   5 +-
 include/linux/init.h                      |  89 +++-
 include/linux/jump_label.h                |   8 +-
 include/linux/kprobes.h                   |  24 +-
 include/linux/ranges.h                    | 183 +++++++
 include/linux/sections.h                  |  87 ++++
 include/linux/tables.h                    | 683 +++++++++++++++++++++++++
 init/Kconfig                              |  22 +
 kernel/jump_label.c                       |  17 +-
 kernel/kprobes.c                          |  17 +-
 lib/Kconfig.debug                         |   6 +
 lib/Makefile                              |   1 +
 lib/dynamic_debug.c                       |  13 +-
 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 ++
 scripts/Makefile.build                    |   7 +-
 scripts/Makefile.clean                    |   2 +
 scripts/Makefile.lib                      |  11 +
 scripts/mod/modpost.c                     |   2 +-
 scripts/module-common.lds                 |   2 +
 scripts/recordmcount.c                    |   2 +-
 scripts/recordmcount.pl                   |   2 +-
 tools/objtool/special.c                   |   2 +-
 143 files changed, 3633 insertions(+), 200 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/linker-tables.rst
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/c6x/include/asm/tables.h
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/kprobes.h
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/asm-generic/tables.h
 create mode 100644 include/linux/ranges.h
 create mode 100644 include/linux/sections.h
 create mode 100644 include/linux/tables.h
 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

-- 
2.11.0


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v7 00/14] linux: generalize sections, ranges and linker tables
@ 2017-01-15 21:10         ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

This v7 addresses spelling / minor checkpatch complaints, as requested.
checkpatch still complains but the remaining complaints are not valid for
the code in question.

A respective userspace sandbox for the kernel's tools/ follows this series.
A branch based on linux-next tag next-20170113 is available [0], if you use that
you should drop the last patch, that is used to force 0-day to test the
linker table test driver enabled on all architectures.

Even though the changes made are minor I've re-tested this on all archs again,
and all is good.

[0] https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linux-next.git/log/?h=20170113-linker-tables-v7-try2

Luis R. Rodriguez (14):
  generic-sections: add section core helpers
  xtensa: skip adding literal when SORT() is used
  ranges.h: add helpers to build and identify Linux section ranges
  tables.h: add linker table support
  kbuild: enable option to force compile force-obj-y and force-lib-y
  firmware/Makefile: force recompilation if makefile changes
  firmware: port built-in section to linker table
  jump_label: move guard #endif down where it belongs
  jump_label: port __jump_table to linker tables
  dynamic_debug: port to use linker tables
  kprobes: move kprobe declarations to asm-generic/kprobes.h
  kprobes: port .kprobes.text to section range
  kprobes: port blacklist kprobes to linker table
  lib: add linker tables test driver

 Documentation/index.rst                   |   1 +
 Documentation/kbuild/makefiles.txt        |  36 ++
 Documentation/sections/background.rst     | 105 ++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  19 +
 Documentation/sections/linker-tables.rst  | 227 +++++++++
 Documentation/sections/ranges.rst         |  74 +++
 Documentation/sections/section-core.rst   | 153 ++++++
 MAINTAINERS                               |  33 ++
 arch/alpha/include/asm/Kbuild             |   4 +
 arch/arc/include/asm/Kbuild               |   3 +
 arch/arc/include/asm/kprobes.h            |   6 +-
 arch/arc/kernel/vmlinux.lds.S             |   1 -
 arch/arm/include/asm/Kbuild               |   3 +
 arch/arm/include/asm/jump_label.h         |   6 +-
 arch/arm/include/asm/kprobes.h            |   4 +
 arch/arm/kernel/entry-armv.S              |   3 +-
 arch/arm/kernel/vmlinux-xip.lds.S         |   1 -
 arch/arm/kernel/vmlinux.lds.S             |   1 -
 arch/arm/probes/decode.h                  |   1 +
 arch/arm64/include/asm/Kbuild             |   3 +
 arch/arm64/include/asm/jump_label.h       |   6 +-
 arch/arm64/include/asm/kprobes.h          |   4 +
 arch/arm64/kernel/armv8_deprecated.c      |   1 +
 arch/arm64/kernel/insn.c                  |   1 +
 arch/arm64/kernel/probes/decode-insn.h    |   2 +
 arch/arm64/kernel/probes/kprobes.c        |   4 +-
 arch/arm64/kernel/vmlinux.lds.S           |   1 -
 arch/avr32/include/asm/Kbuild             |   3 +
 arch/avr32/include/asm/kprobes.h          |   7 +-
 arch/avr32/kernel/entry-avr32b.S          |  13 +-
 arch/avr32/kernel/vmlinux.lds.S           |   1 -
 arch/blackfin/include/asm/Kbuild          |   4 +
 arch/blackfin/kernel/vmlinux.lds.S        |   1 -
 arch/c6x/include/asm/Kbuild               |   3 +
 arch/c6x/include/asm/tables.h             |  26 +
 arch/c6x/kernel/vmlinux.lds.S             |   1 -
 arch/cris/include/asm/Kbuild              |   4 +
 arch/frv/include/asm/Kbuild               |   4 +
 arch/h8300/include/asm/Kbuild             |   4 +
 arch/hexagon/include/asm/Kbuild           |   4 +
 arch/hexagon/kernel/vmlinux.lds.S         |   1 -
 arch/ia64/include/asm/Kbuild              |   3 +
 arch/ia64/include/asm/kprobes.h           |  12 +-
 arch/ia64/kernel/jprobes.S                |   3 +-
 arch/ia64/kernel/vmlinux.lds.S            |   1 -
 arch/ia64/lib/flush.S                     |   6 +-
 arch/m32r/include/asm/Kbuild              |   4 +
 arch/m68k/include/asm/Kbuild              |   4 +
 arch/metag/include/asm/Kbuild             |   4 +
 arch/metag/kernel/vmlinux.lds.S           |   1 -
 arch/microblaze/include/asm/Kbuild        |   4 +
 arch/microblaze/kernel/vmlinux.lds.S      |   1 -
 arch/mips/include/asm/Kbuild              |   3 +
 arch/mips/include/asm/jump_label.h        |   6 +-
 arch/mips/include/asm/kprobes.h           |   6 +-
 arch/mips/kernel/vmlinux.lds.S            |   1 -
 arch/mn10300/include/asm/Kbuild           |   3 +
 arch/mn10300/include/asm/kprobes.h        |   7 +-
 arch/mn10300/kernel/vmlinux.lds.S         |   1 -
 arch/nios2/include/asm/Kbuild             |   4 +
 arch/nios2/kernel/vmlinux.lds.S           |   1 -
 arch/openrisc/include/asm/Kbuild          |   4 +
 arch/openrisc/kernel/vmlinux.lds.S        |   1 -
 arch/parisc/include/asm/Kbuild            |   4 +
 arch/parisc/kernel/vmlinux.lds.S          |   1 -
 arch/powerpc/include/asm/Kbuild           |   3 +
 arch/powerpc/include/asm/jump_label.h     |   8 +-
 arch/powerpc/include/asm/kprobes.h        |   3 +
 arch/powerpc/include/asm/ppc_asm.h        |   3 +-
 arch/powerpc/kernel/vmlinux.lds.S         |   3 +-
 arch/s390/include/asm/Kbuild              |   3 +
 arch/s390/include/asm/jump_label.h        |   6 +-
 arch/s390/include/asm/kprobes.h           |   7 +-
 arch/s390/kernel/entry.S                  |   5 +-
 arch/s390/kernel/kprobes.c                |   6 +-
 arch/s390/kernel/mcount.S                 |   3 +-
 arch/s390/kernel/vmlinux.lds.S            |   1 -
 arch/score/include/asm/Kbuild             |   4 +
 arch/score/kernel/vmlinux.lds.S           |   1 -
 arch/sh/include/asm/Kbuild                |   3 +
 arch/sh/include/asm/kprobes.h             |   5 +-
 arch/sh/kernel/vmlinux.lds.S              |   1 -
 arch/sparc/include/asm/Kbuild             |   3 +
 arch/sparc/include/asm/jump_label.h       |   6 +-
 arch/sparc/include/asm/kprobes.h          |  10 +-
 arch/sparc/kernel/vmlinux.lds.S           |   1 -
 arch/sparc/mm/ultra.S                     |   3 +-
 arch/tile/include/asm/Kbuild              |   3 +
 arch/tile/include/asm/jump_label.h        |   5 +-
 arch/tile/include/asm/kprobes.h           |   6 +-
 arch/tile/kernel/vmlinux.lds.S            |   1 -
 arch/um/include/asm/Kbuild                |   4 +
 arch/unicore32/include/asm/Kbuild         |   3 +
 arch/unicore32/include/asm/section-core.h |  19 +
 arch/x86/include/asm/Kbuild               |   3 +
 arch/x86/include/asm/asm.h                |   4 +-
 arch/x86/include/asm/jump_label.h         |  10 +-
 arch/x86/include/asm/kprobes.h            |   9 +-
 arch/x86/kernel/cpu/microcode/core.c      |   8 +-
 arch/x86/kernel/kprobes/core.c            |  11 +-
 arch/x86/kernel/vmlinux.lds.S             |   1 -
 arch/x86/tools/relocs.c                   |   4 +
 arch/xtensa/include/asm/Kbuild            |   4 +
 arch/xtensa/kernel/Makefile               |   8 +-
 drivers/base/firmware_class.c             |  12 +-
 firmware/Makefile                         |   6 +-
 include/asm-generic/kprobes.h             |  26 +
 include/asm-generic/ranges.h              |  93 ++++
 include/asm-generic/section-core.h        | 348 +++++++++++++
 include/asm-generic/sections.h            |   4 +-
 include/asm-generic/tables.h              |  48 ++
 include/asm-generic/vmlinux.lds.h         |  47 +-
 include/linux/compiler.h                  |   8 -
 include/linux/dynamic_debug.h             |   5 +-
 include/linux/init.h                      |  89 +++-
 include/linux/jump_label.h                |   8 +-
 include/linux/kprobes.h                   |  24 +-
 include/linux/ranges.h                    | 183 +++++++
 include/linux/sections.h                  |  87 ++++
 include/linux/tables.h                    | 683 +++++++++++++++++++++++++
 init/Kconfig                              |  22 +
 kernel/jump_label.c                       |  17 +-
 kernel/kprobes.c                          |  17 +-
 lib/Kconfig.debug                         |   6 +
 lib/Makefile                              |   1 +
 lib/dynamic_debug.c                       |  13 +-
 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 ++
 scripts/Makefile.build                    |   7 +-
 scripts/Makefile.clean                    |   2 +
 scripts/Makefile.lib                      |  11 +
 scripts/mod/modpost.c                     |   2 +-
 scripts/module-common.lds                 |   2 +
 scripts/recordmcount.c                    |   2 +-
 scripts/recordmcount.pl                   |   2 +-
 tools/objtool/special.c                   |   2 +-
 143 files changed, 3633 insertions(+), 200 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/linker-tables.rst
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/c6x/include/asm/tables.h
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/kprobes.h
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/asm-generic/tables.h
 create mode 100644 include/linux/ranges.h
 create mode 100644 include/linux/sections.h
 create mode 100644 include/linux/tables.h
 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

-- 
2.11.0


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v7 01/14] generic-sections: add section core helpers
  2017-01-15 21:10         ` Luis R. Rodriguez
                             ` (2 preceding siblings ...)
  (?)
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="windows-1254", Size: 47058 bytes --]

Linux makes extensive use of custom ELF header sections,
documentation for these are well scattered. Unify this
documentation in a central place and provide helpers to
build custom Linux sections.

This also generalizes sections code to enable avoiding
modifying the linker scripts when we want to add new
custom Linux sections. In order to make this generally
useful we need to ensure all architectures can make use of
core section helpers but that they can also override should
this be needed. Instead of relying on section.h this adds
a sections-core.h since this will be targeted to be safe
to be used on asm code, linker scripts and C code.

v7: ran ispell to fix spelling as requested by Boris

v5:

o Huge documentation revamp based on a careful review of the ELF
  specifications. Includes documentation now also about usage of
  two dots (..) when prefixing ELF program specific sections.

o Replace macros for sections names in favor of just using
  the section names explicitly in the linker script. This is
  perhaps more work to grep but this is what folks seem to
  currently prefer.

o Fix .text and .rodata documentation to explain memory protection
  strategies which architectures can embrace upon initialization
  (documents CONFIG_DEBUG_RODATA and mark_rodata_ro())

o Skip the 'Linux section ordering' documentation section, we'll instead
  add this on subsequent patch which will expand on it considerably

o Dropped tree on MAINTAINERS -- as per discussions with Arnd, hpa and
  Josh, its easier to just let changes for sections go in through the
  respective tree that needs the changes.

o Fix typos on documentation

o Dropped SECTION_ALL(), __SECTION_CORE(), SECTION_CORE_ALL() macros
  since we are favoring using explicit section names. These are
  useless if we are being explicit.

o Drop LINUX_SECTION_SIZE(), LINUX_SECTION_EMPTY() in favor of having
  section ranges and linker tables define their own, to avoid confusion
  and make code more readable.

o Add __define_initcall() documentation and a small section describing
  our current initcall levels. This should help also clarify what was
  meant about keeping backward compatibility.

v4:

o Port to shiny new sphinx documentation format

o fix a unicore32 build, turns out this actually fixes unicore32
  defconfig builds which were failing for a long while. unicore32
  does not seem to grok well the type passed on a section declaration,
  this ignores it.

o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
  this was causing final linker issues with blackfin -- this is
  a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
  being metatag. metatag is not supported on 0-day so I cannot confirm
  compilation there.

o Added SECTION_CORE() for C code, used later by __LINUX_RANGE()

o Since SECTION_CORE() is defined for linker script and C code, share
  the same helper and just use a __stringify() for the C code as is done
  for the other C helpers.

o move generic sections to asm-generic/section-core.h instead.
  PowerPC compilation blows up if asm/jump_labels.h gets
  section.h included, fixing this is not in any way easy.
  The list of issues are endless. Moving new data to a new
  simple file resolves this.

o since things are now in asm-generic/section-core.h the
  guard changes on asm-generic/sections.h and each architecture
  sections.h are no longer needed

o Give generic sections some maintainer love, that change is
  Acked-by Arnd Bergmann, Josh and hpa.

o A few checkpatch.pl style fixes

o As suggested by James Hogan use generic-y to copy generic
  header files on architectures that do not have a sections.h
  instead of writing a simple file only to include the generic one.

v3:

o add missing sections.h for architectures that did not
  have it

o move generic sections to asm-generic/sections.h

o add generic asm helpers section_type(), section_type_asmtype(),
  push_section_type() -- these helpers enable easy use for
  for later declaring and using of custom Linux sections using
  more standard APIs in both C code, asm code (C asm calls, or
  asm files), enabling future standardized section types to
  be more immediately accessible to asm code, not just C code.
  Note for ASM_CMD_SEP we use by default "\n", architectures needed
  to override can do so on their own sections.h prior to inclusion
  of asm-generic/sections.h

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/index.rst                   |   1 +
 Documentation/sections/background.rst     | 105 ++++++++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  17 ++
 Documentation/sections/section-core.rst   | 148 ++++++++++++++
 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/Kbuild               |   1 +
 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/section-core.h |  19 ++
 arch/x86/include/asm/Kbuild               |   1 +
 arch/xtensa/include/asm/Kbuild            |   1 +
 include/asm-generic/section-core.h        | 307 ++++++++++++++++++++++++++++++
 include/asm-generic/sections.h            |   2 +
 include/asm-generic/vmlinux.lds.h         |   1 +
 include/linux/init.h                      |  89 +++++++--
 include/linux/sections.h                  |  87 +++++++++
 42 files changed, 809 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/linux/sections.h

diff --git a/Documentation/index.rst b/Documentation/index.rst
index cb5d77699c60..71e0305c036d 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -57,6 +57,7 @@ needed).
    media/index
    gpu/index
    security/index
+   sections/index
    sound/index
    crypto/index
 
diff --git a/Documentation/sections/background.rst b/Documentation/sections/background.rst
new file mode 100644
index 000000000000..4f04c0682a6f
--- /dev/null
+++ b/Documentation/sections/background.rst
@@ -0,0 +1,105 @@
+===========
+ELF section background
+===========
+
+About
+==+
+The purpose of this chapter is to help those not familiar with ELF to brush up
+the latest ELF specifications in order to help understand how Linux uses and
+defines its own ELF sections.
+
+Standardized ELF
+========
+
+The first publication documenting ELF was UNIX System Laboratories' (USL)
+*System V Release 4 Application Binary Interface* (`SRV4 ABI`_) specification.
+Originally ELF was only a small part of the SRV4 ABI, with time however new
+specifications only put focus on ELF, such was the case of the *TIS Portable
+Formats Specification version 1.2* (`TIS 1.2`_). As of TIS 1.2, ELF was
+supplemented with processor specific ELF addendums, available on the *Linux
+Foundation referenced specification page* (`LF ref page`_). The latest ELF
+specification is the *System V Application Binary Interface - DRAFT - 24 April
+2001* (`gabi4`_).
+
+.. _SRV4 ABI: http://www.sco.com/developers/devspecs/gabi41.pdf
+.. _TIS 1.2: https://refspecs.linuxbase.org/elf/elf.pdf
+.. _LF ref page: https://refspecs.linuxbase.org/
+.. _gabi4: https://refspecs.linuxbase.org/elf/gabi4+/contents.html
+
+ELF views on Linux
+=========
+
+There are two views which can be used for inspecting data in an ELF file, a
+Linking view, and an Execution view. A Section Header Table enables one to
+describe an object using the Linking view while a Program Header Table enables
+one to describe an object using the Execution view. The views are not mutually
+exclusive. For instance, vmlinux can be viewed under both views, ``readelf -S
+vmlinux`` for the Linking view, and ``readelf -l vmlinux`` for the Execution
+view.  In Linux only the vmlinux file will have an Execution view, even modules
+lack an Execution view given that vmlinux is the only file that describes how
+the the kernel runs from the start.  All other Linux kernel object files have
+an available Linking view.
+
+Under the Linking view, the Section Header Table describes all available
+sections. The Section Header Table is an array of ELF section header data
+structures. If on a 32-bit system this is ``struct elf32_shd``, if on a 64-bit
+this is ``struct elf64_shdr``. Sections are only visible on object files that
+have a Linking view, since all Linux kernel files have Linking view, all kernel
+objects have ELF sections.
+
+Limitations on ELF sections
+=============+
+We provide a summary on the limitations of ELF sections. Refer to the public
+ELF specifications for details. Note that 64-bit limitations may depend
+on processor specific section attributes to be used, refer to your processor
+specification if unsure.
+
+Its worth elaborating on the limitations on the name of an ELF section:
+ELF section names are stored as strings as per the ELF specification, and
+as can be expected, these don't have explicit limitations. The implicit
+limitation then depends on the size of an ELF object file and ELF section.
+
+If using really large kernels or objects with large amounts of sections one
+would still need to be sure that ELF loader in charge of loading the Linux
+kernel is properly updated to handle coping with the latest ELF extensions.
+
+   .. flat-table:: Limitations on ELF Sections
+
+      * - Section attribute
+        - 32-bit
+        - 64-bit
+
+      * - ELF section name
+        - Size of an ELF section
+        - Size of an ELF section
+
+      * - Size of an ELF section
+        - 4 GiB
+        - 16 EiB
+
+      * - Max number of sections in an object file
+        - 4 GiEntries (4294967296)
+        - 16 EiEntries (18446744073709551616)
+
+Program specific ELF sections
+==============+
+The ELF specification allows for a section type to be specified as
+*Program specific section*, defined as ``SHT_PROGBITS``. This sections type
+enables programs to customize sections for their own use. In assembly this
+specified ``@progbits`` on most architectures, on ARM this is ``%progbits``.
+
+``SHT_PROGBITS`` is used by Linux for defining and using Linux ELF sections.
+
+Special ELF Sections
+==========
+
+The ELF specification defines *Special ELF Sections* on chapter 4 (`gabi4
+ch4`_). These are defined as sections which hold program and control
+information. Of these sections, a few have the section type as
+``SHT_PROGBITS``. This enables Linux to *further customize* use of the section
+beyond what the ELF specification suggests.
+
+.. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
new file mode 100644
index 000000000000..faa1c57595e1
--- /dev/null
+++ b/Documentation/sections/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel ELF sections'
+html_search_language = 'en'
diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
new file mode 100644
index 000000000000..f37511ef05e7
--- /dev/null
+++ b/Documentation/sections/index.rst
@@ -0,0 +1,17 @@
+============+Linux Kernel ELF sections
+============+
+This book documents the different ELF sections used on the Linux kernel.
+We start off by providing references to how ELF was standardized, references
+to the standards on ELF sections, review limitations of ELF sections, and
+finally how Linux uses ELF sections in the Linux kernel. Certain important
+Linux ELF sections are documented carefully: we describe the goal of the
+ELF section, and address concurrency considerations when applicable. A few
+common a set of Linux helpers for ELF sections are also documented.
+
+.. toctree::
+   :maxdepth: 4
+
+   background
+   section-core
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
new file mode 100644
index 000000000000..ac5815a0d9b3
--- /dev/null
+++ b/Documentation/sections/section-core.rst
@@ -0,0 +1,148 @@
+=================+Linux ELF program specific sections
+=================+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux ELF program specific sections
+
+Linux linker script
+=========+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux linker script
+
+Memory protection
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Memory protection
+
+mark_rodata_ro
+-----------------------
+.. kernel-doc:: include/linux/init.h
+   :functions: mark_rodata_ro
+
+.rodata
+-------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .rodata
+
+.text
+-----
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .text
+
+.data
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .data
+
+Linux .init\* sections
+===========
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux init sections
+
+.init.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.text
+
+.init.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.data
+
+.init.rodata
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.rodata
+
+Initcall levels
+---------------
+.. kernel-doc:: include/linux/init.h
+   :doc: Initcall levels
+
+.initcall
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .initcall
+
+__define_initcall
+-----------------
+.. kernel-doc:: include/linux/init.h
+   :functions: __define_initcall
+
+Linux .exit\* sections
+===========
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux exit sections
+
+.exit.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.text
+
+.exit.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.data
+
+.exitcall.exit
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exitcall.exit
+
+Linux .ref\* sections
+==========+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux references to init sections
+
+.ref.text
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.text
+
+.ref.data
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.data
+
+.ref.rodata
+-----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.rodata
+
+Generic Linux kernel section helpers
+==================
+
+Introduction
+-------------
+.. kernel-doc:: include/linux/sections.h
+   :doc: Introduction
+
+LINUX_SECTION_ALIGNMENT
+-----------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_ALIGNMENT
+
+LINUX_SECTION_START
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_START
+
+LINUX_SECTION_END
+-----------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_END
+
+DECLARE_LINUX_SECTION
+---------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION
+
+DECLARE_LINUX_SECTION_RO
+------------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION_RO
diff --git a/MAINTAINERS b/MAINTAINERS
index d2db7fecef32..5e580b1257fb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5438,6 +5438,18 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTIONS
+M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
+M:	Josh Poimboeuf <jpoimboe@redhat.com>
+M:	"H. Peter Anvin" <hpa@zytor.com>
+L:	linux-arch@vger.kernel.org
+L:	linux-kernel@vger.kernel.org
+S:	Supported
+F:	include/asm-generic/section-core.h
+F:	include/asm-generic/sections.h
+F:	include/asm-generic/vmlinux.lds.h
+F:	Documentation/sections/section-core.rst
+
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index bf8475ce85ee..5422827f1585 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += section-core.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index c332604606dd..7b2cb3dea5fc 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index efb21757d41f..9b69a22a9ae1 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += unaligned.h
 
 generated-y += mach-types.h
 generated-y += unistd-nr.h
+generic-y += section-core.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 8365a84c2640..00ace5e826f1 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 241b9b9729d8..f2c3b656a0e7 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 2fb67b59d188..bf20541bcf21 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -47,3 +47,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 64465e7e2245..38127ce747be 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -62,3 +62,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 1778805f6380..385cd88a9d9e 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += types.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 1fa084cf1a43..46d7c599d9b8 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 373cb23301e3..1ec04ec1c82b 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -75,3 +75,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index db8ddabc6bd2..37d7bfae7619 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -60,3 +60,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 502a91d8dbbd..672c6d5da18c 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 6e69d2c42eee..8ccfb5eb9678 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1f2e5d31cb24..1277b45bf4f9 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -34,3 +34,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 167150c701d1..b1011375cd7a 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -55,3 +55,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index b0ae88c9fed9..c6c2cf6edc98 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index ed07179fe26a..7a932b4a5531 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 1c8dd0f5cd5d..f8145bc85835 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index d63330e88379..c9c7cb82b00f 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 2832f031fb11..86175e701869 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -71,3 +71,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 91f53c07f410..18a9d4c5ead7 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -28,3 +28,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 5c4fbc80dc6c..4322d9746cdb 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
+generic-y += section-core.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 8aea32fe8bd2..63a1c2924b91 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index a05218ff3fe4..f089a264cd38 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 751c3373a92c..7b0356dca562 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 0569bfac4afb..438f86573dc5 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 2d1f5638974c..fb6b831c1fba 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 052f7f6d0551..580bd5ff828f 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -26,3 +26,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
new file mode 100644
index 000000000000..0b9c68429a1a
--- /dev/null
+++ b/arch/unicore32/include/asm/section-core.h
@@ -0,0 +1,19 @@
+#ifndef __UNICORE_SECTION_CORE_ASM_H__
+#define __UNICORE_SECTION_CORE_ASM_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/.
+ */
+
+/* Unicore32 has known to not work properly with the type set, so ignore it */
+
+#define __set_section_core_type(___section, ___core, ___name,		\
+				___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags
+
+#include <asm-generic/section-core.h>
+
+#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 2b892e2313a9..af975f21eeee 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
+generic-y += section-core.h
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index b7fbaa56b51a..7879c31e66a7 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..efc753e80d76
--- /dev/null
+++ b/include/asm-generic/section-core.h
@@ -0,0 +1,307 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Linux ELF program specific sections
+ *
+ * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and
+ * definition of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
+ * sections. This chapter is dedicated to documenting Linux program specific
+ * sections and helpers available to make use of these easier to implement and
+ * use.
+ *
+ * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
+ */
+
+/**
+ * DOC: Linux linker script
+ *
+ * Linux uses a custom linker script to build the vmlinux binary, it uses it to
+ * strategically place and define Linux ELF sections.  Each architecture needs
+ * to implement its own linker script, it is expected to reside in
+ * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
+ * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
+ * as well as some helpers documented in this chapter.
+ *
+ * In assembly it is common practice to use dots (``.``) in labels to avoid
+ * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
+ * name but not a C symbol. Historically then, two dots are used (``..``)
+ * have been used in linker scripts when adding program specific sections
+ * when there are concerns to avoid clashes with compiler generated sections.
+ */
+
+/**
+ * DOC: Memory protection
+ *
+ * Linux allows architectures which support memory protection features to
+ * take advantage of them by letting architectures define and enable
+ * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.
+ * mark_rodata_ro() can be used for instance to mark specific sections as
+ * read-only or non-executable.
+ *
+ * Linux typically follows a convention to have the .rodata ELF section follow
+ * after the .text ELF section, it does this to help architectures which
+ * support memory protection to mark both .text and .rodata as read-only in
+ * one shot.
+ *
+ * For more details refer to mark_rodata_ro().
+ */
+
+/**
+ * DOC: .rodata
+ *
+ * ELF section used for data which must be protected from write access.
+ */
+
+/**
+ * DOC: .text
+ *
+ * ELF section name used for code (functions) used during regular
+ * kernel run time.
+ */
+
+/**
+ * DOC: .data
+ *
+ * ELF section used for read-write data.
+ */
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: .init.text
+ *
+ * ELF section for code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+
+/**
+ * DOC: .init.data
+ *
+ * ELF section used for data structures used only during boot or driver
+ * initialization.
+ */
+
+/**
+ * DOC: .init.rodata
+ *
+ * ELF section used for read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+
+/**
+ * DOC: .initcall
+ *
+ * ELF section used for subsystem init calls. There are init levels
+ * representing different functionality in the kernel. For more details
+ * refer to __define_initcall().
+ */
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: .exit.text
+ *
+ * ELF section used to for code (functions) used only during module unload.
+ */
+
+/**
+ * DOC: .exit.data
+ *
+ * ELF section used to for data structures used only during module
+ * unload.
+ */
+
+/**
+ * DOC: .exitcall.exit
+ *
+ * ELF section used for exit routines, order is important and maintained by
+ * link order.
+ */
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: .ref.text
+ *
+ * ELF section used to annotate code (functions) which has been vetted as
+ * valid for its reference or use of other code (functions) or data structures
+ * which are part of the init sections.
+ */
+
+/**
+ * DOC: .ref.data
+ *
+ * ELF section used for data structures which have been vetted for its
+ * reference or use of other code (functions) or data structures part of the
+ * init sections.
+ */
+
+/**
+ * DOC: .ref.rodata
+ *
+ * ELF section used to annotate const code (functions) const data structures
+ * which has been vetted for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section..___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section..__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifndef LINKER_SCRIPT
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align\x16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 4df64a1fc09e..b145ae8d9cbe 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_GENERIC_SECTIONS_H_
 #define _ASM_GENERIC_SECTIONS_H_
 
+#include <asm/section-core.h>
+
 /* References to section boundaries */
 
 #include <linux/compiler.h>
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 0968d13b3885..483f60c451f9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -55,6 +55,7 @@
 #endif
 
 #include <linux/export.h>
+#include <asm/section-core.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
diff --git a/include/linux/init.h b/include/linux/init.h
index 885c3e6d0f9d..21c6bec9e3d0 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -130,6 +130,24 @@ int __init init_rootfs(void);
 extern bool rodata_enabled;
 #endif
 #ifdef CONFIG_DEBUG_RODATA
+/**
+ * mark_rodata_ro - implement memory protection for ELF sections
+ *
+ * Architectures which support memory protection define a kernel configuration
+ * entry for CONFIG_DEBUG_RODATA, enable it in and implement mark_rodata_ro().
+ * mark_rodata_ro() should strive to adjust the .rodata and .text ELF sections
+ * with read-only memory protection to prevent modifications of these sections
+ * after bootup. It can also try to use memory protection to prevent execution
+ * on the .rodata ELF section.
+ *
+ * In order to help architectures set both .text and .rodata as read-only with
+ * memory protections in one shot Linux has typically followed the convention
+ * to have the .rodata ELF section follow the .text ELF section on the vmlinux
+ * linker script.
+ *
+ * Linux calls mark_rodata_ro() after freeing .init code and prior to calling
+ * the first init userspace process.
+ */
 void mark_rodata_ro(void);
 #endif
 
@@ -140,25 +158,70 @@ extern bool initcall_debug;
 #endif
   
 #ifndef MODULE
+/**
+ * DOC: Initcall levels
+ *
+ * When Linux boots the kernel do_initcalls() iterates over each Linux
+ * initialization level ID and calls all routines embedded on each level ID.
+ * Prior to v2.5.2.3 Linux had only one init level onto which all init
+ * functions folded onto using __initcall(). After v2.5.2.4 Linux split up
+ * initcalls into 7 separate initcall subsection levels, each level describing
+ * different functionality part of the kernel (commit `9d6ba121b7e17085`_
+ * (v2.5.2.3 -> v2.5.2.4)). In order to remain backward compatible __initcall()
+ * calls were left mapped to device_initcall().
+ *
+ * Each init level consists of a dedicated ELF section, init functions are
+ * associated to an init level by linking it into the respective level's
+ * ELF section.
+ *
+ * Lower order init levels run prior to higher order init levels. Ordering
+ * inside each initcall level is determined by respective link order.
+ *
+ * .. _9d6ba121b7e17085: https://git.kernel.org/cgit/linux/kernel/git/history/history.git/commit/?id6ba121b7e17085c95139233686b27a4d4c650e
+ */
 
 #ifndef __ASSEMBLY__
 
-/*
- * initcalls are now grouped by functionality into separate
- * subsections. Ordering inside the subsections is determined
- * by link order. 
- * For backwards compatibility, initcall() puts the call in 
- * the device init subsection.
+/**
+ * __define_initcall - wrapper for defining init levels
  *
- * The `id' arg to __define_initcall() is needed so that multiple initcalls
- * can point at the same handler without causing duplicate-symbol build errors.
+ * @fn: init routine
+ * @id: init level
  *
- * Initcalls are run by placing pointers in initcall sections that the
- * kernel iterates at runtime. The linker can do dead code / data elimination
- * and remove that completely, so the initcall sections have to be marked
- * as KEEP() in the linker script.
+ * Defines a kernel initialization level. A respective linker script entry
+ * is required to ensure the init level is accounted for and to ensure symbols
+ * exist for iterating over all functions in the init level. A init level
+ * represents a series of functionality in the kernel.
+ *
+ * Ordering within an initialization level is determined by link order, so
+ * for instance if a Makefile had::
+ *
+ *	obj-y += foo.o
+ *	obj-y += bar.o
+ *
+ * And foo.c::
+ *
+ *	subsys_initcall(foo_init);
+ *
+ * And bar.c had::
+ *
+ *	subsys_initcall(bar_init);
+ *
+ * foo_init() would be called prior to bar_init().
+ *
+ * Note that @id in __define_initcall() also enables multiple initcalls
+ * to be created using the same handler for different init levels without
+ * causing duplicate-symbol build errors.
+ *
+ * Initcalls are run by placing start symbols to initcall levels inside ELF
+ * sections, the kernel in turn uses these symbols to iterate over each init
+ * level at runtime with do_initcall_level(). The end of each init level is
+ * marked by the subsequent symbol's start address until we reach the symbol
+ * ``__initcall_end``. The linker can do dead code / data elimination and each
+ * init level start symbol could be removed completely in this process, to
+ * avoid this each init level start symbols must be marked as 'KEEP()' in the
+ * linker script to avoid any linker optimization heuristic on initcalls.
  */
-
 #define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
 	__attribute__((__section__(".initcall" #id ".init"))) = fn;
diff --git a/include/linux/sections.h b/include/linux/sections.h
new file mode 100644
index 000000000000..6771c727bcd1
--- /dev/null
+++ b/include/linux/sections.h
@@ -0,0 +1,87 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_CORE(section, core, name, level)			\
+	#section ".." #core "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 01/14] generic-sections: add section core helpers
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Linux makes extensive use of custom ELF header sections,
documentation for these are well scattered. Unify this
documentation in a central place and provide helpers to
build custom Linux sections.

This also generalizes sections code to enable avoiding
modifying the linker scripts when we want to add new
custom Linux sections. In order to make this generally
useful we need to ensure all architectures can make use of
core section helpers but that they can also override should
this be needed. Instead of relying on section.h this adds
a sections-core.h since this will be targeted to be safe
to be used on asm code, linker scripts and C code.

v7: ran ispell to fix spelling as requested by Boris

v5:

o Huge documentation revamp based on a careful review of the ELF
  specifications. Includes documentation now also about usage of
  two dots (..) when prefixing ELF program specific sections.

o Replace macros for sections names in favor of just using
  the section names explicitly in the linker script. This is
  perhaps more work to grep but this is what folks seem to
  currently prefer.

o Fix .text and .rodata documentation to explain memory protection
  strategies which architectures can embrace upon initialization
  (documents CONFIG_DEBUG_RODATA and mark_rodata_ro())

o Skip the 'Linux section ordering' documentation section, we'll instead
  add this on subsequent patch which will expand on it considerably

o Dropped tree on MAINTAINERS -- as per discussions with Arnd, hpa and
  Josh, its easier to just let changes for sections go in through the
  respective tree that needs the changes.

o Fix typos on documentation

o Dropped SECTION_ALL(), __SECTION_CORE(), SECTION_CORE_ALL() macros
  since we are favoring using explicit section names. These are
  useless if we are being explicit.

o Drop LINUX_SECTION_SIZE(), LINUX_SECTION_EMPTY() in favor of having
  section ranges and linker tables define their own, to avoid confusion
  and make code more readable.

o Add __define_initcall() documentation and a small section describing
  our current initcall levels. This should help also clarify what was
  meant about keeping backward compatibility.

v4:

o Port to shiny new sphinx documentation format

o fix a unicore32 build, turns out this actually fixes unicore32
  defconfig builds which were failing for a long while. unicore32
  does not seem to grok well the type passed on a section declaration,
  this ignores it.

o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
  this was causing final linker issues with blackfin -- this is
  a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
  being metatag. metatag is not supported on 0-day so I cannot confirm
  compilation there.

o Added SECTION_CORE() for C code, used later by __LINUX_RANGE()

o Since SECTION_CORE() is defined for linker script and C code, share
  the same helper and just use a __stringify() for the C code as is done
  for the other C helpers.

o move generic sections to asm-generic/section-core.h instead.
  PowerPC compilation blows up if asm/jump_labels.h gets
  section.h included, fixing this is not in any way easy.
  The list of issues are endless. Moving new data to a new
  simple file resolves this.

o since things are now in asm-generic/section-core.h the
  guard changes on asm-generic/sections.h and each architecture
  sections.h are no longer needed

o Give generic sections some maintainer love, that change is
  Acked-by Arnd Bergmann, Josh and hpa.

o A few checkpatch.pl style fixes

o As suggested by James Hogan use generic-y to copy generic
  header files on architectures that do not have a sections.h
  instead of writing a simple file only to include the generic one.

v3:

o add missing sections.h for architectures that did not
  have it

o move generic sections to asm-generic/sections.h

o add generic asm helpers section_type(), section_type_asmtype(),
  push_section_type() -- these helpers enable easy use for
  for later declaring and using of custom Linux sections using
  more standard APIs in both C code, asm code (C asm calls, or
  asm files), enabling future standardized section types to
  be more immediately accessible to asm code, not just C code.
  Note for ASM_CMD_SEP we use by default "\n", architectures needed
  to override can do so on their own sections.h prior to inclusion
  of asm-generic/sections.h

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/index.rst                   |   1 +
 Documentation/sections/background.rst     | 105 ++++++++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  17 ++
 Documentation/sections/section-core.rst   | 148 ++++++++++++++
 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/Kbuild               |   1 +
 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/section-core.h |  19 ++
 arch/x86/include/asm/Kbuild               |   1 +
 arch/xtensa/include/asm/Kbuild            |   1 +
 include/asm-generic/section-core.h        | 307 ++++++++++++++++++++++++++++++
 include/asm-generic/sections.h            |   2 +
 include/asm-generic/vmlinux.lds.h         |   1 +
 include/linux/init.h                      |  89 +++++++--
 include/linux/sections.h                  |  87 +++++++++
 42 files changed, 809 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/linux/sections.h

diff --git a/Documentation/index.rst b/Documentation/index.rst
index cb5d77699c60..71e0305c036d 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -57,6 +57,7 @@ needed).
    media/index
    gpu/index
    security/index
+   sections/index
    sound/index
    crypto/index
 
diff --git a/Documentation/sections/background.rst b/Documentation/sections/background.rst
new file mode 100644
index 000000000000..4f04c0682a6f
--- /dev/null
+++ b/Documentation/sections/background.rst
@@ -0,0 +1,105 @@
+======================
+ELF section background
+======================
+
+About
+=====
+
+The purpose of this chapter is to help those not familiar with ELF to brush up
+the latest ELF specifications in order to help understand how Linux uses and
+defines its own ELF sections.
+
+Standardized ELF
+================
+
+The first publication documenting ELF was UNIX System Laboratories' (USL)
+*System V Release 4 Application Binary Interface* (`SRV4 ABI`_) specification.
+Originally ELF was only a small part of the SRV4 ABI, with time however new
+specifications only put focus on ELF, such was the case of the *TIS Portable
+Formats Specification version 1.2* (`TIS 1.2`_). As of TIS 1.2, ELF was
+supplemented with processor specific ELF addendums, available on the *Linux
+Foundation referenced specification page* (`LF ref page`_). The latest ELF
+specification is the *System V Application Binary Interface - DRAFT - 24 April
+2001* (`gabi4`_).
+
+.. _SRV4 ABI: http://www.sco.com/developers/devspecs/gabi41.pdf
+.. _TIS 1.2: https://refspecs.linuxbase.org/elf/elf.pdf
+.. _LF ref page: https://refspecs.linuxbase.org/
+.. _gabi4: https://refspecs.linuxbase.org/elf/gabi4+/contents.html
+
+ELF views on Linux
+==================
+
+There are two views which can be used for inspecting data in an ELF file, a
+Linking view, and an Execution view. A Section Header Table enables one to
+describe an object using the Linking view while a Program Header Table enables
+one to describe an object using the Execution view. The views are not mutually
+exclusive. For instance, vmlinux can be viewed under both views, ``readelf -S
+vmlinux`` for the Linking view, and ``readelf -l vmlinux`` for the Execution
+view.  In Linux only the vmlinux file will have an Execution view, even modules
+lack an Execution view given that vmlinux is the only file that describes how
+the the kernel runs from the start.  All other Linux kernel object files have
+an available Linking view.
+
+Under the Linking view, the Section Header Table describes all available
+sections. The Section Header Table is an array of ELF section header data
+structures. If on a 32-bit system this is ``struct elf32_shd``, if on a 64-bit
+this is ``struct elf64_shdr``. Sections are only visible on object files that
+have a Linking view, since all Linux kernel files have Linking view, all kernel
+objects have ELF sections.
+
+Limitations on ELF sections
+===========================
+
+We provide a summary on the limitations of ELF sections. Refer to the public
+ELF specifications for details. Note that 64-bit limitations may depend
+on processor specific section attributes to be used, refer to your processor
+specification if unsure.
+
+Its worth elaborating on the limitations on the name of an ELF section:
+ELF section names are stored as strings as per the ELF specification, and
+as can be expected, these don't have explicit limitations. The implicit
+limitation then depends on the size of an ELF object file and ELF section.
+
+If using really large kernels or objects with large amounts of sections one
+would still need to be sure that ELF loader in charge of loading the Linux
+kernel is properly updated to handle coping with the latest ELF extensions.
+
+   .. flat-table:: Limitations on ELF Sections
+
+      * - Section attribute
+        - 32-bit
+        - 64-bit
+
+      * - ELF section name
+        - Size of an ELF section
+        - Size of an ELF section
+
+      * - Size of an ELF section
+        - 4 GiB
+        - 16 EiB
+
+      * - Max number of sections in an object file
+        - 4 GiEntries (4294967296)
+        - 16 EiEntries (18446744073709551616)
+
+Program specific ELF sections
+=============================
+
+The ELF specification allows for a section type to be specified as
+*Program specific section*, defined as ``SHT_PROGBITS``. This sections type
+enables programs to customize sections for their own use. In assembly this
+specified ``@progbits`` on most architectures, on ARM this is ``%progbits``.
+
+``SHT_PROGBITS`` is used by Linux for defining and using Linux ELF sections.
+
+Special ELF Sections
+====================
+
+The ELF specification defines *Special ELF Sections* on chapter 4 (`gabi4
+ch4`_). These are defined as sections which hold program and control
+information. Of these sections, a few have the section type as
+``SHT_PROGBITS``. This enables Linux to *further customize* use of the section
+beyond what the ELF specification suggests.
+
+.. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
new file mode 100644
index 000000000000..faa1c57595e1
--- /dev/null
+++ b/Documentation/sections/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel ELF sections'
+html_search_language = 'en'
diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
new file mode 100644
index 000000000000..f37511ef05e7
--- /dev/null
+++ b/Documentation/sections/index.rst
@@ -0,0 +1,17 @@
+=========================
+Linux Kernel ELF sections
+=========================
+
+This book documents the different ELF sections used on the Linux kernel.
+We start off by providing references to how ELF was standardized, references
+to the standards on ELF sections, review limitations of ELF sections, and
+finally how Linux uses ELF sections in the Linux kernel. Certain important
+Linux ELF sections are documented carefully: we describe the goal of the
+ELF section, and address concurrency considerations when applicable. A few
+common a set of Linux helpers for ELF sections are also documented.
+
+.. toctree::
+   :maxdepth: 4
+
+   background
+   section-core
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
new file mode 100644
index 000000000000..ac5815a0d9b3
--- /dev/null
+++ b/Documentation/sections/section-core.rst
@@ -0,0 +1,148 @@
+===================================
+Linux ELF program specific sections
+===================================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux ELF program specific sections
+
+Linux linker script
+===================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux linker script
+
+Memory protection
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Memory protection
+
+mark_rodata_ro
+-----------------------
+.. kernel-doc:: include/linux/init.h
+   :functions: mark_rodata_ro
+
+.rodata
+-------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .rodata
+
+.text
+-----
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .text
+
+.data
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .data
+
+Linux .init\* sections
+======================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux init sections
+
+.init.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.text
+
+.init.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.data
+
+.init.rodata
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.rodata
+
+Initcall levels
+---------------
+.. kernel-doc:: include/linux/init.h
+   :doc: Initcall levels
+
+.initcall
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .initcall
+
+__define_initcall
+-----------------
+.. kernel-doc:: include/linux/init.h
+   :functions: __define_initcall
+
+Linux .exit\* sections
+======================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux exit sections
+
+.exit.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.text
+
+.exit.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.data
+
+.exitcall.exit
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exitcall.exit
+
+Linux .ref\* sections
+=====================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux references to init sections
+
+.ref.text
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.text
+
+.ref.data
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.data
+
+.ref.rodata
+-----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.rodata
+
+Generic Linux kernel section helpers
+====================================
+
+Introduction
+-------------
+.. kernel-doc:: include/linux/sections.h
+   :doc: Introduction
+
+LINUX_SECTION_ALIGNMENT
+-----------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_ALIGNMENT
+
+LINUX_SECTION_START
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_START
+
+LINUX_SECTION_END
+-----------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_END
+
+DECLARE_LINUX_SECTION
+---------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION
+
+DECLARE_LINUX_SECTION_RO
+------------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION_RO
diff --git a/MAINTAINERS b/MAINTAINERS
index d2db7fecef32..5e580b1257fb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5438,6 +5438,18 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTIONS
+M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
+M:	Josh Poimboeuf <jpoimboe@redhat.com>
+M:	"H. Peter Anvin" <hpa@zytor.com>
+L:	linux-arch@vger.kernel.org
+L:	linux-kernel@vger.kernel.org
+S:	Supported
+F:	include/asm-generic/section-core.h
+F:	include/asm-generic/sections.h
+F:	include/asm-generic/vmlinux.lds.h
+F:	Documentation/sections/section-core.rst
+
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index bf8475ce85ee..5422827f1585 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += section-core.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index c332604606dd..7b2cb3dea5fc 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index efb21757d41f..9b69a22a9ae1 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += unaligned.h
 
 generated-y += mach-types.h
 generated-y += unistd-nr.h
+generic-y += section-core.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 8365a84c2640..00ace5e826f1 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 241b9b9729d8..f2c3b656a0e7 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 2fb67b59d188..bf20541bcf21 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -47,3 +47,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 64465e7e2245..38127ce747be 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -62,3 +62,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 1778805f6380..385cd88a9d9e 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += types.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 1fa084cf1a43..46d7c599d9b8 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 373cb23301e3..1ec04ec1c82b 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -75,3 +75,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index db8ddabc6bd2..37d7bfae7619 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -60,3 +60,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 502a91d8dbbd..672c6d5da18c 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 6e69d2c42eee..8ccfb5eb9678 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1f2e5d31cb24..1277b45bf4f9 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -34,3 +34,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 167150c701d1..b1011375cd7a 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -55,3 +55,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index b0ae88c9fed9..c6c2cf6edc98 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index ed07179fe26a..7a932b4a5531 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 1c8dd0f5cd5d..f8145bc85835 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index d63330e88379..c9c7cb82b00f 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 2832f031fb11..86175e701869 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -71,3 +71,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 91f53c07f410..18a9d4c5ead7 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -28,3 +28,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 5c4fbc80dc6c..4322d9746cdb 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
+generic-y += section-core.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 8aea32fe8bd2..63a1c2924b91 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index a05218ff3fe4..f089a264cd38 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 751c3373a92c..7b0356dca562 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 0569bfac4afb..438f86573dc5 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 2d1f5638974c..fb6b831c1fba 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 052f7f6d0551..580bd5ff828f 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -26,3 +26,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
new file mode 100644
index 000000000000..0b9c68429a1a
--- /dev/null
+++ b/arch/unicore32/include/asm/section-core.h
@@ -0,0 +1,19 @@
+#ifndef __UNICORE_SECTION_CORE_ASM_H__
+#define __UNICORE_SECTION_CORE_ASM_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/.
+ */
+
+/* Unicore32 has known to not work properly with the type set, so ignore it */
+
+#define __set_section_core_type(___section, ___core, ___name,		\
+				___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags
+
+#include <asm-generic/section-core.h>
+
+#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 2b892e2313a9..af975f21eeee 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
+generic-y += section-core.h
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index b7fbaa56b51a..7879c31e66a7 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..efc753e80d76
--- /dev/null
+++ b/include/asm-generic/section-core.h
@@ -0,0 +1,307 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Linux ELF program specific sections
+ *
+ * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and
+ * definition of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
+ * sections. This chapter is dedicated to documenting Linux program specific
+ * sections and helpers available to make use of these easier to implement and
+ * use.
+ *
+ * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
+ */
+
+/**
+ * DOC: Linux linker script
+ *
+ * Linux uses a custom linker script to build the vmlinux binary, it uses it to
+ * strategically place and define Linux ELF sections.  Each architecture needs
+ * to implement its own linker script, it is expected to reside in
+ * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
+ * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
+ * as well as some helpers documented in this chapter.
+ *
+ * In assembly it is common practice to use dots (``.``) in labels to avoid
+ * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
+ * name but not a C symbol. Historically then, two dots are used (``..``)
+ * have been used in linker scripts when adding program specific sections
+ * when there are concerns to avoid clashes with compiler generated sections.
+ */
+
+/**
+ * DOC: Memory protection
+ *
+ * Linux allows architectures which support memory protection features to
+ * take advantage of them by letting architectures define and enable
+ * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.
+ * mark_rodata_ro() can be used for instance to mark specific sections as
+ * read-only or non-executable.
+ *
+ * Linux typically follows a convention to have the .rodata ELF section follow
+ * after the .text ELF section, it does this to help architectures which
+ * support memory protection to mark both .text and .rodata as read-only in
+ * one shot.
+ *
+ * For more details refer to mark_rodata_ro().
+ */
+
+/**
+ * DOC: .rodata
+ *
+ * ELF section used for data which must be protected from write access.
+ */
+
+/**
+ * DOC: .text
+ *
+ * ELF section name used for code (functions) used during regular
+ * kernel run time.
+ */
+
+/**
+ * DOC: .data
+ *
+ * ELF section used for read-write data.
+ */
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: .init.text
+ *
+ * ELF section for code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+
+/**
+ * DOC: .init.data
+ *
+ * ELF section used for data structures used only during boot or driver
+ * initialization.
+ */
+
+/**
+ * DOC: .init.rodata
+ *
+ * ELF section used for read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+
+/**
+ * DOC: .initcall
+ *
+ * ELF section used for subsystem init calls. There are init levels
+ * representing different functionality in the kernel. For more details
+ * refer to __define_initcall().
+ */
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: .exit.text
+ *
+ * ELF section used to for code (functions) used only during module unload.
+ */
+
+/**
+ * DOC: .exit.data
+ *
+ * ELF section used to for data structures used only during module
+ * unload.
+ */
+
+/**
+ * DOC: .exitcall.exit
+ *
+ * ELF section used for exit routines, order is important and maintained by
+ * link order.
+ */
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: .ref.text
+ *
+ * ELF section used to annotate code (functions) which has been vetted as
+ * valid for its reference or use of other code (functions) or data structures
+ * which are part of the init sections.
+ */
+
+/**
+ * DOC: .ref.data
+ *
+ * ELF section used for data structures which have been vetted for its
+ * reference or use of other code (functions) or data structures part of the
+ * init sections.
+ */
+
+/**
+ * DOC: .ref.rodata
+ *
+ * ELF section used to annotate const code (functions) const data structures
+ * which has been vetted for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section..___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section..__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifndef LINKER_SCRIPT
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align=16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 4df64a1fc09e..b145ae8d9cbe 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_GENERIC_SECTIONS_H_
 #define _ASM_GENERIC_SECTIONS_H_
 
+#include <asm/section-core.h>
+
 /* References to section boundaries */
 
 #include <linux/compiler.h>
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 0968d13b3885..483f60c451f9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -55,6 +55,7 @@
 #endif
 
 #include <linux/export.h>
+#include <asm/section-core.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
diff --git a/include/linux/init.h b/include/linux/init.h
index 885c3e6d0f9d..21c6bec9e3d0 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -130,6 +130,24 @@ int __init init_rootfs(void);
 extern bool rodata_enabled;
 #endif
 #ifdef CONFIG_DEBUG_RODATA
+/**
+ * mark_rodata_ro - implement memory protection for ELF sections
+ *
+ * Architectures which support memory protection define a kernel configuration
+ * entry for CONFIG_DEBUG_RODATA, enable it in and implement mark_rodata_ro().
+ * mark_rodata_ro() should strive to adjust the .rodata and .text ELF sections
+ * with read-only memory protection to prevent modifications of these sections
+ * after bootup. It can also try to use memory protection to prevent execution
+ * on the .rodata ELF section.
+ *
+ * In order to help architectures set both .text and .rodata as read-only with
+ * memory protections in one shot Linux has typically followed the convention
+ * to have the .rodata ELF section follow the .text ELF section on the vmlinux
+ * linker script.
+ *
+ * Linux calls mark_rodata_ro() after freeing .init code and prior to calling
+ * the first init userspace process.
+ */
 void mark_rodata_ro(void);
 #endif
 
@@ -140,25 +158,70 @@ extern bool initcall_debug;
 #endif
   
 #ifndef MODULE
+/**
+ * DOC: Initcall levels
+ *
+ * When Linux boots the kernel do_initcalls() iterates over each Linux
+ * initialization level ID and calls all routines embedded on each level ID.
+ * Prior to v2.5.2.3 Linux had only one init level onto which all init
+ * functions folded onto using __initcall(). After v2.5.2.4 Linux split up
+ * initcalls into 7 separate initcall subsection levels, each level describing
+ * different functionality part of the kernel (commit `9d6ba121b7e17085`_
+ * (v2.5.2.3 -> v2.5.2.4)). In order to remain backward compatible __initcall()
+ * calls were left mapped to device_initcall().
+ *
+ * Each init level consists of a dedicated ELF section, init functions are
+ * associated to an init level by linking it into the respective level's
+ * ELF section.
+ *
+ * Lower order init levels run prior to higher order init levels. Ordering
+ * inside each initcall level is determined by respective link order.
+ *
+ * .. _9d6ba121b7e17085: https://git.kernel.org/cgit/linux/kernel/git/history/history.git/commit/?id=9d6ba121b7e17085c95139233686b27a4d4c650e
+ */
 
 #ifndef __ASSEMBLY__
 
-/*
- * initcalls are now grouped by functionality into separate
- * subsections. Ordering inside the subsections is determined
- * by link order. 
- * For backwards compatibility, initcall() puts the call in 
- * the device init subsection.
+/**
+ * __define_initcall - wrapper for defining init levels
  *
- * The `id' arg to __define_initcall() is needed so that multiple initcalls
- * can point at the same handler without causing duplicate-symbol build errors.
+ * @fn: init routine
+ * @id: init level
  *
- * Initcalls are run by placing pointers in initcall sections that the
- * kernel iterates at runtime. The linker can do dead code / data elimination
- * and remove that completely, so the initcall sections have to be marked
- * as KEEP() in the linker script.
+ * Defines a kernel initialization level. A respective linker script entry
+ * is required to ensure the init level is accounted for and to ensure symbols
+ * exist for iterating over all functions in the init level. A init level
+ * represents a series of functionality in the kernel.
+ *
+ * Ordering within an initialization level is determined by link order, so
+ * for instance if a Makefile had::
+ *
+ *	obj-y += foo.o
+ *	obj-y += bar.o
+ *
+ * And foo.c::
+ *
+ *	subsys_initcall(foo_init);
+ *
+ * And bar.c had::
+ *
+ *	subsys_initcall(bar_init);
+ *
+ * foo_init() would be called prior to bar_init().
+ *
+ * Note that @id in __define_initcall() also enables multiple initcalls
+ * to be created using the same handler for different init levels without
+ * causing duplicate-symbol build errors.
+ *
+ * Initcalls are run by placing start symbols to initcall levels inside ELF
+ * sections, the kernel in turn uses these symbols to iterate over each init
+ * level at runtime with do_initcall_level(). The end of each init level is
+ * marked by the subsequent symbol's start address until we reach the symbol
+ * ``__initcall_end``. The linker can do dead code / data elimination and each
+ * init level start symbol could be removed completely in this process, to
+ * avoid this each init level start symbols must be marked as 'KEEP()' in the
+ * linker script to avoid any linker optimization heuristic on initcalls.
  */
-
 #define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
 	__attribute__((__section__(".initcall" #id ".init"))) = fn;
diff --git a/include/linux/sections.h b/include/linux/sections.h
new file mode 100644
index 000000000000..6771c727bcd1
--- /dev/null
+++ b/include/linux/sections.h
@@ -0,0 +1,87 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_CORE(section, core, name, level)			\
+	#section ".." #core "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 01/14] generic-sections: add section core helpers
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

Linux makes extensive use of custom ELF header sections,
documentation for these are well scattered. Unify this
documentation in a central place and provide helpers to
build custom Linux sections.

This also generalizes sections code to enable avoiding
modifying the linker scripts when we want to add new
custom Linux sections. In order to make this generally
useful we need to ensure all architectures can make use of
core section helpers but that they can also override should
this be needed. Instead of relying on section.h this adds
a sections-core.h since this will be targeted to be safe
to be used on asm code, linker scripts and C code.

v7: ran ispell to fix spelling as requested by Boris

v5:

o Huge documentation revamp based on a careful review of the ELF
  specifications. Includes documentation now also about usage of
  two dots (..) when prefixing ELF program specific sections.

o Replace macros for sections names in favor of just using
  the section names explicitly in the linker script. This is
  perhaps more work to grep but this is what folks seem to
  currently prefer.

o Fix .text and .rodata documentation to explain memory protection
  strategies which architectures can embrace upon initialization
  (documents CONFIG_DEBUG_RODATA and mark_rodata_ro())

o Skip the 'Linux section ordering' documentation section, we'll instead
  add this on subsequent patch which will expand on it considerably

o Dropped tree on MAINTAINERS -- as per discussions with Arnd, hpa and
  Josh, its easier to just let changes for sections go in through the
  respective tree that needs the changes.

o Fix typos on documentation

o Dropped SECTION_ALL(), __SECTION_CORE(), SECTION_CORE_ALL() macros
  since we are favoring using explicit section names. These are
  useless if we are being explicit.

o Drop LINUX_SECTION_SIZE(), LINUX_SECTION_EMPTY() in favor of having
  section ranges and linker tables define their own, to avoid confusion
  and make code more readable.

o Add __define_initcall() documentation and a small section describing
  our current initcall levels. This should help also clarify what was
  meant about keeping backward compatibility.

v4:

o Port to shiny new sphinx documentation format

o fix a unicore32 build, turns out this actually fixes unicore32
  defconfig builds which were failing for a long while. unicore32
  does not seem to grok well the type passed on a section declaration,
  this ignores it.

o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
  this was causing final linker issues with blackfin -- this is
  a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
  being metatag. metatag is not supported on 0-day so I cannot confirm
  compilation there.

o Added SECTION_CORE() for C code, used later by __LINUX_RANGE()

o Since SECTION_CORE() is defined for linker script and C code, share
  the same helper and just use a __stringify() for the C code as is done
  for the other C helpers.

o move generic sections to asm-generic/section-core.h instead.
  PowerPC compilation blows up if asm/jump_labels.h gets
  section.h included, fixing this is not in any way easy.
  The list of issues are endless. Moving new data to a new
  simple file resolves this.

o since things are now in asm-generic/section-core.h the
  guard changes on asm-generic/sections.h and each architecture
  sections.h are no longer needed

o Give generic sections some maintainer love, that change is
  Acked-by Arnd Bergmann, Josh and hpa.

o A few checkpatch.pl style fixes

o As suggested by James Hogan use generic-y to copy generic
  header files on architectures that do not have a sections.h
  instead of writing a simple file only to include the generic one.

v3:

o add missing sections.h for architectures that did not
  have it

o move generic sections to asm-generic/sections.h

o add generic asm helpers section_type(), section_type_asmtype(),
  push_section_type() -- these helpers enable easy use for
  for later declaring and using of custom Linux sections using
  more standard APIs in both C code, asm code (C asm calls, or
  asm files), enabling future standardized section types to
  be more immediately accessible to asm code, not just C code.
  Note for ASM_CMD_SEP we use by default "\n", architectures needed
  to override can do so on their own sections.h prior to inclusion
  of asm-generic/sections.h

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/index.rst                   |   1 +
 Documentation/sections/background.rst     | 105 ++++++++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  17 ++
 Documentation/sections/section-core.rst   | 148 ++++++++++++++
 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/Kbuild               |   1 +
 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/section-core.h |  19 ++
 arch/x86/include/asm/Kbuild               |   1 +
 arch/xtensa/include/asm/Kbuild            |   1 +
 include/asm-generic/section-core.h        | 307 ++++++++++++++++++++++++++++++
 include/asm-generic/sections.h            |   2 +
 include/asm-generic/vmlinux.lds.h         |   1 +
 include/linux/init.h                      |  89 +++++++--
 include/linux/sections.h                  |  87 +++++++++
 42 files changed, 809 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/linux/sections.h

diff --git a/Documentation/index.rst b/Documentation/index.rst
index cb5d77699c60..71e0305c036d 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -57,6 +57,7 @@ needed).
    media/index
    gpu/index
    security/index
+   sections/index
    sound/index
    crypto/index
 
diff --git a/Documentation/sections/background.rst b/Documentation/sections/background.rst
new file mode 100644
index 000000000000..4f04c0682a6f
--- /dev/null
+++ b/Documentation/sections/background.rst
@@ -0,0 +1,105 @@
+======================
+ELF section background
+======================
+
+About
+=====
+
+The purpose of this chapter is to help those not familiar with ELF to brush up
+the latest ELF specifications in order to help understand how Linux uses and
+defines its own ELF sections.
+
+Standardized ELF
+================
+
+The first publication documenting ELF was UNIX System Laboratories' (USL)
+*System V Release 4 Application Binary Interface* (`SRV4 ABI`_) specification.
+Originally ELF was only a small part of the SRV4 ABI, with time however new
+specifications only put focus on ELF, such was the case of the *TIS Portable
+Formats Specification version 1.2* (`TIS 1.2`_). As of TIS 1.2, ELF was
+supplemented with processor specific ELF addendums, available on the *Linux
+Foundation referenced specification page* (`LF ref page`_). The latest ELF
+specification is the *System V Application Binary Interface - DRAFT - 24 April
+2001* (`gabi4`_).
+
+.. _SRV4 ABI: http://www.sco.com/developers/devspecs/gabi41.pdf
+.. _TIS 1.2: https://refspecs.linuxbase.org/elf/elf.pdf
+.. _LF ref page: https://refspecs.linuxbase.org/
+.. _gabi4: https://refspecs.linuxbase.org/elf/gabi4+/contents.html
+
+ELF views on Linux
+==================
+
+There are two views which can be used for inspecting data in an ELF file, a
+Linking view, and an Execution view. A Section Header Table enables one to
+describe an object using the Linking view while a Program Header Table enables
+one to describe an object using the Execution view. The views are not mutually
+exclusive. For instance, vmlinux can be viewed under both views, ``readelf -S
+vmlinux`` for the Linking view, and ``readelf -l vmlinux`` for the Execution
+view.  In Linux only the vmlinux file will have an Execution view, even modules
+lack an Execution view given that vmlinux is the only file that describes how
+the the kernel runs from the start.  All other Linux kernel object files have
+an available Linking view.
+
+Under the Linking view, the Section Header Table describes all available
+sections. The Section Header Table is an array of ELF section header data
+structures. If on a 32-bit system this is ``struct elf32_shd``, if on a 64-bit
+this is ``struct elf64_shdr``. Sections are only visible on object files that
+have a Linking view, since all Linux kernel files have Linking view, all kernel
+objects have ELF sections.
+
+Limitations on ELF sections
+===========================
+
+We provide a summary on the limitations of ELF sections. Refer to the public
+ELF specifications for details. Note that 64-bit limitations may depend
+on processor specific section attributes to be used, refer to your processor
+specification if unsure.
+
+Its worth elaborating on the limitations on the name of an ELF section:
+ELF section names are stored as strings as per the ELF specification, and
+as can be expected, these don't have explicit limitations. The implicit
+limitation then depends on the size of an ELF object file and ELF section.
+
+If using really large kernels or objects with large amounts of sections one
+would still need to be sure that ELF loader in charge of loading the Linux
+kernel is properly updated to handle coping with the latest ELF extensions.
+
+   .. flat-table:: Limitations on ELF Sections
+
+      * - Section attribute
+        - 32-bit
+        - 64-bit
+
+      * - ELF section name
+        - Size of an ELF section
+        - Size of an ELF section
+
+      * - Size of an ELF section
+        - 4 GiB
+        - 16 EiB
+
+      * - Max number of sections in an object file
+        - 4 GiEntries (4294967296)
+        - 16 EiEntries (18446744073709551616)
+
+Program specific ELF sections
+=============================
+
+The ELF specification allows for a section type to be specified as
+*Program specific section*, defined as ``SHT_PROGBITS``. This sections type
+enables programs to customize sections for their own use. In assembly this
+specified ``@progbits`` on most architectures, on ARM this is ``%progbits``.
+
+``SHT_PROGBITS`` is used by Linux for defining and using Linux ELF sections.
+
+Special ELF Sections
+====================
+
+The ELF specification defines *Special ELF Sections* on chapter 4 (`gabi4
+ch4`_). These are defined as sections which hold program and control
+information. Of these sections, a few have the section type as
+``SHT_PROGBITS``. This enables Linux to *further customize* use of the section
+beyond what the ELF specification suggests.
+
+.. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
new file mode 100644
index 000000000000..faa1c57595e1
--- /dev/null
+++ b/Documentation/sections/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel ELF sections'
+html_search_language = 'en'
diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
new file mode 100644
index 000000000000..f37511ef05e7
--- /dev/null
+++ b/Documentation/sections/index.rst
@@ -0,0 +1,17 @@
+=========================
+Linux Kernel ELF sections
+=========================
+
+This book documents the different ELF sections used on the Linux kernel.
+We start off by providing references to how ELF was standardized, references
+to the standards on ELF sections, review limitations of ELF sections, and
+finally how Linux uses ELF sections in the Linux kernel. Certain important
+Linux ELF sections are documented carefully: we describe the goal of the
+ELF section, and address concurrency considerations when applicable. A few
+common a set of Linux helpers for ELF sections are also documented.
+
+.. toctree::
+   :maxdepth: 4
+
+   background
+   section-core
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
new file mode 100644
index 000000000000..ac5815a0d9b3
--- /dev/null
+++ b/Documentation/sections/section-core.rst
@@ -0,0 +1,148 @@
+===================================
+Linux ELF program specific sections
+===================================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux ELF program specific sections
+
+Linux linker script
+===================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux linker script
+
+Memory protection
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Memory protection
+
+mark_rodata_ro
+-----------------------
+.. kernel-doc:: include/linux/init.h
+   :functions: mark_rodata_ro
+
+.rodata
+-------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .rodata
+
+.text
+-----
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .text
+
+.data
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .data
+
+Linux .init\* sections
+======================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux init sections
+
+.init.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.text
+
+.init.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.data
+
+.init.rodata
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.rodata
+
+Initcall levels
+---------------
+.. kernel-doc:: include/linux/init.h
+   :doc: Initcall levels
+
+.initcall
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .initcall
+
+__define_initcall
+-----------------
+.. kernel-doc:: include/linux/init.h
+   :functions: __define_initcall
+
+Linux .exit\* sections
+======================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux exit sections
+
+.exit.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.text
+
+.exit.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.data
+
+.exitcall.exit
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exitcall.exit
+
+Linux .ref\* sections
+=====================
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux references to init sections
+
+.ref.text
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.text
+
+.ref.data
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.data
+
+.ref.rodata
+-----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.rodata
+
+Generic Linux kernel section helpers
+====================================
+
+Introduction
+-------------
+.. kernel-doc:: include/linux/sections.h
+   :doc: Introduction
+
+LINUX_SECTION_ALIGNMENT
+-----------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_ALIGNMENT
+
+LINUX_SECTION_START
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_START
+
+LINUX_SECTION_END
+-----------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_END
+
+DECLARE_LINUX_SECTION
+---------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION
+
+DECLARE_LINUX_SECTION_RO
+------------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION_RO
diff --git a/MAINTAINERS b/MAINTAINERS
index d2db7fecef32..5e580b1257fb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5438,6 +5438,18 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTIONS
+M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
+M:	Josh Poimboeuf <jpoimboe@redhat.com>
+M:	"H. Peter Anvin" <hpa@zytor.com>
+L:	linux-arch@vger.kernel.org
+L:	linux-kernel@vger.kernel.org
+S:	Supported
+F:	include/asm-generic/section-core.h
+F:	include/asm-generic/sections.h
+F:	include/asm-generic/vmlinux.lds.h
+F:	Documentation/sections/section-core.rst
+
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index bf8475ce85ee..5422827f1585 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += section-core.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index c332604606dd..7b2cb3dea5fc 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index efb21757d41f..9b69a22a9ae1 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += unaligned.h
 
 generated-y += mach-types.h
 generated-y += unistd-nr.h
+generic-y += section-core.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 8365a84c2640..00ace5e826f1 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 241b9b9729d8..f2c3b656a0e7 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 2fb67b59d188..bf20541bcf21 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -47,3 +47,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 64465e7e2245..38127ce747be 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -62,3 +62,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 1778805f6380..385cd88a9d9e 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += types.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 1fa084cf1a43..46d7c599d9b8 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 373cb23301e3..1ec04ec1c82b 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -75,3 +75,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index db8ddabc6bd2..37d7bfae7619 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -60,3 +60,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 502a91d8dbbd..672c6d5da18c 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 6e69d2c42eee..8ccfb5eb9678 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1f2e5d31cb24..1277b45bf4f9 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -34,3 +34,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 167150c701d1..b1011375cd7a 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -55,3 +55,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index b0ae88c9fed9..c6c2cf6edc98 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index ed07179fe26a..7a932b4a5531 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 1c8dd0f5cd5d..f8145bc85835 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index d63330e88379..c9c7cb82b00f 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 2832f031fb11..86175e701869 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -71,3 +71,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 91f53c07f410..18a9d4c5ead7 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -28,3 +28,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 5c4fbc80dc6c..4322d9746cdb 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
+generic-y += section-core.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 8aea32fe8bd2..63a1c2924b91 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index a05218ff3fe4..f089a264cd38 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 751c3373a92c..7b0356dca562 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 0569bfac4afb..438f86573dc5 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 2d1f5638974c..fb6b831c1fba 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 052f7f6d0551..580bd5ff828f 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -26,3 +26,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
new file mode 100644
index 000000000000..0b9c68429a1a
--- /dev/null
+++ b/arch/unicore32/include/asm/section-core.h
@@ -0,0 +1,19 @@
+#ifndef __UNICORE_SECTION_CORE_ASM_H__
+#define __UNICORE_SECTION_CORE_ASM_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/.
+ */
+
+/* Unicore32 has known to not work properly with the type set, so ignore it */
+
+#define __set_section_core_type(___section, ___core, ___name,		\
+				___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags
+
+#include <asm-generic/section-core.h>
+
+#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 2b892e2313a9..af975f21eeee 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
+generic-y += section-core.h
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index b7fbaa56b51a..7879c31e66a7 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..efc753e80d76
--- /dev/null
+++ b/include/asm-generic/section-core.h
@@ -0,0 +1,307 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Linux ELF program specific sections
+ *
+ * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and
+ * definition of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
+ * sections. This chapter is dedicated to documenting Linux program specific
+ * sections and helpers available to make use of these easier to implement and
+ * use.
+ *
+ * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
+ */
+
+/**
+ * DOC: Linux linker script
+ *
+ * Linux uses a custom linker script to build the vmlinux binary, it uses it to
+ * strategically place and define Linux ELF sections.  Each architecture needs
+ * to implement its own linker script, it is expected to reside in
+ * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
+ * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
+ * as well as some helpers documented in this chapter.
+ *
+ * In assembly it is common practice to use dots (``.``) in labels to avoid
+ * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
+ * name but not a C symbol. Historically then, two dots are used (``..``)
+ * have been used in linker scripts when adding program specific sections
+ * when there are concerns to avoid clashes with compiler generated sections.
+ */
+
+/**
+ * DOC: Memory protection
+ *
+ * Linux allows architectures which support memory protection features to
+ * take advantage of them by letting architectures define and enable
+ * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.
+ * mark_rodata_ro() can be used for instance to mark specific sections as
+ * read-only or non-executable.
+ *
+ * Linux typically follows a convention to have the .rodata ELF section follow
+ * after the .text ELF section, it does this to help architectures which
+ * support memory protection to mark both .text and .rodata as read-only in
+ * one shot.
+ *
+ * For more details refer to mark_rodata_ro().
+ */
+
+/**
+ * DOC: .rodata
+ *
+ * ELF section used for data which must be protected from write access.
+ */
+
+/**
+ * DOC: .text
+ *
+ * ELF section name used for code (functions) used during regular
+ * kernel run time.
+ */
+
+/**
+ * DOC: .data
+ *
+ * ELF section used for read-write data.
+ */
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: .init.text
+ *
+ * ELF section for code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+
+/**
+ * DOC: .init.data
+ *
+ * ELF section used for data structures used only during boot or driver
+ * initialization.
+ */
+
+/**
+ * DOC: .init.rodata
+ *
+ * ELF section used for read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+
+/**
+ * DOC: .initcall
+ *
+ * ELF section used for subsystem init calls. There are init levels
+ * representing different functionality in the kernel. For more details
+ * refer to __define_initcall().
+ */
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: .exit.text
+ *
+ * ELF section used to for code (functions) used only during module unload.
+ */
+
+/**
+ * DOC: .exit.data
+ *
+ * ELF section used to for data structures used only during module
+ * unload.
+ */
+
+/**
+ * DOC: .exitcall.exit
+ *
+ * ELF section used for exit routines, order is important and maintained by
+ * link order.
+ */
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: .ref.text
+ *
+ * ELF section used to annotate code (functions) which has been vetted as
+ * valid for its reference or use of other code (functions) or data structures
+ * which are part of the init sections.
+ */
+
+/**
+ * DOC: .ref.data
+ *
+ * ELF section used for data structures which have been vetted for its
+ * reference or use of other code (functions) or data structures part of the
+ * init sections.
+ */
+
+/**
+ * DOC: .ref.rodata
+ *
+ * ELF section used to annotate const code (functions) const data structures
+ * which has been vetted for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section..___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section..__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifndef LINKER_SCRIPT
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align=16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 4df64a1fc09e..b145ae8d9cbe 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_GENERIC_SECTIONS_H_
 #define _ASM_GENERIC_SECTIONS_H_
 
+#include <asm/section-core.h>
+
 /* References to section boundaries */
 
 #include <linux/compiler.h>
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 0968d13b3885..483f60c451f9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -55,6 +55,7 @@
 #endif
 
 #include <linux/export.h>
+#include <asm/section-core.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
diff --git a/include/linux/init.h b/include/linux/init.h
index 885c3e6d0f9d..21c6bec9e3d0 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -130,6 +130,24 @@ int __init init_rootfs(void);
 extern bool rodata_enabled;
 #endif
 #ifdef CONFIG_DEBUG_RODATA
+/**
+ * mark_rodata_ro - implement memory protection for ELF sections
+ *
+ * Architectures which support memory protection define a kernel configuration
+ * entry for CONFIG_DEBUG_RODATA, enable it in and implement mark_rodata_ro().
+ * mark_rodata_ro() should strive to adjust the .rodata and .text ELF sections
+ * with read-only memory protection to prevent modifications of these sections
+ * after bootup. It can also try to use memory protection to prevent execution
+ * on the .rodata ELF section.
+ *
+ * In order to help architectures set both .text and .rodata as read-only with
+ * memory protections in one shot Linux has typically followed the convention
+ * to have the .rodata ELF section follow the .text ELF section on the vmlinux
+ * linker script.
+ *
+ * Linux calls mark_rodata_ro() after freeing .init code and prior to calling
+ * the first init userspace process.
+ */
 void mark_rodata_ro(void);
 #endif
 
@@ -140,25 +158,70 @@ extern bool initcall_debug;
 #endif
   
 #ifndef MODULE
+/**
+ * DOC: Initcall levels
+ *
+ * When Linux boots the kernel do_initcalls() iterates over each Linux
+ * initialization level ID and calls all routines embedded on each level ID.
+ * Prior to v2.5.2.3 Linux had only one init level onto which all init
+ * functions folded onto using __initcall(). After v2.5.2.4 Linux split up
+ * initcalls into 7 separate initcall subsection levels, each level describing
+ * different functionality part of the kernel (commit `9d6ba121b7e17085`_
+ * (v2.5.2.3 -> v2.5.2.4)). In order to remain backward compatible __initcall()
+ * calls were left mapped to device_initcall().
+ *
+ * Each init level consists of a dedicated ELF section, init functions are
+ * associated to an init level by linking it into the respective level's
+ * ELF section.
+ *
+ * Lower order init levels run prior to higher order init levels. Ordering
+ * inside each initcall level is determined by respective link order.
+ *
+ * .. _9d6ba121b7e17085: https://git.kernel.org/cgit/linux/kernel/git/history/history.git/commit/?id=9d6ba121b7e17085c95139233686b27a4d4c650e
+ */
 
 #ifndef __ASSEMBLY__
 
-/*
- * initcalls are now grouped by functionality into separate
- * subsections. Ordering inside the subsections is determined
- * by link order. 
- * For backwards compatibility, initcall() puts the call in 
- * the device init subsection.
+/**
+ * __define_initcall - wrapper for defining init levels
  *
- * The `id' arg to __define_initcall() is needed so that multiple initcalls
- * can point at the same handler without causing duplicate-symbol build errors.
+ * @fn: init routine
+ * @id: init level
  *
- * Initcalls are run by placing pointers in initcall sections that the
- * kernel iterates at runtime. The linker can do dead code / data elimination
- * and remove that completely, so the initcall sections have to be marked
- * as KEEP() in the linker script.
+ * Defines a kernel initialization level. A respective linker script entry
+ * is required to ensure the init level is accounted for and to ensure symbols
+ * exist for iterating over all functions in the init level. A init level
+ * represents a series of functionality in the kernel.
+ *
+ * Ordering within an initialization level is determined by link order, so
+ * for instance if a Makefile had::
+ *
+ *	obj-y += foo.o
+ *	obj-y += bar.o
+ *
+ * And foo.c::
+ *
+ *	subsys_initcall(foo_init);
+ *
+ * And bar.c had::
+ *
+ *	subsys_initcall(bar_init);
+ *
+ * foo_init() would be called prior to bar_init().
+ *
+ * Note that @id in __define_initcall() also enables multiple initcalls
+ * to be created using the same handler for different init levels without
+ * causing duplicate-symbol build errors.
+ *
+ * Initcalls are run by placing start symbols to initcall levels inside ELF
+ * sections, the kernel in turn uses these symbols to iterate over each init
+ * level at runtime with do_initcall_level(). The end of each init level is
+ * marked by the subsequent symbol's start address until we reach the symbol
+ * ``__initcall_end``. The linker can do dead code / data elimination and each
+ * init level start symbol could be removed completely in this process, to
+ * avoid this each init level start symbols must be marked as 'KEEP()' in the
+ * linker script to avoid any linker optimization heuristic on initcalls.
  */
-
 #define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
 	__attribute__((__section__(".initcall" #id ".init"))) = fn;
diff --git a/include/linux/sections.h b/include/linux/sections.h
new file mode 100644
index 000000000000..6771c727bcd1
--- /dev/null
+++ b/include/linux/sections.h
@@ -0,0 +1,87 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_CORE(section, core, name, level)			\
+	#section ".." #core "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 01/14] generic-sections: add section core helpers
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="windows-1254", Size: 47060 bytes --]

Linux makes extensive use of custom ELF header sections,
documentation for these are well scattered. Unify this
documentation in a central place and provide helpers to
build custom Linux sections.

This also generalizes sections code to enable avoiding
modifying the linker scripts when we want to add new
custom Linux sections. In order to make this generally
useful we need to ensure all architectures can make use of
core section helpers but that they can also override should
this be needed. Instead of relying on section.h this adds
a sections-core.h since this will be targeted to be safe
to be used on asm code, linker scripts and C code.

v7: ran ispell to fix spelling as requested by Boris

v5:

o Huge documentation revamp based on a careful review of the ELF
  specifications. Includes documentation now also about usage of
  two dots (..) when prefixing ELF program specific sections.

o Replace macros for sections names in favor of just using
  the section names explicitly in the linker script. This is
  perhaps more work to grep but this is what folks seem to
  currently prefer.

o Fix .text and .rodata documentation to explain memory protection
  strategies which architectures can embrace upon initialization
  (documents CONFIG_DEBUG_RODATA and mark_rodata_ro())

o Skip the 'Linux section ordering' documentation section, we'll instead
  add this on subsequent patch which will expand on it considerably

o Dropped tree on MAINTAINERS -- as per discussions with Arnd, hpa and
  Josh, its easier to just let changes for sections go in through the
  respective tree that needs the changes.

o Fix typos on documentation

o Dropped SECTION_ALL(), __SECTION_CORE(), SECTION_CORE_ALL() macros
  since we are favoring using explicit section names. These are
  useless if we are being explicit.

o Drop LINUX_SECTION_SIZE(), LINUX_SECTION_EMPTY() in favor of having
  section ranges and linker tables define their own, to avoid confusion
  and make code more readable.

o Add __define_initcall() documentation and a small section describing
  our current initcall levels. This should help also clarify what was
  meant about keeping backward compatibility.

v4:

o Port to shiny new sphinx documentation format

o fix a unicore32 build, turns out this actually fixes unicore32
  defconfig builds which were failing for a long while. unicore32
  does not seem to grok well the type passed on a section declaration,
  this ignores it.

o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
  this was causing final linker issues with blackfin -- this is
  a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
  being metatag. metatag is not supported on 0-day so I cannot confirm
  compilation there.

o Added SECTION_CORE() for C code, used later by __LINUX_RANGE()

o Since SECTION_CORE() is defined for linker script and C code, share
  the same helper and just use a __stringify() for the C code as is done
  for the other C helpers.

o move generic sections to asm-generic/section-core.h instead.
  PowerPC compilation blows up if asm/jump_labels.h gets
  section.h included, fixing this is not in any way easy.
  The list of issues are endless. Moving new data to a new
  simple file resolves this.

o since things are now in asm-generic/section-core.h the
  guard changes on asm-generic/sections.h and each architecture
  sections.h are no longer needed

o Give generic sections some maintainer love, that change is
  Acked-by Arnd Bergmann, Josh and hpa.

o A few checkpatch.pl style fixes

o As suggested by James Hogan use generic-y to copy generic
  header files on architectures that do not have a sections.h
  instead of writing a simple file only to include the generic one.

v3:

o add missing sections.h for architectures that did not
  have it

o move generic sections to asm-generic/sections.h

o add generic asm helpers section_type(), section_type_asmtype(),
  push_section_type() -- these helpers enable easy use for
  for later declaring and using of custom Linux sections using
  more standard APIs in both C code, asm code (C asm calls, or
  asm files), enabling future standardized section types to
  be more immediately accessible to asm code, not just C code.
  Note for ASM_CMD_SEP we use by default "\n", architectures needed
  to override can do so on their own sections.h prior to inclusion
  of asm-generic/sections.h

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/index.rst                   |   1 +
 Documentation/sections/background.rst     | 105 ++++++++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  17 ++
 Documentation/sections/section-core.rst   | 148 ++++++++++++++
 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/Kbuild               |   1 +
 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/section-core.h |  19 ++
 arch/x86/include/asm/Kbuild               |   1 +
 arch/xtensa/include/asm/Kbuild            |   1 +
 include/asm-generic/section-core.h        | 307 ++++++++++++++++++++++++++++++
 include/asm-generic/sections.h            |   2 +
 include/asm-generic/vmlinux.lds.h         |   1 +
 include/linux/init.h                      |  89 +++++++--
 include/linux/sections.h                  |  87 +++++++++
 42 files changed, 809 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/linux/sections.h

diff --git a/Documentation/index.rst b/Documentation/index.rst
index cb5d77699c60..71e0305c036d 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -57,6 +57,7 @@ needed).
    media/index
    gpu/index
    security/index
+   sections/index
    sound/index
    crypto/index
 
diff --git a/Documentation/sections/background.rst b/Documentation/sections/background.rst
new file mode 100644
index 000000000000..4f04c0682a6f
--- /dev/null
+++ b/Documentation/sections/background.rst
@@ -0,0 +1,105 @@
+===========
+ELF section background
+===========
+
+About
+==+
+The purpose of this chapter is to help those not familiar with ELF to brush up
+the latest ELF specifications in order to help understand how Linux uses and
+defines its own ELF sections.
+
+Standardized ELF
+========
+
+The first publication documenting ELF was UNIX System Laboratories' (USL)
+*System V Release 4 Application Binary Interface* (`SRV4 ABI`_) specification.
+Originally ELF was only a small part of the SRV4 ABI, with time however new
+specifications only put focus on ELF, such was the case of the *TIS Portable
+Formats Specification version 1.2* (`TIS 1.2`_). As of TIS 1.2, ELF was
+supplemented with processor specific ELF addendums, available on the *Linux
+Foundation referenced specification page* (`LF ref page`_). The latest ELF
+specification is the *System V Application Binary Interface - DRAFT - 24 April
+2001* (`gabi4`_).
+
+.. _SRV4 ABI: http://www.sco.com/developers/devspecs/gabi41.pdf
+.. _TIS 1.2: https://refspecs.linuxbase.org/elf/elf.pdf
+.. _LF ref page: https://refspecs.linuxbase.org/
+.. _gabi4: https://refspecs.linuxbase.org/elf/gabi4+/contents.html
+
+ELF views on Linux
+=========
+
+There are two views which can be used for inspecting data in an ELF file, a
+Linking view, and an Execution view. A Section Header Table enables one to
+describe an object using the Linking view while a Program Header Table enables
+one to describe an object using the Execution view. The views are not mutually
+exclusive. For instance, vmlinux can be viewed under both views, ``readelf -S
+vmlinux`` for the Linking view, and ``readelf -l vmlinux`` for the Execution
+view.  In Linux only the vmlinux file will have an Execution view, even modules
+lack an Execution view given that vmlinux is the only file that describes how
+the the kernel runs from the start.  All other Linux kernel object files have
+an available Linking view.
+
+Under the Linking view, the Section Header Table describes all available
+sections. The Section Header Table is an array of ELF section header data
+structures. If on a 32-bit system this is ``struct elf32_shd``, if on a 64-bit
+this is ``struct elf64_shdr``. Sections are only visible on object files that
+have a Linking view, since all Linux kernel files have Linking view, all kernel
+objects have ELF sections.
+
+Limitations on ELF sections
+=============+
+We provide a summary on the limitations of ELF sections. Refer to the public
+ELF specifications for details. Note that 64-bit limitations may depend
+on processor specific section attributes to be used, refer to your processor
+specification if unsure.
+
+Its worth elaborating on the limitations on the name of an ELF section:
+ELF section names are stored as strings as per the ELF specification, and
+as can be expected, these don't have explicit limitations. The implicit
+limitation then depends on the size of an ELF object file and ELF section.
+
+If using really large kernels or objects with large amounts of sections one
+would still need to be sure that ELF loader in charge of loading the Linux
+kernel is properly updated to handle coping with the latest ELF extensions.
+
+   .. flat-table:: Limitations on ELF Sections
+
+      * - Section attribute
+        - 32-bit
+        - 64-bit
+
+      * - ELF section name
+        - Size of an ELF section
+        - Size of an ELF section
+
+      * - Size of an ELF section
+        - 4 GiB
+        - 16 EiB
+
+      * - Max number of sections in an object file
+        - 4 GiEntries (4294967296)
+        - 16 EiEntries (18446744073709551616)
+
+Program specific ELF sections
+==============+
+The ELF specification allows for a section type to be specified as
+*Program specific section*, defined as ``SHT_PROGBITS``. This sections type
+enables programs to customize sections for their own use. In assembly this
+specified ``@progbits`` on most architectures, on ARM this is ``%progbits``.
+
+``SHT_PROGBITS`` is used by Linux for defining and using Linux ELF sections.
+
+Special ELF Sections
+==========
+
+The ELF specification defines *Special ELF Sections* on chapter 4 (`gabi4
+ch4`_). These are defined as sections which hold program and control
+information. Of these sections, a few have the section type as
+``SHT_PROGBITS``. This enables Linux to *further customize* use of the section
+beyond what the ELF specification suggests.
+
+.. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
new file mode 100644
index 000000000000..faa1c57595e1
--- /dev/null
+++ b/Documentation/sections/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel ELF sections'
+html_search_language = 'en'
diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
new file mode 100644
index 000000000000..f37511ef05e7
--- /dev/null
+++ b/Documentation/sections/index.rst
@@ -0,0 +1,17 @@
+============+Linux Kernel ELF sections
+============+
+This book documents the different ELF sections used on the Linux kernel.
+We start off by providing references to how ELF was standardized, references
+to the standards on ELF sections, review limitations of ELF sections, and
+finally how Linux uses ELF sections in the Linux kernel. Certain important
+Linux ELF sections are documented carefully: we describe the goal of the
+ELF section, and address concurrency considerations when applicable. A few
+common a set of Linux helpers for ELF sections are also documented.
+
+.. toctree::
+   :maxdepth: 4
+
+   background
+   section-core
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
new file mode 100644
index 000000000000..ac5815a0d9b3
--- /dev/null
+++ b/Documentation/sections/section-core.rst
@@ -0,0 +1,148 @@
+=================+Linux ELF program specific sections
+=================+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux ELF program specific sections
+
+Linux linker script
+=========+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux linker script
+
+Memory protection
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Memory protection
+
+mark_rodata_ro
+-----------------------
+.. kernel-doc:: include/linux/init.h
+   :functions: mark_rodata_ro
+
+.rodata
+-------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .rodata
+
+.text
+-----
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .text
+
+.data
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .data
+
+Linux .init\* sections
+===========
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux init sections
+
+.init.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.text
+
+.init.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.data
+
+.init.rodata
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.rodata
+
+Initcall levels
+---------------
+.. kernel-doc:: include/linux/init.h
+   :doc: Initcall levels
+
+.initcall
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .initcall
+
+__define_initcall
+-----------------
+.. kernel-doc:: include/linux/init.h
+   :functions: __define_initcall
+
+Linux .exit\* sections
+===========
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux exit sections
+
+.exit.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.text
+
+.exit.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.data
+
+.exitcall.exit
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exitcall.exit
+
+Linux .ref\* sections
+==========+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux references to init sections
+
+.ref.text
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.text
+
+.ref.data
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.data
+
+.ref.rodata
+-----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.rodata
+
+Generic Linux kernel section helpers
+==================
+
+Introduction
+-------------
+.. kernel-doc:: include/linux/sections.h
+   :doc: Introduction
+
+LINUX_SECTION_ALIGNMENT
+-----------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_ALIGNMENT
+
+LINUX_SECTION_START
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_START
+
+LINUX_SECTION_END
+-----------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_END
+
+DECLARE_LINUX_SECTION
+---------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION
+
+DECLARE_LINUX_SECTION_RO
+------------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION_RO
diff --git a/MAINTAINERS b/MAINTAINERS
index d2db7fecef32..5e580b1257fb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5438,6 +5438,18 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTIONS
+M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
+M:	Josh Poimboeuf <jpoimboe@redhat.com>
+M:	"H. Peter Anvin" <hpa@zytor.com>
+L:	linux-arch@vger.kernel.org
+L:	linux-kernel@vger.kernel.org
+S:	Supported
+F:	include/asm-generic/section-core.h
+F:	include/asm-generic/sections.h
+F:	include/asm-generic/vmlinux.lds.h
+F:	Documentation/sections/section-core.rst
+
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index bf8475ce85ee..5422827f1585 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += section-core.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index c332604606dd..7b2cb3dea5fc 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index efb21757d41f..9b69a22a9ae1 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += unaligned.h
 
 generated-y += mach-types.h
 generated-y += unistd-nr.h
+generic-y += section-core.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 8365a84c2640..00ace5e826f1 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 241b9b9729d8..f2c3b656a0e7 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 2fb67b59d188..bf20541bcf21 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -47,3 +47,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 64465e7e2245..38127ce747be 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -62,3 +62,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 1778805f6380..385cd88a9d9e 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += types.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 1fa084cf1a43..46d7c599d9b8 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 373cb23301e3..1ec04ec1c82b 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -75,3 +75,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index db8ddabc6bd2..37d7bfae7619 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -60,3 +60,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 502a91d8dbbd..672c6d5da18c 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 6e69d2c42eee..8ccfb5eb9678 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1f2e5d31cb24..1277b45bf4f9 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -34,3 +34,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 167150c701d1..b1011375cd7a 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -55,3 +55,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index b0ae88c9fed9..c6c2cf6edc98 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index ed07179fe26a..7a932b4a5531 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 1c8dd0f5cd5d..f8145bc85835 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index d63330e88379..c9c7cb82b00f 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 2832f031fb11..86175e701869 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -71,3 +71,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 91f53c07f410..18a9d4c5ead7 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -28,3 +28,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 5c4fbc80dc6c..4322d9746cdb 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
+generic-y += section-core.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 8aea32fe8bd2..63a1c2924b91 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index a05218ff3fe4..f089a264cd38 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 751c3373a92c..7b0356dca562 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 0569bfac4afb..438f86573dc5 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 2d1f5638974c..fb6b831c1fba 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 052f7f6d0551..580bd5ff828f 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -26,3 +26,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
new file mode 100644
index 000000000000..0b9c68429a1a
--- /dev/null
+++ b/arch/unicore32/include/asm/section-core.h
@@ -0,0 +1,19 @@
+#ifndef __UNICORE_SECTION_CORE_ASM_H__
+#define __UNICORE_SECTION_CORE_ASM_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/.
+ */
+
+/* Unicore32 has known to not work properly with the type set, so ignore it */
+
+#define __set_section_core_type(___section, ___core, ___name,		\
+				___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags
+
+#include <asm-generic/section-core.h>
+
+#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 2b892e2313a9..af975f21eeee 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
+generic-y += section-core.h
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index b7fbaa56b51a..7879c31e66a7 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..efc753e80d76
--- /dev/null
+++ b/include/asm-generic/section-core.h
@@ -0,0 +1,307 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Linux ELF program specific sections
+ *
+ * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and
+ * definition of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
+ * sections. This chapter is dedicated to documenting Linux program specific
+ * sections and helpers available to make use of these easier to implement and
+ * use.
+ *
+ * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
+ */
+
+/**
+ * DOC: Linux linker script
+ *
+ * Linux uses a custom linker script to build the vmlinux binary, it uses it to
+ * strategically place and define Linux ELF sections.  Each architecture needs
+ * to implement its own linker script, it is expected to reside in
+ * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
+ * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
+ * as well as some helpers documented in this chapter.
+ *
+ * In assembly it is common practice to use dots (``.``) in labels to avoid
+ * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
+ * name but not a C symbol. Historically then, two dots are used (``..``)
+ * have been used in linker scripts when adding program specific sections
+ * when there are concerns to avoid clashes with compiler generated sections.
+ */
+
+/**
+ * DOC: Memory protection
+ *
+ * Linux allows architectures which support memory protection features to
+ * take advantage of them by letting architectures define and enable
+ * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.
+ * mark_rodata_ro() can be used for instance to mark specific sections as
+ * read-only or non-executable.
+ *
+ * Linux typically follows a convention to have the .rodata ELF section follow
+ * after the .text ELF section, it does this to help architectures which
+ * support memory protection to mark both .text and .rodata as read-only in
+ * one shot.
+ *
+ * For more details refer to mark_rodata_ro().
+ */
+
+/**
+ * DOC: .rodata
+ *
+ * ELF section used for data which must be protected from write access.
+ */
+
+/**
+ * DOC: .text
+ *
+ * ELF section name used for code (functions) used during regular
+ * kernel run time.
+ */
+
+/**
+ * DOC: .data
+ *
+ * ELF section used for read-write data.
+ */
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: .init.text
+ *
+ * ELF section for code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+
+/**
+ * DOC: .init.data
+ *
+ * ELF section used for data structures used only during boot or driver
+ * initialization.
+ */
+
+/**
+ * DOC: .init.rodata
+ *
+ * ELF section used for read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+
+/**
+ * DOC: .initcall
+ *
+ * ELF section used for subsystem init calls. There are init levels
+ * representing different functionality in the kernel. For more details
+ * refer to __define_initcall().
+ */
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: .exit.text
+ *
+ * ELF section used to for code (functions) used only during module unload.
+ */
+
+/**
+ * DOC: .exit.data
+ *
+ * ELF section used to for data structures used only during module
+ * unload.
+ */
+
+/**
+ * DOC: .exitcall.exit
+ *
+ * ELF section used for exit routines, order is important and maintained by
+ * link order.
+ */
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: .ref.text
+ *
+ * ELF section used to annotate code (functions) which has been vetted as
+ * valid for its reference or use of other code (functions) or data structures
+ * which are part of the init sections.
+ */
+
+/**
+ * DOC: .ref.data
+ *
+ * ELF section used for data structures which have been vetted for its
+ * reference or use of other code (functions) or data structures part of the
+ * init sections.
+ */
+
+/**
+ * DOC: .ref.rodata
+ *
+ * ELF section used to annotate const code (functions) const data structures
+ * which has been vetted for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section..___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section..__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifndef LINKER_SCRIPT
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align\x16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 4df64a1fc09e..b145ae8d9cbe 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_GENERIC_SECTIONS_H_
 #define _ASM_GENERIC_SECTIONS_H_
 
+#include <asm/section-core.h>
+
 /* References to section boundaries */
 
 #include <linux/compiler.h>
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 0968d13b3885..483f60c451f9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -55,6 +55,7 @@
 #endif
 
 #include <linux/export.h>
+#include <asm/section-core.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
diff --git a/include/linux/init.h b/include/linux/init.h
index 885c3e6d0f9d..21c6bec9e3d0 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -130,6 +130,24 @@ int __init init_rootfs(void);
 extern bool rodata_enabled;
 #endif
 #ifdef CONFIG_DEBUG_RODATA
+/**
+ * mark_rodata_ro - implement memory protection for ELF sections
+ *
+ * Architectures which support memory protection define a kernel configuration
+ * entry for CONFIG_DEBUG_RODATA, enable it in and implement mark_rodata_ro().
+ * mark_rodata_ro() should strive to adjust the .rodata and .text ELF sections
+ * with read-only memory protection to prevent modifications of these sections
+ * after bootup. It can also try to use memory protection to prevent execution
+ * on the .rodata ELF section.
+ *
+ * In order to help architectures set both .text and .rodata as read-only with
+ * memory protections in one shot Linux has typically followed the convention
+ * to have the .rodata ELF section follow the .text ELF section on the vmlinux
+ * linker script.
+ *
+ * Linux calls mark_rodata_ro() after freeing .init code and prior to calling
+ * the first init userspace process.
+ */
 void mark_rodata_ro(void);
 #endif
 
@@ -140,25 +158,70 @@ extern bool initcall_debug;
 #endif
   
 #ifndef MODULE
+/**
+ * DOC: Initcall levels
+ *
+ * When Linux boots the kernel do_initcalls() iterates over each Linux
+ * initialization level ID and calls all routines embedded on each level ID.
+ * Prior to v2.5.2.3 Linux had only one init level onto which all init
+ * functions folded onto using __initcall(). After v2.5.2.4 Linux split up
+ * initcalls into 7 separate initcall subsection levels, each level describing
+ * different functionality part of the kernel (commit `9d6ba121b7e17085`_
+ * (v2.5.2.3 -> v2.5.2.4)). In order to remain backward compatible __initcall()
+ * calls were left mapped to device_initcall().
+ *
+ * Each init level consists of a dedicated ELF section, init functions are
+ * associated to an init level by linking it into the respective level's
+ * ELF section.
+ *
+ * Lower order init levels run prior to higher order init levels. Ordering
+ * inside each initcall level is determined by respective link order.
+ *
+ * .. _9d6ba121b7e17085: https://git.kernel.org/cgit/linux/kernel/git/history/history.git/commit/?id6ba121b7e17085c95139233686b27a4d4c650e
+ */
 
 #ifndef __ASSEMBLY__
 
-/*
- * initcalls are now grouped by functionality into separate
- * subsections. Ordering inside the subsections is determined
- * by link order. 
- * For backwards compatibility, initcall() puts the call in 
- * the device init subsection.
+/**
+ * __define_initcall - wrapper for defining init levels
  *
- * The `id' arg to __define_initcall() is needed so that multiple initcalls
- * can point at the same handler without causing duplicate-symbol build errors.
+ * @fn: init routine
+ * @id: init level
  *
- * Initcalls are run by placing pointers in initcall sections that the
- * kernel iterates at runtime. The linker can do dead code / data elimination
- * and remove that completely, so the initcall sections have to be marked
- * as KEEP() in the linker script.
+ * Defines a kernel initialization level. A respective linker script entry
+ * is required to ensure the init level is accounted for and to ensure symbols
+ * exist for iterating over all functions in the init level. A init level
+ * represents a series of functionality in the kernel.
+ *
+ * Ordering within an initialization level is determined by link order, so
+ * for instance if a Makefile had::
+ *
+ *	obj-y += foo.o
+ *	obj-y += bar.o
+ *
+ * And foo.c::
+ *
+ *	subsys_initcall(foo_init);
+ *
+ * And bar.c had::
+ *
+ *	subsys_initcall(bar_init);
+ *
+ * foo_init() would be called prior to bar_init().
+ *
+ * Note that @id in __define_initcall() also enables multiple initcalls
+ * to be created using the same handler for different init levels without
+ * causing duplicate-symbol build errors.
+ *
+ * Initcalls are run by placing start symbols to initcall levels inside ELF
+ * sections, the kernel in turn uses these symbols to iterate over each init
+ * level at runtime with do_initcall_level(). The end of each init level is
+ * marked by the subsequent symbol's start address until we reach the symbol
+ * ``__initcall_end``. The linker can do dead code / data elimination and each
+ * init level start symbol could be removed completely in this process, to
+ * avoid this each init level start symbols must be marked as 'KEEP()' in the
+ * linker script to avoid any linker optimization heuristic on initcalls.
  */
-
 #define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
 	__attribute__((__section__(".initcall" #id ".init"))) = fn;
diff --git a/include/linux/sections.h b/include/linux/sections.h
new file mode 100644
index 000000000000..6771c727bcd1
--- /dev/null
+++ b/include/linux/sections.h
@@ -0,0 +1,87 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_CORE(section, core, name, level)			\
+	#section ".." #core "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe sparclinux" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 01/14] generic-sections: add section core helpers
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Linux makes extensive use of custom ELF header sections,
documentation for these are well scattered. Unify this
documentation in a central place and provide helpers to
build custom Linux sections.

This also generalizes sections code to enable avoiding
modifying the linker scripts when we want to add new
custom Linux sections. In order to make this generally
useful we need to ensure all architectures can make use of
core section helpers but that they can also override should
this be needed. Instead of relying on section.h this adds
a sections-core.h since this will be targeted to be safe
to be used on asm code, linker scripts and C code.

v7: ran ispell to fix spelling as requested by Boris

v5:

o Huge documentation revamp based on a careful review of the ELF
  specifications. Includes documentation now also about usage of
  two dots (..) when prefixing ELF program specific sections.

o Replace macros for sections names in favor of just using
  the section names explicitly in the linker script. This is
  perhaps more work to grep but this is what folks seem to
  currently prefer.

o Fix .text and .rodata documentation to explain memory protection
  strategies which architectures can embrace upon initialization
  (documents CONFIG_DEBUG_RODATA and mark_rodata_ro())

o Skip the 'Linux section ordering' documentation section, we'll instead
  add this on subsequent patch which will expand on it considerably

o Dropped tree on MAINTAINERS -- as per discussions with Arnd, hpa and
  Josh, its easier to just let changes for sections go in through the
  respective tree that needs the changes.

o Fix typos on documentation

o Dropped SECTION_ALL(), __SECTION_CORE(), SECTION_CORE_ALL() macros
  since we are favoring using explicit section names. These are
  useless if we are being explicit.

o Drop LINUX_SECTION_SIZE(), LINUX_SECTION_EMPTY() in favor of having
  section ranges and linker tables define their own, to avoid confusion
  and make code more readable.

o Add __define_initcall() documentation and a small section describing
  our current initcall levels. This should help also clarify what was
  meant about keeping backward compatibility.

v4:

o Port to shiny new sphinx documentation format

o fix a unicore32 build, turns out this actually fixes unicore32
  defconfig builds which were failing for a long while. unicore32
  does not seem to grok well the type passed on a section declaration,
  this ignores it.

o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
  this was causing final linker issues with blackfin -- this is
  a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
  being metatag. metatag is not supported on 0-day so I cannot confirm
  compilation there.

o Added SECTION_CORE() for C code, used later by __LINUX_RANGE()

o Since SECTION_CORE() is defined for linker script and C code, share
  the same helper and just use a __stringify() for the C code as is done
  for the other C helpers.

o move generic sections to asm-generic/section-core.h instead.
  PowerPC compilation blows up if asm/jump_labels.h gets
  section.h included, fixing this is not in any way easy.
  The list of issues are endless. Moving new data to a new
  simple file resolves this.

o since things are now in asm-generic/section-core.h the
  guard changes on asm-generic/sections.h and each architecture
  sections.h are no longer needed

o Give generic sections some maintainer love, that change is
  Acked-by Arnd Bergmann, Josh and hpa.

o A few checkpatch.pl style fixes

o As suggested by James Hogan use generic-y to copy generic
  header files on architectures that do not have a sections.h
  instead of writing a simple file only to include the generic one.

v3:

o add missing sections.h for architectures that did not
  have it

o move generic sections to asm-generic/sections.h

o add generic asm helpers section_type(), section_type_asmtype(),
  push_section_type() -- these helpers enable easy use for
  for later declaring and using of custom Linux sections using
  more standard APIs in both C code, asm code (C asm calls, or
  asm files), enabling future standardized section types to
  be more immediately accessible to asm code, not just C code.
  Note for ASM_CMD_SEP we use by default "\n", architectures needed
  to override can do so on their own sections.h prior to inclusion
  of asm-generic/sections.h

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/index.rst                   |   1 +
 Documentation/sections/background.rst     | 105 ++++++++++
 Documentation/sections/conf.py            |   4 +
 Documentation/sections/index.rst          |  17 ++
 Documentation/sections/section-core.rst   | 148 ++++++++++++++
 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/Kbuild               |   1 +
 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/section-core.h |  19 ++
 arch/x86/include/asm/Kbuild               |   1 +
 arch/xtensa/include/asm/Kbuild            |   1 +
 include/asm-generic/section-core.h        | 307 ++++++++++++++++++++++++++++++
 include/asm-generic/sections.h            |   2 +
 include/asm-generic/vmlinux.lds.h         |   1 +
 include/linux/init.h                      |  89 +++++++--
 include/linux/sections.h                  |  87 +++++++++
 42 files changed, 809 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/sections/background.rst
 create mode 100644 Documentation/sections/conf.py
 create mode 100644 Documentation/sections/index.rst
 create mode 100644 Documentation/sections/section-core.rst
 create mode 100644 arch/unicore32/include/asm/section-core.h
 create mode 100644 include/asm-generic/section-core.h
 create mode 100644 include/linux/sections.h

diff --git a/Documentation/index.rst b/Documentation/index.rst
index cb5d77699c60..71e0305c036d 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -57,6 +57,7 @@ needed).
    media/index
    gpu/index
    security/index
+   sections/index
    sound/index
    crypto/index
 
diff --git a/Documentation/sections/background.rst b/Documentation/sections/background.rst
new file mode 100644
index 000000000000..4f04c0682a6f
--- /dev/null
+++ b/Documentation/sections/background.rst
@@ -0,0 +1,105 @@
+===========
+ELF section background
+===========
+
+About
+==+
+The purpose of this chapter is to help those not familiar with ELF to brush up
+the latest ELF specifications in order to help understand how Linux uses and
+defines its own ELF sections.
+
+Standardized ELF
+========
+
+The first publication documenting ELF was UNIX System Laboratories' (USL)
+*System V Release 4 Application Binary Interface* (`SRV4 ABI`_) specification.
+Originally ELF was only a small part of the SRV4 ABI, with time however new
+specifications only put focus on ELF, such was the case of the *TIS Portable
+Formats Specification version 1.2* (`TIS 1.2`_). As of TIS 1.2, ELF was
+supplemented with processor specific ELF addendums, available on the *Linux
+Foundation referenced specification page* (`LF ref page`_). The latest ELF
+specification is the *System V Application Binary Interface - DRAFT - 24 April
+2001* (`gabi4`_).
+
+.. _SRV4 ABI: http://www.sco.com/developers/devspecs/gabi41.pdf
+.. _TIS 1.2: https://refspecs.linuxbase.org/elf/elf.pdf
+.. _LF ref page: https://refspecs.linuxbase.org/
+.. _gabi4: https://refspecs.linuxbase.org/elf/gabi4+/contents.html
+
+ELF views on Linux
+=========
+
+There are two views which can be used for inspecting data in an ELF file, a
+Linking view, and an Execution view. A Section Header Table enables one to
+describe an object using the Linking view while a Program Header Table enables
+one to describe an object using the Execution view. The views are not mutually
+exclusive. For instance, vmlinux can be viewed under both views, ``readelf -S
+vmlinux`` for the Linking view, and ``readelf -l vmlinux`` for the Execution
+view.  In Linux only the vmlinux file will have an Execution view, even modules
+lack an Execution view given that vmlinux is the only file that describes how
+the the kernel runs from the start.  All other Linux kernel object files have
+an available Linking view.
+
+Under the Linking view, the Section Header Table describes all available
+sections. The Section Header Table is an array of ELF section header data
+structures. If on a 32-bit system this is ``struct elf32_shd``, if on a 64-bit
+this is ``struct elf64_shdr``. Sections are only visible on object files that
+have a Linking view, since all Linux kernel files have Linking view, all kernel
+objects have ELF sections.
+
+Limitations on ELF sections
+=============+
+We provide a summary on the limitations of ELF sections. Refer to the public
+ELF specifications for details. Note that 64-bit limitations may depend
+on processor specific section attributes to be used, refer to your processor
+specification if unsure.
+
+Its worth elaborating on the limitations on the name of an ELF section:
+ELF section names are stored as strings as per the ELF specification, and
+as can be expected, these don't have explicit limitations. The implicit
+limitation then depends on the size of an ELF object file and ELF section.
+
+If using really large kernels or objects with large amounts of sections one
+would still need to be sure that ELF loader in charge of loading the Linux
+kernel is properly updated to handle coping with the latest ELF extensions.
+
+   .. flat-table:: Limitations on ELF Sections
+
+      * - Section attribute
+        - 32-bit
+        - 64-bit
+
+      * - ELF section name
+        - Size of an ELF section
+        - Size of an ELF section
+
+      * - Size of an ELF section
+        - 4 GiB
+        - 16 EiB
+
+      * - Max number of sections in an object file
+        - 4 GiEntries (4294967296)
+        - 16 EiEntries (18446744073709551616)
+
+Program specific ELF sections
+==============+
+The ELF specification allows for a section type to be specified as
+*Program specific section*, defined as ``SHT_PROGBITS``. This sections type
+enables programs to customize sections for their own use. In assembly this
+specified ``@progbits`` on most architectures, on ARM this is ``%progbits``.
+
+``SHT_PROGBITS`` is used by Linux for defining and using Linux ELF sections.
+
+Special ELF Sections
+==========
+
+The ELF specification defines *Special ELF Sections* on chapter 4 (`gabi4
+ch4`_). These are defined as sections which hold program and control
+information. Of these sections, a few have the section type as
+``SHT_PROGBITS``. This enables Linux to *further customize* use of the section
+beyond what the ELF specification suggests.
+
+.. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
new file mode 100644
index 000000000000..faa1c57595e1
--- /dev/null
+++ b/Documentation/sections/conf.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8; mode: python -*-
+
+project = 'Linux Kernel ELF sections'
+html_search_language = 'en'
diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
new file mode 100644
index 000000000000..f37511ef05e7
--- /dev/null
+++ b/Documentation/sections/index.rst
@@ -0,0 +1,17 @@
+============+Linux Kernel ELF sections
+============+
+This book documents the different ELF sections used on the Linux kernel.
+We start off by providing references to how ELF was standardized, references
+to the standards on ELF sections, review limitations of ELF sections, and
+finally how Linux uses ELF sections in the Linux kernel. Certain important
+Linux ELF sections are documented carefully: we describe the goal of the
+ELF section, and address concurrency considerations when applicable. A few
+common a set of Linux helpers for ELF sections are also documented.
+
+.. toctree::
+   :maxdepth: 4
+
+   background
+   section-core
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
new file mode 100644
index 000000000000..ac5815a0d9b3
--- /dev/null
+++ b/Documentation/sections/section-core.rst
@@ -0,0 +1,148 @@
+=================+Linux ELF program specific sections
+=================+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux ELF program specific sections
+
+Linux linker script
+=========+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux linker script
+
+Memory protection
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Memory protection
+
+mark_rodata_ro
+-----------------------
+.. kernel-doc:: include/linux/init.h
+   :functions: mark_rodata_ro
+
+.rodata
+-------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .rodata
+
+.text
+-----
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .text
+
+.data
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .data
+
+Linux .init\* sections
+===========
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux init sections
+
+.init.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.text
+
+.init.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.data
+
+.init.rodata
+------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .init.rodata
+
+Initcall levels
+---------------
+.. kernel-doc:: include/linux/init.h
+   :doc: Initcall levels
+
+.initcall
+-----------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .initcall
+
+__define_initcall
+-----------------
+.. kernel-doc:: include/linux/init.h
+   :functions: __define_initcall
+
+Linux .exit\* sections
+===========
+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux exit sections
+
+.exit.text
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.text
+
+.exit.data
+----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exit.data
+
+.exitcall.exit
+--------------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .exitcall.exit
+
+Linux .ref\* sections
+==========+
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux references to init sections
+
+.ref.text
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.text
+
+.ref.data
+---------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.data
+
+.ref.rodata
+-----------
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: .ref.rodata
+
+Generic Linux kernel section helpers
+==================
+
+Introduction
+-------------
+.. kernel-doc:: include/linux/sections.h
+   :doc: Introduction
+
+LINUX_SECTION_ALIGNMENT
+-----------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_ALIGNMENT
+
+LINUX_SECTION_START
+-------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_START
+
+LINUX_SECTION_END
+-----------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: LINUX_SECTION_END
+
+DECLARE_LINUX_SECTION
+---------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION
+
+DECLARE_LINUX_SECTION_RO
+------------------------
+.. kernel-doc:: include/linux/sections.h
+   :functions: DECLARE_LINUX_SECTION_RO
diff --git a/MAINTAINERS b/MAINTAINERS
index d2db7fecef32..5e580b1257fb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5438,6 +5438,18 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTIONS
+M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
+M:	Josh Poimboeuf <jpoimboe@redhat.com>
+M:	"H. Peter Anvin" <hpa@zytor.com>
+L:	linux-arch@vger.kernel.org
+L:	linux-kernel@vger.kernel.org
+S:	Supported
+F:	include/asm-generic/section-core.h
+F:	include/asm-generic/sections.h
+F:	include/asm-generic/vmlinux.lds.h
+F:	Documentation/sections/section-core.rst
+
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:	"Michael S. Tsirkin" <mst@redhat.com>
 L:	kvm@vger.kernel.org
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index bf8475ce85ee..5422827f1585 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
+generic-y += section-core.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index c332604606dd..7b2cb3dea5fc 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -51,3 +51,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index efb21757d41f..9b69a22a9ae1 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += unaligned.h
 
 generated-y += mach-types.h
 generated-y += unistd-nr.h
+generic-y += section-core.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 8365a84c2640..00ace5e826f1 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index 241b9b9729d8..f2c3b656a0e7 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 2fb67b59d188..bf20541bcf21 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -47,3 +47,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 64465e7e2245..38127ce747be 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -62,3 +62,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 1778805f6380..385cd88a9d9e 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -45,3 +45,4 @@ generic-y += types.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 1fa084cf1a43..46d7c599d9b8 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 373cb23301e3..1ec04ec1c82b 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -75,3 +75,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index db8ddabc6bd2..37d7bfae7619 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -60,3 +60,4 @@ generic-y += unaligned.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 502a91d8dbbd..672c6d5da18c 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 6e69d2c42eee..8ccfb5eb9678 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1f2e5d31cb24..1277b45bf4f9 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -34,3 +34,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index 167150c701d1..b1011375cd7a 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -55,3 +55,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index b0ae88c9fed9..c6c2cf6edc98 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index ed07179fe26a..7a932b4a5531 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += unaligned.h
 generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index 1c8dd0f5cd5d..f8145bc85835 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index d63330e88379..c9c7cb82b00f 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 2832f031fb11..86175e701869 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -71,3 +71,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 91f53c07f410..18a9d4c5ead7 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -28,3 +28,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 5c4fbc80dc6c..4322d9746cdb 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mcs_spinlock.h
 generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
+generic-y += section-core.h
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 8aea32fe8bd2..63a1c2924b91 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -8,3 +8,4 @@ generic-y += mm-arch-hooks.h
 generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index a05218ff3fe4..f089a264cd38 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += trace_clock.h
 generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 751c3373a92c..7b0356dca562 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -39,3 +39,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 0569bfac4afb..438f86573dc5 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -21,3 +21,4 @@ generic-y += serial.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
+generic-y += section-core.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index 2d1f5638974c..fb6b831c1fba 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += termios.h
 generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 052f7f6d0551..580bd5ff828f 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -26,3 +26,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
new file mode 100644
index 000000000000..0b9c68429a1a
--- /dev/null
+++ b/arch/unicore32/include/asm/section-core.h
@@ -0,0 +1,19 @@
+#ifndef __UNICORE_SECTION_CORE_ASM_H__
+#define __UNICORE_SECTION_CORE_ASM_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/.
+ */
+
+/* Unicore32 has known to not work properly with the type set, so ignore it */
+
+#define __set_section_core_type(___section, ___core, ___name,		\
+				___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags
+
+#include <asm-generic/section-core.h>
+
+#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index 2b892e2313a9..af975f21eeee 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += dma-contiguous.h
 generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
+generic-y += section-core.h
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index b7fbaa56b51a..7879c31e66a7 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -32,3 +32,4 @@ generic-y += topology.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += section-core.h
diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..efc753e80d76
--- /dev/null
+++ b/include/asm-generic/section-core.h
@@ -0,0 +1,307 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Linux ELF program specific sections
+ *
+ * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and
+ * definition of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
+ * sections. This chapter is dedicated to documenting Linux program specific
+ * sections and helpers available to make use of these easier to implement and
+ * use.
+ *
+ * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
+ */
+
+/**
+ * DOC: Linux linker script
+ *
+ * Linux uses a custom linker script to build the vmlinux binary, it uses it to
+ * strategically place and define Linux ELF sections.  Each architecture needs
+ * to implement its own linker script, it is expected to reside in
+ * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
+ * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
+ * as well as some helpers documented in this chapter.
+ *
+ * In assembly it is common practice to use dots (``.``) in labels to avoid
+ * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
+ * name but not a C symbol. Historically then, two dots are used (``..``)
+ * have been used in linker scripts when adding program specific sections
+ * when there are concerns to avoid clashes with compiler generated sections.
+ */
+
+/**
+ * DOC: Memory protection
+ *
+ * Linux allows architectures which support memory protection features to
+ * take advantage of them by letting architectures define and enable
+ * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.
+ * mark_rodata_ro() can be used for instance to mark specific sections as
+ * read-only or non-executable.
+ *
+ * Linux typically follows a convention to have the .rodata ELF section follow
+ * after the .text ELF section, it does this to help architectures which
+ * support memory protection to mark both .text and .rodata as read-only in
+ * one shot.
+ *
+ * For more details refer to mark_rodata_ro().
+ */
+
+/**
+ * DOC: .rodata
+ *
+ * ELF section used for data which must be protected from write access.
+ */
+
+/**
+ * DOC: .text
+ *
+ * ELF section name used for code (functions) used during regular
+ * kernel run time.
+ */
+
+/**
+ * DOC: .data
+ *
+ * ELF section used for read-write data.
+ */
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: .init.text
+ *
+ * ELF section for code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+
+/**
+ * DOC: .init.data
+ *
+ * ELF section used for data structures used only during boot or driver
+ * initialization.
+ */
+
+/**
+ * DOC: .init.rodata
+ *
+ * ELF section used for read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+
+/**
+ * DOC: .initcall
+ *
+ * ELF section used for subsystem init calls. There are init levels
+ * representing different functionality in the kernel. For more details
+ * refer to __define_initcall().
+ */
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: .exit.text
+ *
+ * ELF section used to for code (functions) used only during module unload.
+ */
+
+/**
+ * DOC: .exit.data
+ *
+ * ELF section used to for data structures used only during module
+ * unload.
+ */
+
+/**
+ * DOC: .exitcall.exit
+ *
+ * ELF section used for exit routines, order is important and maintained by
+ * link order.
+ */
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: .ref.text
+ *
+ * ELF section used to annotate code (functions) which has been vetted as
+ * valid for its reference or use of other code (functions) or data structures
+ * which are part of the init sections.
+ */
+
+/**
+ * DOC: .ref.data
+ *
+ * ELF section used for data structures which have been vetted for its
+ * reference or use of other code (functions) or data structures part of the
+ * init sections.
+ */
+
+/**
+ * DOC: .ref.rodata
+ *
+ * ELF section used to annotate const code (functions) const data structures
+ * which has been vetted for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section..___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section..__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifndef LINKER_SCRIPT
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align\x16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index 4df64a1fc09e..b145ae8d9cbe 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_GENERIC_SECTIONS_H_
 #define _ASM_GENERIC_SECTIONS_H_
 
+#include <asm/section-core.h>
+
 /* References to section boundaries */
 
 #include <linux/compiler.h>
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 0968d13b3885..483f60c451f9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -55,6 +55,7 @@
 #endif
 
 #include <linux/export.h>
+#include <asm/section-core.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
diff --git a/include/linux/init.h b/include/linux/init.h
index 885c3e6d0f9d..21c6bec9e3d0 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -130,6 +130,24 @@ int __init init_rootfs(void);
 extern bool rodata_enabled;
 #endif
 #ifdef CONFIG_DEBUG_RODATA
+/**
+ * mark_rodata_ro - implement memory protection for ELF sections
+ *
+ * Architectures which support memory protection define a kernel configuration
+ * entry for CONFIG_DEBUG_RODATA, enable it in and implement mark_rodata_ro().
+ * mark_rodata_ro() should strive to adjust the .rodata and .text ELF sections
+ * with read-only memory protection to prevent modifications of these sections
+ * after bootup. It can also try to use memory protection to prevent execution
+ * on the .rodata ELF section.
+ *
+ * In order to help architectures set both .text and .rodata as read-only with
+ * memory protections in one shot Linux has typically followed the convention
+ * to have the .rodata ELF section follow the .text ELF section on the vmlinux
+ * linker script.
+ *
+ * Linux calls mark_rodata_ro() after freeing .init code and prior to calling
+ * the first init userspace process.
+ */
 void mark_rodata_ro(void);
 #endif
 
@@ -140,25 +158,70 @@ extern bool initcall_debug;
 #endif
   
 #ifndef MODULE
+/**
+ * DOC: Initcall levels
+ *
+ * When Linux boots the kernel do_initcalls() iterates over each Linux
+ * initialization level ID and calls all routines embedded on each level ID.
+ * Prior to v2.5.2.3 Linux had only one init level onto which all init
+ * functions folded onto using __initcall(). After v2.5.2.4 Linux split up
+ * initcalls into 7 separate initcall subsection levels, each level describing
+ * different functionality part of the kernel (commit `9d6ba121b7e17085`_
+ * (v2.5.2.3 -> v2.5.2.4)). In order to remain backward compatible __initcall()
+ * calls were left mapped to device_initcall().
+ *
+ * Each init level consists of a dedicated ELF section, init functions are
+ * associated to an init level by linking it into the respective level's
+ * ELF section.
+ *
+ * Lower order init levels run prior to higher order init levels. Ordering
+ * inside each initcall level is determined by respective link order.
+ *
+ * .. _9d6ba121b7e17085: https://git.kernel.org/cgit/linux/kernel/git/history/history.git/commit/?idù6ba121b7e17085c95139233686b27a4d4c650e
+ */
 
 #ifndef __ASSEMBLY__
 
-/*
- * initcalls are now grouped by functionality into separate
- * subsections. Ordering inside the subsections is determined
- * by link order. 
- * For backwards compatibility, initcall() puts the call in 
- * the device init subsection.
+/**
+ * __define_initcall - wrapper for defining init levels
  *
- * The `id' arg to __define_initcall() is needed so that multiple initcalls
- * can point at the same handler without causing duplicate-symbol build errors.
+ * @fn: init routine
+ * @id: init level
  *
- * Initcalls are run by placing pointers in initcall sections that the
- * kernel iterates at runtime. The linker can do dead code / data elimination
- * and remove that completely, so the initcall sections have to be marked
- * as KEEP() in the linker script.
+ * Defines a kernel initialization level. A respective linker script entry
+ * is required to ensure the init level is accounted for and to ensure symbols
+ * exist for iterating over all functions in the init level. A init level
+ * represents a series of functionality in the kernel.
+ *
+ * Ordering within an initialization level is determined by link order, so
+ * for instance if a Makefile had::
+ *
+ *	obj-y += foo.o
+ *	obj-y += bar.o
+ *
+ * And foo.c::
+ *
+ *	subsys_initcall(foo_init);
+ *
+ * And bar.c had::
+ *
+ *	subsys_initcall(bar_init);
+ *
+ * foo_init() would be called prior to bar_init().
+ *
+ * Note that @id in __define_initcall() also enables multiple initcalls
+ * to be created using the same handler for different init levels without
+ * causing duplicate-symbol build errors.
+ *
+ * Initcalls are run by placing start symbols to initcall levels inside ELF
+ * sections, the kernel in turn uses these symbols to iterate over each init
+ * level at runtime with do_initcall_level(). The end of each init level is
+ * marked by the subsequent symbol's start address until we reach the symbol
+ * ``__initcall_end``. The linker can do dead code / data elimination and each
+ * init level start symbol could be removed completely in this process, to
+ * avoid this each init level start symbols must be marked as 'KEEP()' in the
+ * linker script to avoid any linker optimization heuristic on initcalls.
  */
-
 #define __define_initcall(fn, id) \
 	static initcall_t __initcall_##fn##id __used \
 	__attribute__((__section__(".initcall" #id ".init"))) = fn;
diff --git a/include/linux/sections.h b/include/linux/sections.h
new file mode 100644
index 000000000000..6771c727bcd1
--- /dev/null
+++ b/include/linux/sections.h
@@ -0,0 +1,87 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_CORE(section, core, name, level)			\
+	#section ".." #core "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe linux-ia64" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 02/14] xtensa: skip adding literal when SORT() is used
  2017-01-15 21:10         ` Luis R. Rodriguez
  (?)
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

When SORT(foo.*) is used the current sed replacements add
SORT(foo.literal foo.*), this breaks linking. Avoid adding
literals for SORT globs, if needed, these need to be added
manually.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/xtensa/kernel/Makefile | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index 264fb89c444e..ccedd016a8e0 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -30,10 +30,10 @@ AFLAGS_mxhead.o += -mtext-section-literals
 #
 # Replicate rules in scripts/Makefile.build
 
-sed-y = -e ':a; s/\*(\([^)]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
-	-e ':b; s/\*(\([^)]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
-	-e ':c; s/\*(\([^)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
-	-e ':d; s/\*(\([^)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
+sed-y = -e ':a; s/\*(\([^)SORT]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
+	-e ':b; s/\*(\([^)SORT]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
+	-e ':c; s/\*(\([^SORT)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
+	-e ':d; s/\*(\([^SORT)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
 	-e 's/\.{text}/.text/g'
 
 quiet_cmd__cpp_lds_S = LDS     $@
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 02/14] xtensa: skip adding literal when SORT() is used
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

When SORT(foo.*) is used the current sed replacements add
SORT(foo.literal foo.*), this breaks linking. Avoid adding
literals for SORT globs, if needed, these need to be added
manually.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/xtensa/kernel/Makefile | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index 264fb89c444e..ccedd016a8e0 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -30,10 +30,10 @@ AFLAGS_mxhead.o += -mtext-section-literals
 #
 # Replicate rules in scripts/Makefile.build
 
-sed-y = -e ':a; s/\*(\([^)]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
-	-e ':b; s/\*(\([^)]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
-	-e ':c; s/\*(\([^)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
-	-e ':d; s/\*(\([^)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
+sed-y = -e ':a; s/\*(\([^)SORT]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
+	-e ':b; s/\*(\([^)SORT]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
+	-e ':c; s/\*(\([^SORT)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
+	-e ':d; s/\*(\([^SORT)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
 	-e 's/\.{text}/.text/g'
 
 quiet_cmd__cpp_lds_S = LDS     $@
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 02/14] xtensa: skip adding literal when SORT() is used
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

When SORT(foo.*) is used the current sed replacements add
SORT(foo.literal foo.*), this breaks linking. Avoid adding
literals for SORT globs, if needed, these need to be added
manually.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/xtensa/kernel/Makefile | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index 264fb89c444e..ccedd016a8e0 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -30,10 +30,10 @@ AFLAGS_mxhead.o += -mtext-section-literals
 #
 # Replicate rules in scripts/Makefile.build
 
-sed-y = -e ':a; s/\*(\([^)]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
-	-e ':b; s/\*(\([^)]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
-	-e ':c; s/\*(\([^)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
-	-e ':d; s/\*(\([^)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
+sed-y = -e ':a; s/\*(\([^)SORT]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
+	-e ':b; s/\*(\([^)SORT]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
+	-e ':c; s/\*(\([^SORT)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
+	-e ':d; s/\*(\([^SORT)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
 	-e 's/\.{text}/.text/g'
 
 quiet_cmd__cpp_lds_S = LDS     $@
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 03/14] ranges.h: add helpers to build and identify Linux section ranges
  2017-01-15 21:10         ` Luis R. Rodriguez
  (?)
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Section ranges are on one of the types of custom sections
types used in Linux. This provides a series of helpers for
defining them and using them. Most importantly this also
enables us to avoid modifying the linker script when we
add a new section range.

It turns out a lot of custom sections are actually section ranges,
and these are typically spelled out in their architecture specific
asm/sections.h file -- we enable architectures to override what asm
is used for section ranges but start by default trusting the
asm-generic version all around.

Although typically you will not want to have section ranges ordered
we must use SORT() on vmlinux.lds.S for section ranges to enable us
to extend a section range without modifying the linker script. To
accomplish this we use a special order string for the first element of a
section range -- the empty string "" (refer to __SECTION_RANGE_BEGIN()),
then "~" for the last element (refer to __SECTION_RANGE_BEGIN()). If
you use the "any" order for elements in between and use SORT() you end
up keeping any added element in between and a reference to the
beginning and end of the section range without requiring custom linker
script modifications. Specific order annotations are also supported
to help construct synthetic functions, a demo for which will be provided
later.

v6: ran /scripts/checkpatch.pl --codespell

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

o Extend commit log to justify SORT() and explain why and how we use
  specific special strings for the beginning, end elements of a section
  range and the "any" order for elements in between.

o Drop SECTION_RNG_ALL() -- we no longer need this on linker scripts

o To make this easier to read, as per Nicholas Piggin, add our own
  SECTION_RANGE_START(), SECTION_RANGE_END(). After reviewing the
  changes affected by this it seemed clearer and better then to also
  use our own specific SECTION_RANGE_SIZE(), and SECTION_RANGE_EMPTY(),
  and SECTION_RANGE_ALIGNMENT() as well.

o We were using LINUX_SECTION_START() and LINUX_SECTION_END() in
  some places but in some other places VMLINUX_SYMBOL(name),
  VMLINUX_SYMBOL(name##__end). Since we are adding SECTION_RANGE_START()
  and SECTION_RANGE_END() just use those consistently.

o Move the linker table *(SORT(.data.rng.*)) to be present before
  the recently added *(.data.[0-9a-zA-Z_]*) to ensure we keep sort order
  on the section range.

o Adds the "Linux section ordering" documentation, as its much more
  relevant after this patch, in particular when treating the "any"
  order level.

o Fix powerpc .text use: -- it does not use TEXT_TEXT so we must
  add our *(SORT(.text.rng.*)) to its linker script manually.

v4:

o tons of documentation love
o fix arch/x86/tools/relocs.c typo - which caused compilation issues
  on old toolchains
o port to new shiny sphinx documentation
o sprinkle a few more needed VMLINUX_SYMBOL() - fixes
  compilation on blackfin
o name changes as suggested 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
- rebrand DECLARE_SECTION_RNG() as DEFINE_SECTION_RANGE() - this is
  the asm version of the respective C version, this will have a
  userspace C demo added later.
o move __LINUX_RANGE() and __LINUX_RANGE_ORDER() - fixes builds
  on sparc
o adds section ranges to linker script
o rename SECTION_RANGE_ALL()
o use default alignment, fixes builds on powerpc and arm for both
  __LINUX_RANGE() and __LINUX_RANGE_ORDER()
o expand documentation to document modules support
o add maintainers
o use generic-y

v3: new in this series, uses copyleft-next

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst        |   1 +
 Documentation/sections/ranges.rst       |  74 +++++++++++++
 Documentation/sections/section-core.rst |   5 +
 MAINTAINERS                             |  10 ++
 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/Kbuild             |   1 +
 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/powerpc/kernel/vmlinux.lds.S       |   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            |  93 ++++++++++++++++
 include/asm-generic/section-core.h      |  41 +++++++
 include/asm-generic/vmlinux.lds.h       |  12 ++-
 include/linux/ranges.h                  | 183 ++++++++++++++++++++++++++++++++
 41 files changed, 451 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/linux/ranges.h

diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
index f37511ef05e7..4a1df389fa91 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -15,3 +15,4 @@ common a set of Linux helpers for ELF sections are also documented.
 
    background
    section-core
+   ranges
diff --git a/Documentation/sections/ranges.rst b/Documentation/sections/ranges.rst
new file mode 100644
index 000000000000..d9d3af4e52cb
--- /dev/null
+++ b/Documentation/sections/ranges.rst
@@ -0,0 +1,74 @@
+==========
+Linux section ranges
+==========
+
+This documents Linux' use of section ranges, how you can use
+them and how they work.
+
+About section ranges
+==========
+
+Introduction
+------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Introduction
+
+Section range module support
+----------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range module support
+
+Section range helpers
+==========+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range helpers
+
+SECTION_RANGE_START
+-------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_START
+
+SECTION_RANGE_END
+-----------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_END
+
+SECTION_RANGE_SIZE
+------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_SIZE
+
+SECTION_RANGE_EMPTY
+-------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_EMPTY
+
+SECTION_RANGE_ADDR_WITHIN
+-------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_ADDR_WITHIN
+
+SECTION_RANGE_ALIGNMENT
+-------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_ALIGNMENT
+
+DECLARE_SECTION_RANGE
+---------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DECLARE_SECTION_RANGE
+
+DEFINE_SECTION_RANGE
+--------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DEFINE_SECTION_RANGE
+
+__LINUX_RANGE
+-------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE
+
+__LINUX_RANGE_ORDER
+-------------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE_ORDER
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
index ac5815a0d9b3..1f613a6c7b78 100644
--- a/Documentation/sections/section-core.rst
+++ b/Documentation/sections/section-core.rst
@@ -114,6 +114,11 @@ Linux .ref\* sections
 .. kernel-doc:: include/asm-generic/section-core.h
    :doc: .ref.rodata
 
+Linux section ordering
+===========
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux section ordering
+
 Generic Linux kernel section helpers
 ==================
 
diff --git a/MAINTAINERS b/MAINTAINERS
index 5e580b1257fb..e0f29ccda90b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5438,6 +5438,16 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTION RANGES
+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
+S:	Supported
+F:	include/asm-generic/ranges.h
+F:	include/linux/ranges.h
+F:	Documentation/sections/ranges.rst
+
 GENERIC SECTIONS
 M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
 M:	Josh Poimboeuf <jpoimboe@redhat.com>
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index 5422827f1585..e44c896b91c4 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 7b2cb3dea5fc..a374b7f83888 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -52,3 +52,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 9b69a22a9ae1..0d47f98ccbc0 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -42,3 +42,4 @@ generic-y += unaligned.h
 generated-y += mach-types.h
 generated-y += unistd-nr.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 00ace5e826f1..e9939cbd9067 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index f2c3b656a0e7..edc176348d7c 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -23,3 +23,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index bf20541bcf21..3428415b1996 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 38127ce747be..cede2a950fbf 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 385cd88a9d9e..fb8bb4112773 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 46d7c599d9b8..5191fec655d7 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 1ec04ec1c82b..7929a992566c 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -76,3 +76,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index 37d7bfae7619..af17ee334788 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 672c6d5da18c..d8f226b35a0a 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 8ccfb5eb9678..aa9739ed9f2a 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1277b45bf4f9..006e2863ad37 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index b1011375cd7a..4a8471434a3e 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -56,3 +56,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index c6c2cf6edc98..63c083a1f8da 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 7a932b4a5531..e844d6058248 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index f8145bc85835..656af7b69940 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index c9c7cb82b00f..c55880659d67 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 86175e701869..7d6a704b808c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -72,3 +72,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 18a9d4c5ead7..f11d1249738f 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 4322d9746cdb..60d8349241a7 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 7394b770ae1f..fcfc9d102348 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -107,6 +107,7 @@ SECTIONS
 #endif
 		/* careful! __ftr_alt_* sections need to be close to .text */
 		*(.text .fixup __ftr_alt_* .ref.text)
+		*(SORT(.text.rng.*))
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 63a1c2924b91..c1b85a361e5d 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index f089a264cd38..f0cdb2cbca4d 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -15,3 +15,4 @@ generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 7b0356dca562..c9bb7932a3d1 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 438f86573dc5..28280887ac79 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index fb6b831c1fba..33f7069763ae 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 580bd5ff828f..b952dcb3e216 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -27,3 +27,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 8578702d4998..93abbfdab543 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += ranges.h
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index af975f21eeee..f672f2fc181d 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index 73eb7fd4aec4..f96fa2ddf7c9 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -68,6 +68,8 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
 	"__end_rodata|"
 	"__initramfs_start|"
 	"(jiffies|jiffies_64)|"
+	".rodata..rng.*|"
+	".init.text..rng.*|"
 #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 7879c31e66a7..2b7fe48c0225 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -33,3 +33,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/include/asm-generic/ranges.h b/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..10e67bcf6dbe
--- /dev/null
+++ b/include/asm-generic/ranges.h
@@ -0,0 +1,93 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  any, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       any, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   any, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(#section "..rng.name.any")))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using binutils
+ *	SORT(), the number is sorted as a string, as such be sure to fill with
+ *	zeroes any empty digits. For instance if you are using 3 levels of
+ *	digits for order levels, use 001 for the first entry, 0002 for the
+ *	second, 999 for the last entry. You can use however many digits you
+ *	need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(#section "..rng.name." #level)))
+
+#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/section-core.h b/include/asm-generic/section-core.h
index efc753e80d76..e2db4da87222 100644
--- a/include/asm-generic/section-core.h
+++ b/include/asm-generic/section-core.h
@@ -183,6 +183,47 @@
  * or data structures part of the init sections.
  */
 
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections alpha numerically. Linux has historically used 'SORT()' in
+ * ``include/asm-generic/vmlinux.lds.h``, its a well established practice. If
+ * 'SORT()' is used on a section one can provide ordering using a postfix on
+ * each section entry added. For instance if a linker script uses::
+ *
+ *    SORT(.foo.*)
+ *
+ * one can then add entries with explicit ordering using numeric postfixes for
+ * each entry, we refer to these as 'order levels'. Since 'SORT()' sorts alpha
+ * numerically a specific series set of digits must be agreed a-priori which
+ * would give also an idea of the max expected number of entries added to a
+ * section. For instance, if you expect a maximum of 999 entries you can use
+ * 3 digits for a section order level. If you wanted an entry to be ordered
+ * first you could use the postfix '000', if you wanted an entry to follow this
+ * you could use '001', and so on. We could for instance have::
+ *
+ *    .foo.000
+ *    .foo.001
+ *    .foo.002
+ *
+ * Often times one may want the option to specify no order is required for
+ * certain elements added to a section which does use 'SORT()' on the linker
+ * script. You can use any arbitrary string value to to specify no order is
+ * used, so long as its used consistantly. For instance, one possibility is to
+ * use the 'any' postfix.  All entries on the section would then have no
+ * specific ordering::
+ *
+ *    .foo.any
+ *    .foo.any
+ *    .foo.any
+ *
+ * To help establish a convention we reserve the special name 'any' for this
+ * purpose. Developers can use and expect the 'any' postfix string on sections
+ * as a helper to annotate section ordering at link time is not relevant
+ * for entries on a section.
+ */
+
 /* Can be used on foo.S for instance */
 #ifndef __set_section_core_type
 # define __set_section_core_type(___section, ___core, ___name,		\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 483f60c451f9..71bfd3b3c719 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -56,6 +56,7 @@
 
 #include <linux/export.h>
 #include <asm/section-core.h>
+#include <asm/ranges.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
@@ -205,6 +206,7 @@
  */
 #define DATA_DATA							\
 	*(.data .data.[0-9a-zA-Z_]*)					\
+	*(SORT(.data..rng.*))						\
 	*(.ref.data)							\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -273,7 +275,9 @@
 	. = ALIGN((align));						\
 	.rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {		\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
-		*(.rodata) *(.rodata.*)					\
+		*(.rodata)						\
+		*(SORT(.rodata..rng.*))					\
+		*(.rodata.*)						\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		KEEP(*(__vermagic))	/* Kernel version magic */	\
 		. = ALIGN(8);						\
@@ -446,7 +450,9 @@
  * conflicting section names, and must pull in .text.[0-9a-zA-Z_]* */
 #define TEXT_TEXT							\
 		ALIGN_FUNCTION();					\
-		*(.text.hot .text .text.fixup .text.unlikely)		\
+		*(.text.hot .text)					\
+		*(SORT(.text..rng.*))					\
+		*(.text.fixup .text.unlikely)				\
 		*(.ref.text)						\
 	MEM_KEEP(init.text)						\
 	MEM_KEEP(exit.text)						\
@@ -549,6 +555,7 @@
 #define INIT_DATA							\
 	KEEP(*(SORT(___kentry+*)))					\
 	*(.init.data)							\
+	*(SORT(.init.data..rng.*))					\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -572,6 +579,7 @@
 
 #define INIT_TEXT							\
 	*(.init.text)							\
+	*(SORT(.init.text..rng.*))					\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/ranges.h b/include/linux/ranges.h
new file mode 100644
index 000000000000..3368fc475cd8
--- /dev/null
+++ b/include/linux/ranges.h
@@ -0,0 +1,183 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * SECTION_RANGE_START - get address of start of section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the start address of the section range.
+ * This should give you the address of the first entry.
+ *
+ */
+#define SECTION_RANGE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * SECTION_RANGE_END - get address of end of the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define SECTION_RANGE_END(name)		LINUX_SECTION_END(name)
+
+/**
+ * SECTION_RANGE_SIZE - get number of entries in the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the number of entries in the section range.
+ * Example usage:
+ *
+ *   unsigned int num_ents = LINKTABLE_SIZE(some_fns);
+ */
+#define SECTION_RANGE_SIZE(name)					\
+	((SECTION_RANGE_END(name)) - (SECTION_RANGE_START(name)))
+
+/**
+ * SECTION_RANGE_EMPTY - check if section range has no entries
+ *
+ * @name: name of the section range
+ *
+ * Returns true if the section range is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(some_fns);
+ */
+#define SECTION_RANGE_EMPTY(name)	(SECTION_RANGE_SIZE(name) = 0)
+
+/**
+ * SECTION_RANGE_ADDR_WITHIN - returns true if address is in the section range
+ *
+ * @name: name of the section range
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_RANGE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) SECTION_RANGE_START(name) &&		\
+	  addr < (unsigned long) SECTION_RANGE_END(name))
+
+/**
+ * SECTION_RANGE_ALIGNMENT - get the alignment of the section range
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the section range.
+ */
+#define SECTION_RANGE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.")))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.~")))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) SECTION_RANGE_START(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) SECTION_RANGE_END(name)[0] = {}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 03/14] ranges.h: add helpers to build and identify Linux section ranges
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Section ranges are on one of the types of custom sections
types used in Linux. This provides a series of helpers for
defining them and using them. Most importantly this also
enables us to avoid modifying the linker script when we
add a new section range.

It turns out a lot of custom sections are actually section ranges,
and these are typically spelled out in their architecture specific
asm/sections.h file -- we enable architectures to override what asm
is used for section ranges but start by default trusting the
asm-generic version all around.

Although typically you will not want to have section ranges ordered
we must use SORT() on vmlinux.lds.S for section ranges to enable us
to extend a section range without modifying the linker script. To
accomplish this we use a special order string for the first element of a
section range -- the empty string "" (refer to __SECTION_RANGE_BEGIN()),
then "~" for the last element (refer to __SECTION_RANGE_BEGIN()). If
you use the "any" order for elements in between and use SORT() you end
up keeping any added element in between and a reference to the
beginning and end of the section range without requiring custom linker
script modifications. Specific order annotations are also supported
to help construct synthetic functions, a demo for which will be provided
later.

v6: ran /scripts/checkpatch.pl --codespell

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

o Extend commit log to justify SORT() and explain why and how we use
  specific special strings for the beginning, end elements of a section
  range and the "any" order for elements in between.

o Drop SECTION_RNG_ALL() -- we no longer need this on linker scripts

o To make this easier to read, as per Nicholas Piggin, add our own
  SECTION_RANGE_START(), SECTION_RANGE_END(). After reviewing the
  changes affected by this it seemed clearer and better then to also
  use our own specific SECTION_RANGE_SIZE(), and SECTION_RANGE_EMPTY(),
  and SECTION_RANGE_ALIGNMENT() as well.

o We were using LINUX_SECTION_START() and LINUX_SECTION_END() in
  some places but in some other places VMLINUX_SYMBOL(name),
  VMLINUX_SYMBOL(name##__end). Since we are adding SECTION_RANGE_START()
  and SECTION_RANGE_END() just use those consistently.

o Move the linker table *(SORT(.data.rng.*)) to be present before
  the recently added *(.data.[0-9a-zA-Z_]*) to ensure we keep sort order
  on the section range.

o Adds the "Linux section ordering" documentation, as its much more
  relevant after this patch, in particular when treating the "any"
  order level.

o Fix powerpc .text use: -- it does not use TEXT_TEXT so we must
  add our *(SORT(.text.rng.*)) to its linker script manually.

v4:

o tons of documentation love
o fix arch/x86/tools/relocs.c typo - which caused compilation issues
  on old toolchains
o port to new shiny sphinx documentation
o sprinkle a few more needed VMLINUX_SYMBOL() - fixes
  compilation on blackfin
o name changes as suggested 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
- rebrand DECLARE_SECTION_RNG() as DEFINE_SECTION_RANGE() - this is
  the asm version of the respective C version, this will have a
  userspace C demo added later.
o move __LINUX_RANGE() and __LINUX_RANGE_ORDER() - fixes builds
  on sparc
o adds section ranges to linker script
o rename SECTION_RANGE_ALL()
o use default alignment, fixes builds on powerpc and arm for both
  __LINUX_RANGE() and __LINUX_RANGE_ORDER()
o expand documentation to document modules support
o add maintainers
o use generic-y

v3: new in this series, uses copyleft-next

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst        |   1 +
 Documentation/sections/ranges.rst       |  74 +++++++++++++
 Documentation/sections/section-core.rst |   5 +
 MAINTAINERS                             |  10 ++
 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/Kbuild             |   1 +
 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/powerpc/kernel/vmlinux.lds.S       |   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            |  93 ++++++++++++++++
 include/asm-generic/section-core.h      |  41 +++++++
 include/asm-generic/vmlinux.lds.h       |  12 ++-
 include/linux/ranges.h                  | 183 ++++++++++++++++++++++++++++++++
 41 files changed, 451 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/linux/ranges.h

diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
index f37511ef05e7..4a1df389fa91 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -15,3 +15,4 @@ common a set of Linux helpers for ELF sections are also documented.
 
    background
    section-core
+   ranges
diff --git a/Documentation/sections/ranges.rst b/Documentation/sections/ranges.rst
new file mode 100644
index 000000000000..d9d3af4e52cb
--- /dev/null
+++ b/Documentation/sections/ranges.rst
@@ -0,0 +1,74 @@
+====================
+Linux section ranges
+====================
+
+This documents Linux' use of section ranges, how you can use
+them and how they work.
+
+About section ranges
+====================
+
+Introduction
+------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Introduction
+
+Section range module support
+----------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range module support
+
+Section range helpers
+=====================
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range helpers
+
+SECTION_RANGE_START
+-------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_START
+
+SECTION_RANGE_END
+-----------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_END
+
+SECTION_RANGE_SIZE
+------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_SIZE
+
+SECTION_RANGE_EMPTY
+-------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_EMPTY
+
+SECTION_RANGE_ADDR_WITHIN
+-------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_ADDR_WITHIN
+
+SECTION_RANGE_ALIGNMENT
+-------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_ALIGNMENT
+
+DECLARE_SECTION_RANGE
+---------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DECLARE_SECTION_RANGE
+
+DEFINE_SECTION_RANGE
+--------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DEFINE_SECTION_RANGE
+
+__LINUX_RANGE
+-------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE
+
+__LINUX_RANGE_ORDER
+-------------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE_ORDER
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
index ac5815a0d9b3..1f613a6c7b78 100644
--- a/Documentation/sections/section-core.rst
+++ b/Documentation/sections/section-core.rst
@@ -114,6 +114,11 @@ Linux .ref\* sections
 .. kernel-doc:: include/asm-generic/section-core.h
    :doc: .ref.rodata
 
+Linux section ordering
+======================
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux section ordering
+
 Generic Linux kernel section helpers
 ====================================
 
diff --git a/MAINTAINERS b/MAINTAINERS
index 5e580b1257fb..e0f29ccda90b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5438,6 +5438,16 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTION RANGES
+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
+S:	Supported
+F:	include/asm-generic/ranges.h
+F:	include/linux/ranges.h
+F:	Documentation/sections/ranges.rst
+
 GENERIC SECTIONS
 M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
 M:	Josh Poimboeuf <jpoimboe@redhat.com>
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index 5422827f1585..e44c896b91c4 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 7b2cb3dea5fc..a374b7f83888 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -52,3 +52,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 9b69a22a9ae1..0d47f98ccbc0 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -42,3 +42,4 @@ generic-y += unaligned.h
 generated-y += mach-types.h
 generated-y += unistd-nr.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 00ace5e826f1..e9939cbd9067 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index f2c3b656a0e7..edc176348d7c 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -23,3 +23,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index bf20541bcf21..3428415b1996 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 38127ce747be..cede2a950fbf 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 385cd88a9d9e..fb8bb4112773 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 46d7c599d9b8..5191fec655d7 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 1ec04ec1c82b..7929a992566c 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -76,3 +76,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index 37d7bfae7619..af17ee334788 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 672c6d5da18c..d8f226b35a0a 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 8ccfb5eb9678..aa9739ed9f2a 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1277b45bf4f9..006e2863ad37 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index b1011375cd7a..4a8471434a3e 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -56,3 +56,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index c6c2cf6edc98..63c083a1f8da 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 7a932b4a5531..e844d6058248 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index f8145bc85835..656af7b69940 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index c9c7cb82b00f..c55880659d67 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 86175e701869..7d6a704b808c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -72,3 +72,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 18a9d4c5ead7..f11d1249738f 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 4322d9746cdb..60d8349241a7 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 7394b770ae1f..fcfc9d102348 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -107,6 +107,7 @@ SECTIONS
 #endif
 		/* careful! __ftr_alt_* sections need to be close to .text */
 		*(.text .fixup __ftr_alt_* .ref.text)
+		*(SORT(.text.rng.*))
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 63a1c2924b91..c1b85a361e5d 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index f089a264cd38..f0cdb2cbca4d 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -15,3 +15,4 @@ generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 7b0356dca562..c9bb7932a3d1 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 438f86573dc5..28280887ac79 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index fb6b831c1fba..33f7069763ae 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 580bd5ff828f..b952dcb3e216 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -27,3 +27,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 8578702d4998..93abbfdab543 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += ranges.h
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index af975f21eeee..f672f2fc181d 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index 73eb7fd4aec4..f96fa2ddf7c9 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -68,6 +68,8 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
 	"__end_rodata|"
 	"__initramfs_start|"
 	"(jiffies|jiffies_64)|"
+	".rodata..rng.*|"
+	".init.text..rng.*|"
 #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 7879c31e66a7..2b7fe48c0225 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -33,3 +33,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/include/asm-generic/ranges.h b/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..10e67bcf6dbe
--- /dev/null
+++ b/include/asm-generic/ranges.h
@@ -0,0 +1,93 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  any, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       any, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   any, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(#section "..rng.name.any")))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using binutils
+ *	SORT(), the number is sorted as a string, as such be sure to fill with
+ *	zeroes any empty digits. For instance if you are using 3 levels of
+ *	digits for order levels, use 001 for the first entry, 0002 for the
+ *	second, 999 for the last entry. You can use however many digits you
+ *	need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(#section "..rng.name." #level)))
+
+#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/section-core.h b/include/asm-generic/section-core.h
index efc753e80d76..e2db4da87222 100644
--- a/include/asm-generic/section-core.h
+++ b/include/asm-generic/section-core.h
@@ -183,6 +183,47 @@
  * or data structures part of the init sections.
  */
 
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections alpha numerically. Linux has historically used 'SORT()' in
+ * ``include/asm-generic/vmlinux.lds.h``, its a well established practice. If
+ * 'SORT()' is used on a section one can provide ordering using a postfix on
+ * each section entry added. For instance if a linker script uses::
+ *
+ *    SORT(.foo.*)
+ *
+ * one can then add entries with explicit ordering using numeric postfixes for
+ * each entry, we refer to these as 'order levels'. Since 'SORT()' sorts alpha
+ * numerically a specific series set of digits must be agreed a-priori which
+ * would give also an idea of the max expected number of entries added to a
+ * section. For instance, if you expect a maximum of 999 entries you can use
+ * 3 digits for a section order level. If you wanted an entry to be ordered
+ * first you could use the postfix '000', if you wanted an entry to follow this
+ * you could use '001', and so on. We could for instance have::
+ *
+ *    .foo.000
+ *    .foo.001
+ *    .foo.002
+ *
+ * Often times one may want the option to specify no order is required for
+ * certain elements added to a section which does use 'SORT()' on the linker
+ * script. You can use any arbitrary string value to to specify no order is
+ * used, so long as its used consistantly. For instance, one possibility is to
+ * use the 'any' postfix.  All entries on the section would then have no
+ * specific ordering::
+ *
+ *    .foo.any
+ *    .foo.any
+ *    .foo.any
+ *
+ * To help establish a convention we reserve the special name 'any' for this
+ * purpose. Developers can use and expect the 'any' postfix string on sections
+ * as a helper to annotate section ordering at link time is not relevant
+ * for entries on a section.
+ */
+
 /* Can be used on foo.S for instance */
 #ifndef __set_section_core_type
 # define __set_section_core_type(___section, ___core, ___name,		\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 483f60c451f9..71bfd3b3c719 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -56,6 +56,7 @@
 
 #include <linux/export.h>
 #include <asm/section-core.h>
+#include <asm/ranges.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
@@ -205,6 +206,7 @@
  */
 #define DATA_DATA							\
 	*(.data .data.[0-9a-zA-Z_]*)					\
+	*(SORT(.data..rng.*))						\
 	*(.ref.data)							\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -273,7 +275,9 @@
 	. = ALIGN((align));						\
 	.rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {		\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
-		*(.rodata) *(.rodata.*)					\
+		*(.rodata)						\
+		*(SORT(.rodata..rng.*))					\
+		*(.rodata.*)						\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		KEEP(*(__vermagic))	/* Kernel version magic */	\
 		. = ALIGN(8);						\
@@ -446,7 +450,9 @@
  * conflicting section names, and must pull in .text.[0-9a-zA-Z_]* */
 #define TEXT_TEXT							\
 		ALIGN_FUNCTION();					\
-		*(.text.hot .text .text.fixup .text.unlikely)		\
+		*(.text.hot .text)					\
+		*(SORT(.text..rng.*))					\
+		*(.text.fixup .text.unlikely)				\
 		*(.ref.text)						\
 	MEM_KEEP(init.text)						\
 	MEM_KEEP(exit.text)						\
@@ -549,6 +555,7 @@
 #define INIT_DATA							\
 	KEEP(*(SORT(___kentry+*)))					\
 	*(.init.data)							\
+	*(SORT(.init.data..rng.*))					\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -572,6 +579,7 @@
 
 #define INIT_TEXT							\
 	*(.init.text)							\
+	*(SORT(.init.text..rng.*))					\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/ranges.h b/include/linux/ranges.h
new file mode 100644
index 000000000000..3368fc475cd8
--- /dev/null
+++ b/include/linux/ranges.h
@@ -0,0 +1,183 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * SECTION_RANGE_START - get address of start of section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the start address of the section range.
+ * This should give you the address of the first entry.
+ *
+ */
+#define SECTION_RANGE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * SECTION_RANGE_END - get address of end of the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define SECTION_RANGE_END(name)		LINUX_SECTION_END(name)
+
+/**
+ * SECTION_RANGE_SIZE - get number of entries in the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the number of entries in the section range.
+ * Example usage:
+ *
+ *   unsigned int num_ents = LINKTABLE_SIZE(some_fns);
+ */
+#define SECTION_RANGE_SIZE(name)					\
+	((SECTION_RANGE_END(name)) - (SECTION_RANGE_START(name)))
+
+/**
+ * SECTION_RANGE_EMPTY - check if section range has no entries
+ *
+ * @name: name of the section range
+ *
+ * Returns true if the section range is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(some_fns);
+ */
+#define SECTION_RANGE_EMPTY(name)	(SECTION_RANGE_SIZE(name) == 0)
+
+/**
+ * SECTION_RANGE_ADDR_WITHIN - returns true if address is in the section range
+ *
+ * @name: name of the section range
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_RANGE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) SECTION_RANGE_START(name) &&		\
+	  addr < (unsigned long) SECTION_RANGE_END(name))
+
+/**
+ * SECTION_RANGE_ALIGNMENT - get the alignment of the section range
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the section range.
+ */
+#define SECTION_RANGE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.")))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.~")))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) SECTION_RANGE_START(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) SECTION_RANGE_END(name)[0] = {}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 03/14] ranges.h: add helpers to build and identify Linux section ranges
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

Section ranges are on one of the types of custom sections
types used in Linux. This provides a series of helpers for
defining them and using them. Most importantly this also
enables us to avoid modifying the linker script when we
add a new section range.

It turns out a lot of custom sections are actually section ranges,
and these are typically spelled out in their architecture specific
asm/sections.h file -- we enable architectures to override what asm
is used for section ranges but start by default trusting the
asm-generic version all around.

Although typically you will not want to have section ranges ordered
we must use SORT() on vmlinux.lds.S for section ranges to enable us
to extend a section range without modifying the linker script. To
accomplish this we use a special order string for the first element of a
section range -- the empty string "" (refer to __SECTION_RANGE_BEGIN()),
then "~" for the last element (refer to __SECTION_RANGE_BEGIN()). If
you use the "any" order for elements in between and use SORT() you end
up keeping any added element in between and a reference to the
beginning and end of the section range without requiring custom linker
script modifications. Specific order annotations are also supported
to help construct synthetic functions, a demo for which will be provided
later.

v6: ran /scripts/checkpatch.pl --codespell

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

o Extend commit log to justify SORT() and explain why and how we use
  specific special strings for the beginning, end elements of a section
  range and the "any" order for elements in between.

o Drop SECTION_RNG_ALL() -- we no longer need this on linker scripts

o To make this easier to read, as per Nicholas Piggin, add our own
  SECTION_RANGE_START(), SECTION_RANGE_END(). After reviewing the
  changes affected by this it seemed clearer and better then to also
  use our own specific SECTION_RANGE_SIZE(), and SECTION_RANGE_EMPTY(),
  and SECTION_RANGE_ALIGNMENT() as well.

o We were using LINUX_SECTION_START() and LINUX_SECTION_END() in
  some places but in some other places VMLINUX_SYMBOL(name),
  VMLINUX_SYMBOL(name##__end). Since we are adding SECTION_RANGE_START()
  and SECTION_RANGE_END() just use those consistently.

o Move the linker table *(SORT(.data.rng.*)) to be present before
  the recently added *(.data.[0-9a-zA-Z_]*) to ensure we keep sort order
  on the section range.

o Adds the "Linux section ordering" documentation, as its much more
  relevant after this patch, in particular when treating the "any"
  order level.

o Fix powerpc .text use: -- it does not use TEXT_TEXT so we must
  add our *(SORT(.text.rng.*)) to its linker script manually.

v4:

o tons of documentation love
o fix arch/x86/tools/relocs.c typo - which caused compilation issues
  on old toolchains
o port to new shiny sphinx documentation
o sprinkle a few more needed VMLINUX_SYMBOL() - fixes
  compilation on blackfin
o name changes as suggested 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
- rebrand DECLARE_SECTION_RNG() as DEFINE_SECTION_RANGE() - this is
  the asm version of the respective C version, this will have a
  userspace C demo added later.
o move __LINUX_RANGE() and __LINUX_RANGE_ORDER() - fixes builds
  on sparc
o adds section ranges to linker script
o rename SECTION_RANGE_ALL()
o use default alignment, fixes builds on powerpc and arm for both
  __LINUX_RANGE() and __LINUX_RANGE_ORDER()
o expand documentation to document modules support
o add maintainers
o use generic-y

v3: new in this series, uses copyleft-next

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst        |   1 +
 Documentation/sections/ranges.rst       |  74 +++++++++++++
 Documentation/sections/section-core.rst |   5 +
 MAINTAINERS                             |  10 ++
 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/Kbuild             |   1 +
 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/powerpc/kernel/vmlinux.lds.S       |   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            |  93 ++++++++++++++++
 include/asm-generic/section-core.h      |  41 +++++++
 include/asm-generic/vmlinux.lds.h       |  12 ++-
 include/linux/ranges.h                  | 183 ++++++++++++++++++++++++++++++++
 41 files changed, 451 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/sections/ranges.rst
 create mode 100644 include/asm-generic/ranges.h
 create mode 100644 include/linux/ranges.h

diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
index f37511ef05e7..4a1df389fa91 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -15,3 +15,4 @@ common a set of Linux helpers for ELF sections are also documented.
 
    background
    section-core
+   ranges
diff --git a/Documentation/sections/ranges.rst b/Documentation/sections/ranges.rst
new file mode 100644
index 000000000000..d9d3af4e52cb
--- /dev/null
+++ b/Documentation/sections/ranges.rst
@@ -0,0 +1,74 @@
+====================
+Linux section ranges
+====================
+
+This documents Linux' use of section ranges, how you can use
+them and how they work.
+
+About section ranges
+====================
+
+Introduction
+------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Introduction
+
+Section range module support
+----------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range module support
+
+Section range helpers
+=====================
+.. kernel-doc:: include/linux/ranges.h
+   :doc: Section range helpers
+
+SECTION_RANGE_START
+-------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_START
+
+SECTION_RANGE_END
+-----------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_END
+
+SECTION_RANGE_SIZE
+------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_SIZE
+
+SECTION_RANGE_EMPTY
+-------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_EMPTY
+
+SECTION_RANGE_ADDR_WITHIN
+-------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_ADDR_WITHIN
+
+SECTION_RANGE_ALIGNMENT
+-------------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: SECTION_RANGE_ALIGNMENT
+
+DECLARE_SECTION_RANGE
+---------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DECLARE_SECTION_RANGE
+
+DEFINE_SECTION_RANGE
+--------------------
+.. kernel-doc:: include/linux/ranges.h
+   :functions: DEFINE_SECTION_RANGE
+
+__LINUX_RANGE
+-------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE
+
+__LINUX_RANGE_ORDER
+-------------------
+.. kernel-doc:: include/asm-generic/ranges.h
+   :functions: __LINUX_RANGE_ORDER
diff --git a/Documentation/sections/section-core.rst b/Documentation/sections/section-core.rst
index ac5815a0d9b3..1f613a6c7b78 100644
--- a/Documentation/sections/section-core.rst
+++ b/Documentation/sections/section-core.rst
@@ -114,6 +114,11 @@ Linux .ref\* sections
 .. kernel-doc:: include/asm-generic/section-core.h
    :doc: .ref.rodata
 
+Linux section ordering
+======================
+.. kernel-doc:: include/asm-generic/section-core.h
+   :doc: Linux section ordering
+
 Generic Linux kernel section helpers
 ====================================
 
diff --git a/MAINTAINERS b/MAINTAINERS
index 5e580b1257fb..e0f29ccda90b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5438,6 +5438,16 @@ S:	Supported
 F:	drivers/base/power/domain*.c
 F:	include/linux/pm_domain.h
 
+GENERIC SECTION RANGES
+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
+S:	Supported
+F:	include/asm-generic/ranges.h
+F:	include/linux/ranges.h
+F:	Documentation/sections/ranges.rst
+
 GENERIC SECTIONS
 M:	"Luis R. Rodriguez" <mcgrof@kernel.org>
 M:	Josh Poimboeuf <jpoimboe@redhat.com>
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index 5422827f1585..e44c896b91c4 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arc/include/asm/Kbuild b/arch/arc/include/asm/Kbuild
index 7b2cb3dea5fc..a374b7f83888 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -52,3 +52,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild
index 9b69a22a9ae1..0d47f98ccbc0 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -42,3 +42,4 @@ generic-y += unaligned.h
 generated-y += mach-types.h
 generated-y += unistd-nr.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 00ace5e826f1..e9939cbd9067 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild
index f2c3b656a0e7..edc176348d7c 100644
--- a/arch/avr32/include/asm/Kbuild
+++ b/arch/avr32/include/asm/Kbuild
@@ -23,3 +23,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index bf20541bcf21..3428415b1996 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index 38127ce747be..cede2a950fbf 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 385cd88a9d9e..fb8bb4112773 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -46,3 +46,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 46d7c599d9b8..5191fec655d7 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index 1ec04ec1c82b..7929a992566c 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -76,3 +76,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index 37d7bfae7619..af17ee334788 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild
index 672c6d5da18c..d8f226b35a0a 100644
--- a/arch/ia64/include/asm/Kbuild
+++ b/arch/ia64/include/asm/Kbuild
@@ -10,3 +10,4 @@ generic-y += trace_clock.h
 generic-y += vtime.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index 8ccfb5eb9678..aa9739ed9f2a 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index 1277b45bf4f9..006e2863ad37 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index b1011375cd7a..4a8471434a3e 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -56,3 +56,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index c6c2cf6edc98..63c083a1f8da 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -12,3 +12,4 @@ generic-y += syscalls.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mips/include/asm/Kbuild b/arch/mips/include/asm/Kbuild
index 7a932b4a5531..e844d6058248 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += user.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild
index f8145bc85835..656af7b69940 100644
--- a/arch/mn10300/include/asm/Kbuild
+++ b/arch/mn10300/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += sections.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index c9c7cb82b00f..c55880659d67 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index 86175e701869..7d6a704b808c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -72,3 +72,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index 18a9d4c5ead7..f11d1249738f 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index 4322d9746cdb..60d8349241a7 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += rwsem.h
 generic-y += vtime.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 7394b770ae1f..fcfc9d102348 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -107,6 +107,7 @@ SECTIONS
 #endif
 		/* careful! __ftr_alt_* sections need to be close to .text */
 		*(.text .fixup __ftr_alt_* .ref.text)
+		*(SORT(.text.rng.*))
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index 63a1c2924b91..c1b85a361e5d 100644
--- a/arch/s390/include/asm/Kbuild
+++ b/arch/s390/include/asm/Kbuild
@@ -9,3 +9,4 @@ generic-y += preempt.h
 generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index f089a264cd38..f0cdb2cbca4d 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -15,3 +15,4 @@ generic-y += xor.h
 generic-y += serial.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild
index 7b0356dca562..c9bb7932a3d1 100644
--- a/arch/sh/include/asm/Kbuild
+++ b/arch/sh/include/asm/Kbuild
@@ -40,3 +40,4 @@ generic-y += trace_clock.h
 generic-y += ucontext.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild
index 438f86573dc5..28280887ac79 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -22,3 +22,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += word-at-a-time.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index fb6b831c1fba..33f7069763ae 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -41,3 +41,4 @@ generic-y += trace_clock.h
 generic-y += types.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 580bd5ff828f..b952dcb3e216 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -27,3 +27,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 8578702d4998..93abbfdab543 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -61,3 +61,4 @@ generic-y += user.h
 generic-y += vga.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
+generic-y += ranges.h
diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
index af975f21eeee..f672f2fc181d 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += early_ioremap.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index 73eb7fd4aec4..f96fa2ddf7c9 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -68,6 +68,8 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
 	"__end_rodata|"
 	"__initramfs_start|"
 	"(jiffies|jiffies_64)|"
+	".rodata..rng.*|"
+	".init.text..rng.*|"
 #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 7879c31e66a7..2b7fe48c0225 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -33,3 +33,4 @@ generic-y += trace_clock.h
 generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
+generic-y += ranges.h
diff --git a/include/asm-generic/ranges.h b/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..10e67bcf6dbe
--- /dev/null
+++ b/include/asm-generic/ranges.h
@@ -0,0 +1,93 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  any, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       any, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   any, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(#section "..rng.name.any")))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using binutils
+ *	SORT(), the number is sorted as a string, as such be sure to fill with
+ *	zeroes any empty digits. For instance if you are using 3 levels of
+ *	digits for order levels, use 001 for the first entry, 0002 for the
+ *	second, 999 for the last entry. You can use however many digits you
+ *	need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(#section "..rng.name." #level)))
+
+#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/section-core.h b/include/asm-generic/section-core.h
index efc753e80d76..e2db4da87222 100644
--- a/include/asm-generic/section-core.h
+++ b/include/asm-generic/section-core.h
@@ -183,6 +183,47 @@
  * or data structures part of the init sections.
  */
 
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections alpha numerically. Linux has historically used 'SORT()' in
+ * ``include/asm-generic/vmlinux.lds.h``, its a well established practice. If
+ * 'SORT()' is used on a section one can provide ordering using a postfix on
+ * each section entry added. For instance if a linker script uses::
+ *
+ *    SORT(.foo.*)
+ *
+ * one can then add entries with explicit ordering using numeric postfixes for
+ * each entry, we refer to these as 'order levels'. Since 'SORT()' sorts alpha
+ * numerically a specific series set of digits must be agreed a-priori which
+ * would give also an idea of the max expected number of entries added to a
+ * section. For instance, if you expect a maximum of 999 entries you can use
+ * 3 digits for a section order level. If you wanted an entry to be ordered
+ * first you could use the postfix '000', if you wanted an entry to follow this
+ * you could use '001', and so on. We could for instance have::
+ *
+ *    .foo.000
+ *    .foo.001
+ *    .foo.002
+ *
+ * Often times one may want the option to specify no order is required for
+ * certain elements added to a section which does use 'SORT()' on the linker
+ * script. You can use any arbitrary string value to to specify no order is
+ * used, so long as its used consistantly. For instance, one possibility is to
+ * use the 'any' postfix.  All entries on the section would then have no
+ * specific ordering::
+ *
+ *    .foo.any
+ *    .foo.any
+ *    .foo.any
+ *
+ * To help establish a convention we reserve the special name 'any' for this
+ * purpose. Developers can use and expect the 'any' postfix string on sections
+ * as a helper to annotate section ordering at link time is not relevant
+ * for entries on a section.
+ */
+
 /* Can be used on foo.S for instance */
 #ifndef __set_section_core_type
 # define __set_section_core_type(___section, ___core, ___name,		\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 483f60c451f9..71bfd3b3c719 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -56,6 +56,7 @@
 
 #include <linux/export.h>
 #include <asm/section-core.h>
+#include <asm/ranges.h>
 
 /* Align . to a 8 byte boundary equals to maximum function alignment. */
 #define ALIGN_FUNCTION()  . = ALIGN(8)
@@ -205,6 +206,7 @@
  */
 #define DATA_DATA							\
 	*(.data .data.[0-9a-zA-Z_]*)					\
+	*(SORT(.data..rng.*))						\
 	*(.ref.data)							\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -273,7 +275,9 @@
 	. = ALIGN((align));						\
 	.rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {		\
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
-		*(.rodata) *(.rodata.*)					\
+		*(.rodata)						\
+		*(SORT(.rodata..rng.*))					\
+		*(.rodata.*)						\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		KEEP(*(__vermagic))	/* Kernel version magic */	\
 		. = ALIGN(8);						\
@@ -446,7 +450,9 @@
  * conflicting section names, and must pull in .text.[0-9a-zA-Z_]* */
 #define TEXT_TEXT							\
 		ALIGN_FUNCTION();					\
-		*(.text.hot .text .text.fixup .text.unlikely)		\
+		*(.text.hot .text)					\
+		*(SORT(.text..rng.*))					\
+		*(.text.fixup .text.unlikely)				\
 		*(.ref.text)						\
 	MEM_KEEP(init.text)						\
 	MEM_KEEP(exit.text)						\
@@ -549,6 +555,7 @@
 #define INIT_DATA							\
 	KEEP(*(SORT(___kentry+*)))					\
 	*(.init.data)							\
+	*(SORT(.init.data..rng.*))					\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -572,6 +579,7 @@
 
 #define INIT_TEXT							\
 	*(.init.text)							\
+	*(SORT(.init.text..rng.*))					\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/ranges.h b/include/linux/ranges.h
new file mode 100644
index 000000000000..3368fc475cd8
--- /dev/null
+++ b/include/linux/ranges.h
@@ -0,0 +1,183 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * SECTION_RANGE_START - get address of start of section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the start address of the section range.
+ * This should give you the address of the first entry.
+ *
+ */
+#define SECTION_RANGE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * SECTION_RANGE_END - get address of end of the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define SECTION_RANGE_END(name)		LINUX_SECTION_END(name)
+
+/**
+ * SECTION_RANGE_SIZE - get number of entries in the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the number of entries in the section range.
+ * Example usage:
+ *
+ *   unsigned int num_ents = LINKTABLE_SIZE(some_fns);
+ */
+#define SECTION_RANGE_SIZE(name)					\
+	((SECTION_RANGE_END(name)) - (SECTION_RANGE_START(name)))
+
+/**
+ * SECTION_RANGE_EMPTY - check if section range has no entries
+ *
+ * @name: name of the section range
+ *
+ * Returns true if the section range is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(some_fns);
+ */
+#define SECTION_RANGE_EMPTY(name)	(SECTION_RANGE_SIZE(name) == 0)
+
+/**
+ * SECTION_RANGE_ADDR_WITHIN - returns true if address is in the section range
+ *
+ * @name: name of the section range
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_RANGE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) SECTION_RANGE_START(name) &&		\
+	  addr < (unsigned long) SECTION_RANGE_END(name))
+
+/**
+ * SECTION_RANGE_ALIGNMENT - get the alignment of the section range
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the section range.
+ */
+#define SECTION_RANGE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.")))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.~")))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) SECTION_RANGE_START(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) SECTION_RANGE_END(name)[0] = {}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 04/14] tables.h: add linker table support
  2017-01-15 21:10         ` Luis R. Rodriguez
  (?)
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

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.

v7: ./scripts/checkpatch.pl --codespell fixes

v6:

o rename tables macro as requested by Andy Shevchenko

v5:
o Use ..tbl.* instead of .tbl.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clashes with compiler generated
  sections.
o Replace section macros with section names
o Dropped SECTION_RNG_ALL()
o Fix documentation typos
o To make this easier to read, as per Nicholas Piggin, add our own
  LINKTABLE_START(), LINKTABLE_END(). After reviewing the changes
  affected by this it seemed clearer and better then to also
  use our own specific LINKTABLE_SIZE(), LINKTABLE_EMPTY() and
  LINKTABLE_ALIGNMENT() as well.
o Clarifies SECTION_TBL_RO needs to be kept since some toolchains
  are buggy, and so we also add SECTION_TBL_RO_STR.
o We were using LINUX_SECTION_START() and LINUX_SECTION_END() in some
  places but in some other places VMLINUX_SYMBOL(name),
  VMLINUX_SYMBOL(name##__end). Since we are adding LINKTABLE_START()
  and LINKTABLE_END() just use those consistently.
o Fix DEFINE_LINKTABLE_INIT() by making it use DECLARE_LINKTABLE_RO()
  which forces const.
o Fix powerpc .text use: it does not use TEXT_TEXT so we must
  add our *(SORT(.text.tbl.*)) to its linker script manually.

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@ipxe.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst         |   1 +
 Documentation/sections/linker-tables.rst | 212 +++++++++++
 MAINTAINERS                              |  10 +
 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/powerpc/kernel/vmlinux.lds.S        |   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/tables.h             |  48 +++
 include/asm-generic/vmlinux.lds.h        |   6 +
 include/linux/tables.h                   | 612 +++++++++++++++++++++++++++++++
 39 files changed, 948 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 4a1df389fa91..7c7c1adf955c 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -16,3 +16,4 @@ common a set of Linux helpers for ELF sections are also documented.
    background
    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..780a292d2d00
--- /dev/null
+++ b/Documentation/sections/linker-tables.rst
@@ -0,0 +1,212 @@
+=========+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_START
+---------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_START
+
+LINKTABLE_END
+-------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_END
+
+LINKTABLE_SIZE
+--------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_SIZE
+
+LINKTABLE_EMPTY
+---------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_EMPTY
+
+LINKTABLE_ADDR_WITHIN
+---------------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_ADDR_WITHIN
+
+LINKTABLE_ALIGNMENT
+-------------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_ALIGNMENT
+
+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 e0f29ccda90b..99ca436e76d9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5421,6 +5421,16 @@ 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
+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
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 a374b7f83888..ccfa69ce2608 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -53,3 +53,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 0d47f98ccbc0..b70d4b78d577 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -43,3 +43,4 @@ generated-y += mach-types.h
 generated-y += unistd-nr.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 e9939cbd9067..0c1e781ab10b 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -47,3 +47,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 3428415b1996..9115b215fc7e 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -49,3 +49,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..90a0d3df35c8
--- /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@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 weak 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 */
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 aa9739ed9f2a..f3f1e51dd5be 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -14,3 +14,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 006e2863ad37..c28bcdecc764 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -36,3 +36,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 4a8471434a3e..c836f7e2a5e7 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -57,3 +57,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 e844d6058248..db9dff9c1535 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -23,3 +23,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 f11d1249738f..aaae8a9f6099 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -30,3 +30,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 60d8349241a7..7c06627a0a0d 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -10,3 +10,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/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index fcfc9d102348..8cd940c72895 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -108,6 +108,7 @@ SECTIONS
 		/* careful! __ftr_alt_* sections need to be close to .text */
 		*(.text .fixup __ftr_alt_* .ref.text)
 		*(SORT(.text.rng.*))
+		*(SORT(.text..tbl.*))
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index c1b85a361e5d..96dd69931427 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 28280887ac79..23a2216f4146 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -23,3 +23,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 33f7069763ae..a599f6f4ee0a 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -42,3 +42,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 b952dcb3e216..d2867aa09e23 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -28,3 +28,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 93abbfdab543..6671a1f08ead 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -62,3 +62,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 f672f2fc181d..4cb511f1067c 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -14,3 +14,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 f96fa2ddf7c9..484a24c309fb 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 2b7fe48c0225..7b41f32a2ba0 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -34,3 +34,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/tables.h b/include/asm-generic/tables.h
new file mode 100644
index 000000000000..567775b292c2
--- /dev/null
+++ b/include/asm-generic/tables.h
@@ -0,0 +1,48 @@
+#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..tbl.name.level
+
+/* Some toolchains are buggy, let them override */
+#ifndef SECTION_TBL_RO
+# define SECTION_TBL_RO	.rodata
+#endif
+
+#define SECTION_TBL_RO_STR __stringify(SECTION_TBL_RO)
+
+#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, 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, 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 71bfd3b3c719..ce1e9a310ada 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)
@@ -207,6 +208,7 @@
 #define DATA_DATA							\
 	*(.data .data.[0-9a-zA-Z_]*)					\
 	*(SORT(.data..rng.*))						\
+	*(SORT(.data..tbl.*))						\
 	*(.ref.data)							\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -277,6 +279,7 @@
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
 		*(.rodata)						\
 		*(SORT(.rodata..rng.*))					\
+		*(SORT(.rodata..tbl.*))					\
 		*(.rodata.*)						\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		KEEP(*(__vermagic))	/* Kernel version magic */	\
@@ -452,6 +455,7 @@
 		ALIGN_FUNCTION();					\
 		*(.text.hot .text)					\
 		*(SORT(.text..rng.*))					\
+		*(SORT(.text..tbl.*))					\
 		*(.text.fixup .text.unlikely)				\
 		*(.ref.text)						\
 	MEM_KEEP(init.text)						\
@@ -556,6 +560,7 @@
 	KEEP(*(SORT(___kentry+*)))					\
 	*(.init.data)							\
 	*(SORT(.init.data..rng.*))					\
+	*(SORT(.init.data..tbl.*))					\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -580,6 +585,7 @@
 #define INIT_TEXT							\
 	*(.init.text)							\
 	*(SORT(.init.text..rng.*))					\
+	*(SORT(.init.text..tbl.*))					\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
new file mode 100644
index 000000000000..82da59c4266d
--- /dev/null
+++ b/include/linux/tables.h
@@ -0,0 +1,612 @@
+#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(.foo..tbl.*))
+ *
+ * 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_START - get address of start of linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the start address of the linker table.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINKTABLE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * LINKTABLE_END - get address of end of the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define LINKTABLE_END(name)	LINUX_SECTION_END(name)
+
+/**
+ * LINKTABLE_SIZE - get number of entries in the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the number of entries in the linker table.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINKTABLE_SIZE(frobnicator_fns);
+ */
+#define LINKTABLE_SIZE(name)					\
+	((LINKTABLE_END(name)) - (LINKTABLE_START(name)))
+
+/**
+ * LINKTABLE_EMPTY - check if linker table has no entries
+ *
+ * @name: name of linker table
+ *
+ * Returns true if the linker table is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(frobnicator_fns);
+ */
+#define LINKTABLE_EMPTY(name)	(LINKTABLE_SIZE(name) = 0)
+
+/**
+ * LINKTABLE_ADDR_WITHIN - returns true if address is in the linker table
+ *
+ * @name: name of the linker table
+ * @addr: address to query for
+ *
+ * Returns true if the address is part of the linker table.
+ */
+#define LINKTABLE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) LINKTABLE_START(name) &&		\
+	  addr < (unsigned long) LINKTABLE_END(name))
+
+/**
+ * LINKTABLE_ALIGNMENT - get the alignment of the linker table
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the linker table.
+ */
+#define LINKTABLE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * 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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_TEXT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE_RO(name, ~) LINKTABLE_END(name)[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_RO(type, name);				\
+	LINKTABLE_INIT_WEAK(name,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT_DATA(name, ~) LINKTABLE_END(name)[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 = LINKTABLE_START(tbl);				\
+	     pointer < LINKTABLE_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 < LINKTABLE_SIZE(tbl); i++)			\
+		(LINKTABLE_START(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 < LINKTABLE_SIZE(tbl); i++)		\
+		err = (LINKTABLE_START(tbl)[i]).func(args);		\
+	err;								\
+})
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_LINKER_TABLES_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 04/14] tables.h: add linker table support
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

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.

v7: ./scripts/checkpatch.pl --codespell fixes

v6:

o rename tables macro as requested by Andy Shevchenko

v5:
o Use ..tbl.* instead of .tbl.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clashes with compiler generated
  sections.
o Replace section macros with section names
o Dropped SECTION_RNG_ALL()
o Fix documentation typos
o To make this easier to read, as per Nicholas Piggin, add our own
  LINKTABLE_START(), LINKTABLE_END(). After reviewing the changes
  affected by this it seemed clearer and better then to also
  use our own specific LINKTABLE_SIZE(), LINKTABLE_EMPTY() and
  LINKTABLE_ALIGNMENT() as well.
o Clarifies SECTION_TBL_RO needs to be kept since some toolchains
  are buggy, and so we also add SECTION_TBL_RO_STR.
o We were using LINUX_SECTION_START() and LINUX_SECTION_END() in some
  places but in some other places VMLINUX_SYMBOL(name),
  VMLINUX_SYMBOL(name##__end). Since we are adding LINKTABLE_START()
  and LINKTABLE_END() just use those consistently.
o Fix DEFINE_LINKTABLE_INIT() by making it use DECLARE_LINKTABLE_RO()
  which forces const.
o Fix powerpc .text use: it does not use TEXT_TEXT so we must
  add our *(SORT(.text.tbl.*)) to its linker script manually.

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@ipxe.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst         |   1 +
 Documentation/sections/linker-tables.rst | 212 +++++++++++
 MAINTAINERS                              |  10 +
 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/powerpc/kernel/vmlinux.lds.S        |   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/tables.h             |  48 +++
 include/asm-generic/vmlinux.lds.h        |   6 +
 include/linux/tables.h                   | 612 +++++++++++++++++++++++++++++++
 39 files changed, 948 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 4a1df389fa91..7c7c1adf955c 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -16,3 +16,4 @@ common a set of Linux helpers for ELF sections are also documented.
    background
    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..780a292d2d00
--- /dev/null
+++ b/Documentation/sections/linker-tables.rst
@@ -0,0 +1,212 @@
+===================
+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_START
+---------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_START
+
+LINKTABLE_END
+-------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_END
+
+LINKTABLE_SIZE
+--------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_SIZE
+
+LINKTABLE_EMPTY
+---------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_EMPTY
+
+LINKTABLE_ADDR_WITHIN
+---------------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_ADDR_WITHIN
+
+LINKTABLE_ALIGNMENT
+-------------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_ALIGNMENT
+
+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 e0f29ccda90b..99ca436e76d9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5421,6 +5421,16 @@ 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
+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
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 a374b7f83888..ccfa69ce2608 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -53,3 +53,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 0d47f98ccbc0..b70d4b78d577 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -43,3 +43,4 @@ generated-y += mach-types.h
 generated-y += unistd-nr.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 e9939cbd9067..0c1e781ab10b 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -47,3 +47,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 3428415b1996..9115b215fc7e 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -49,3 +49,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..90a0d3df35c8
--- /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@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 weak 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 */
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 aa9739ed9f2a..f3f1e51dd5be 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -14,3 +14,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 006e2863ad37..c28bcdecc764 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -36,3 +36,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 4a8471434a3e..c836f7e2a5e7 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -57,3 +57,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 e844d6058248..db9dff9c1535 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -23,3 +23,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 f11d1249738f..aaae8a9f6099 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -30,3 +30,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 60d8349241a7..7c06627a0a0d 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -10,3 +10,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/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index fcfc9d102348..8cd940c72895 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -108,6 +108,7 @@ SECTIONS
 		/* careful! __ftr_alt_* sections need to be close to .text */
 		*(.text .fixup __ftr_alt_* .ref.text)
 		*(SORT(.text.rng.*))
+		*(SORT(.text..tbl.*))
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index c1b85a361e5d..96dd69931427 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 28280887ac79..23a2216f4146 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -23,3 +23,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 33f7069763ae..a599f6f4ee0a 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -42,3 +42,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 b952dcb3e216..d2867aa09e23 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -28,3 +28,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 93abbfdab543..6671a1f08ead 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -62,3 +62,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 f672f2fc181d..4cb511f1067c 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -14,3 +14,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 f96fa2ddf7c9..484a24c309fb 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 2b7fe48c0225..7b41f32a2ba0 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -34,3 +34,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/tables.h b/include/asm-generic/tables.h
new file mode 100644
index 000000000000..567775b292c2
--- /dev/null
+++ b/include/asm-generic/tables.h
@@ -0,0 +1,48 @@
+#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..tbl.name.level
+
+/* Some toolchains are buggy, let them override */
+#ifndef SECTION_TBL_RO
+# define SECTION_TBL_RO	.rodata
+#endif
+
+#define SECTION_TBL_RO_STR __stringify(SECTION_TBL_RO)
+
+#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, 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, 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 71bfd3b3c719..ce1e9a310ada 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)
@@ -207,6 +208,7 @@
 #define DATA_DATA							\
 	*(.data .data.[0-9a-zA-Z_]*)					\
 	*(SORT(.data..rng.*))						\
+	*(SORT(.data..tbl.*))						\
 	*(.ref.data)							\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -277,6 +279,7 @@
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
 		*(.rodata)						\
 		*(SORT(.rodata..rng.*))					\
+		*(SORT(.rodata..tbl.*))					\
 		*(.rodata.*)						\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		KEEP(*(__vermagic))	/* Kernel version magic */	\
@@ -452,6 +455,7 @@
 		ALIGN_FUNCTION();					\
 		*(.text.hot .text)					\
 		*(SORT(.text..rng.*))					\
+		*(SORT(.text..tbl.*))					\
 		*(.text.fixup .text.unlikely)				\
 		*(.ref.text)						\
 	MEM_KEEP(init.text)						\
@@ -556,6 +560,7 @@
 	KEEP(*(SORT(___kentry+*)))					\
 	*(.init.data)							\
 	*(SORT(.init.data..rng.*))					\
+	*(SORT(.init.data..tbl.*))					\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -580,6 +585,7 @@
 #define INIT_TEXT							\
 	*(.init.text)							\
 	*(SORT(.init.text..rng.*))					\
+	*(SORT(.init.text..tbl.*))					\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
new file mode 100644
index 000000000000..82da59c4266d
--- /dev/null
+++ b/include/linux/tables.h
@@ -0,0 +1,612 @@
+#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(.foo..tbl.*))
+ *
+ * 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_START - get address of start of linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the start address of the linker table.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINKTABLE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * LINKTABLE_END - get address of end of the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define LINKTABLE_END(name)	LINUX_SECTION_END(name)
+
+/**
+ * LINKTABLE_SIZE - get number of entries in the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the number of entries in the linker table.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINKTABLE_SIZE(frobnicator_fns);
+ */
+#define LINKTABLE_SIZE(name)					\
+	((LINKTABLE_END(name)) - (LINKTABLE_START(name)))
+
+/**
+ * LINKTABLE_EMPTY - check if linker table has no entries
+ *
+ * @name: name of linker table
+ *
+ * Returns true if the linker table is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(frobnicator_fns);
+ */
+#define LINKTABLE_EMPTY(name)	(LINKTABLE_SIZE(name) == 0)
+
+/**
+ * LINKTABLE_ADDR_WITHIN - returns true if address is in the linker table
+ *
+ * @name: name of the linker table
+ * @addr: address to query for
+ *
+ * Returns true if the address is part of the linker table.
+ */
+#define LINKTABLE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) LINKTABLE_START(name) &&		\
+	  addr < (unsigned long) LINKTABLE_END(name))
+
+/**
+ * LINKTABLE_ALIGNMENT - get the alignment of the linker table
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the linker table.
+ */
+#define LINKTABLE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * 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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_TEXT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE_RO(name, ~) LINKTABLE_END(name)[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_RO(type, name);				\
+	LINKTABLE_INIT_WEAK(name,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT_DATA(name, ~) LINKTABLE_END(name)[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 = LINKTABLE_START(tbl);				\
+	     pointer < LINKTABLE_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 < LINKTABLE_SIZE(tbl); i++)			\
+		(LINKTABLE_START(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 < LINKTABLE_SIZE(tbl); i++)		\
+		err = (LINKTABLE_START(tbl)[i]).func(args);		\
+	err;								\
+})
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_LINKER_TABLES_H */
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 04/14] tables.h: add linker table support
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

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.

v7: ./scripts/checkpatch.pl --codespell fixes

v6:

o rename tables macro as requested by Andy Shevchenko

v5:
o Use ..tbl.* instead of .tbl.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clashes with compiler generated
  sections.
o Replace section macros with section names
o Dropped SECTION_RNG_ALL()
o Fix documentation typos
o To make this easier to read, as per Nicholas Piggin, add our own
  LINKTABLE_START(), LINKTABLE_END(). After reviewing the changes
  affected by this it seemed clearer and better then to also
  use our own specific LINKTABLE_SIZE(), LINKTABLE_EMPTY() and
  LINKTABLE_ALIGNMENT() as well.
o Clarifies SECTION_TBL_RO needs to be kept since some toolchains
  are buggy, and so we also add SECTION_TBL_RO_STR.
o We were using LINUX_SECTION_START() and LINUX_SECTION_END() in some
  places but in some other places VMLINUX_SYMBOL(name),
  VMLINUX_SYMBOL(name##__end). Since we are adding LINKTABLE_START()
  and LINKTABLE_END() just use those consistently.
o Fix DEFINE_LINKTABLE_INIT() by making it use DECLARE_LINKTABLE_RO()
  which forces const.
o Fix powerpc .text use: it does not use TEXT_TEXT so we must
  add our *(SORT(.text.tbl.*)) to its linker script manually.

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@ipxe.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/index.rst         |   1 +
 Documentation/sections/linker-tables.rst | 212 +++++++++++
 MAINTAINERS                              |  10 +
 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/powerpc/kernel/vmlinux.lds.S        |   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/tables.h             |  48 +++
 include/asm-generic/vmlinux.lds.h        |   6 +
 include/linux/tables.h                   | 612 +++++++++++++++++++++++++++++++
 39 files changed, 948 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 4a1df389fa91..7c7c1adf955c 100644
--- a/Documentation/sections/index.rst
+++ b/Documentation/sections/index.rst
@@ -16,3 +16,4 @@ common a set of Linux helpers for ELF sections are also documented.
    background
    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..780a292d2d00
--- /dev/null
+++ b/Documentation/sections/linker-tables.rst
@@ -0,0 +1,212 @@
+===================
+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_START
+---------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_START
+
+LINKTABLE_END
+-------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_END
+
+LINKTABLE_SIZE
+--------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_SIZE
+
+LINKTABLE_EMPTY
+---------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_EMPTY
+
+LINKTABLE_ADDR_WITHIN
+---------------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_ADDR_WITHIN
+
+LINKTABLE_ALIGNMENT
+-------------------
+.. kernel-doc:: include/linux/tables.h
+   :functions: LINKTABLE_ALIGNMENT
+
+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 e0f29ccda90b..99ca436e76d9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5421,6 +5421,16 @@ 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
+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
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 a374b7f83888..ccfa69ce2608 100644
--- a/arch/arc/include/asm/Kbuild
+++ b/arch/arc/include/asm/Kbuild
@@ -53,3 +53,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 0d47f98ccbc0..b70d4b78d577 100644
--- a/arch/arm/include/asm/Kbuild
+++ b/arch/arm/include/asm/Kbuild
@@ -43,3 +43,4 @@ generated-y += mach-types.h
 generated-y += unistd-nr.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 e9939cbd9067..0c1e781ab10b 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -47,3 +47,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 3428415b1996..9115b215fc7e 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -49,3 +49,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..90a0d3df35c8
--- /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@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 weak 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 */
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 aa9739ed9f2a..f3f1e51dd5be 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -14,3 +14,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 006e2863ad37..c28bcdecc764 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -36,3 +36,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 4a8471434a3e..c836f7e2a5e7 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -57,3 +57,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 e844d6058248..db9dff9c1535 100644
--- a/arch/mips/include/asm/Kbuild
+++ b/arch/mips/include/asm/Kbuild
@@ -23,3 +23,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 f11d1249738f..aaae8a9f6099 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -30,3 +30,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 60d8349241a7..7c06627a0a0d 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -10,3 +10,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/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index fcfc9d102348..8cd940c72895 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -108,6 +108,7 @@ SECTIONS
 		/* careful! __ftr_alt_* sections need to be close to .text */
 		*(.text .fixup __ftr_alt_* .ref.text)
 		*(SORT(.text.rng.*))
+		*(SORT(.text..tbl.*))
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
diff --git a/arch/s390/include/asm/Kbuild b/arch/s390/include/asm/Kbuild
index c1b85a361e5d..96dd69931427 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 28280887ac79..23a2216f4146 100644
--- a/arch/sparc/include/asm/Kbuild
+++ b/arch/sparc/include/asm/Kbuild
@@ -23,3 +23,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 33f7069763ae..a599f6f4ee0a 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -42,3 +42,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 b952dcb3e216..d2867aa09e23 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -28,3 +28,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 93abbfdab543..6671a1f08ead 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -62,3 +62,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 f672f2fc181d..4cb511f1067c 100644
--- a/arch/x86/include/asm/Kbuild
+++ b/arch/x86/include/asm/Kbuild
@@ -14,3 +14,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 f96fa2ddf7c9..484a24c309fb 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 2b7fe48c0225..7b41f32a2ba0 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -34,3 +34,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/tables.h b/include/asm-generic/tables.h
new file mode 100644
index 000000000000..567775b292c2
--- /dev/null
+++ b/include/asm-generic/tables.h
@@ -0,0 +1,48 @@
+#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..tbl.name.level
+
+/* Some toolchains are buggy, let them override */
+#ifndef SECTION_TBL_RO
+# define SECTION_TBL_RO	.rodata
+#endif
+
+#define SECTION_TBL_RO_STR __stringify(SECTION_TBL_RO)
+
+#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, 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, 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 71bfd3b3c719..ce1e9a310ada 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)
@@ -207,6 +208,7 @@
 #define DATA_DATA							\
 	*(.data .data.[0-9a-zA-Z_]*)					\
 	*(SORT(.data..rng.*))						\
+	*(SORT(.data..tbl.*))						\
 	*(.ref.data)							\
 	*(.data..shared_aligned) /* percpu related */			\
 	MEM_KEEP(init.data)						\
@@ -277,6 +279,7 @@
 		VMLINUX_SYMBOL(__start_rodata) = .;			\
 		*(.rodata)						\
 		*(SORT(.rodata..rng.*))					\
+		*(SORT(.rodata..tbl.*))					\
 		*(.rodata.*)						\
 		RO_AFTER_INIT_DATA	/* Read only after init */	\
 		KEEP(*(__vermagic))	/* Kernel version magic */	\
@@ -452,6 +455,7 @@
 		ALIGN_FUNCTION();					\
 		*(.text.hot .text)					\
 		*(SORT(.text..rng.*))					\
+		*(SORT(.text..tbl.*))					\
 		*(.text.fixup .text.unlikely)				\
 		*(.ref.text)						\
 	MEM_KEEP(init.text)						\
@@ -556,6 +560,7 @@
 	KEEP(*(SORT(___kentry+*)))					\
 	*(.init.data)							\
 	*(SORT(.init.data..rng.*))					\
+	*(SORT(.init.data..tbl.*))					\
 	MEM_DISCARD(init.data)						\
 	KERNEL_CTORS()							\
 	MCOUNT_REC()							\
@@ -580,6 +585,7 @@
 #define INIT_TEXT							\
 	*(.init.text)							\
 	*(SORT(.init.text..rng.*))					\
+	*(SORT(.init.text..tbl.*))					\
 	*(.text.startup)						\
 	MEM_DISCARD(init.text)
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
new file mode 100644
index 000000000000..82da59c4266d
--- /dev/null
+++ b/include/linux/tables.h
@@ -0,0 +1,612 @@
+#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(.foo..tbl.*))
+ *
+ * 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_START - get address of start of linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the start address of the linker table.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINKTABLE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * LINKTABLE_END - get address of end of the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define LINKTABLE_END(name)	LINUX_SECTION_END(name)
+
+/**
+ * LINKTABLE_SIZE - get number of entries in the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the number of entries in the linker table.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINKTABLE_SIZE(frobnicator_fns);
+ */
+#define LINKTABLE_SIZE(name)					\
+	((LINKTABLE_END(name)) - (LINKTABLE_START(name)))
+
+/**
+ * LINKTABLE_EMPTY - check if linker table has no entries
+ *
+ * @name: name of linker table
+ *
+ * Returns true if the linker table is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(frobnicator_fns);
+ */
+#define LINKTABLE_EMPTY(name)	(LINKTABLE_SIZE(name) == 0)
+
+/**
+ * LINKTABLE_ADDR_WITHIN - returns true if address is in the linker table
+ *
+ * @name: name of the linker table
+ * @addr: address to query for
+ *
+ * Returns true if the address is part of the linker table.
+ */
+#define LINKTABLE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) LINKTABLE_START(name) &&		\
+	  addr < (unsigned long) LINKTABLE_END(name))
+
+/**
+ * LINKTABLE_ALIGNMENT - get the alignment of the linker table
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the linker table.
+ */
+#define LINKTABLE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * 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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_TEXT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE_RO(name, ~) LINKTABLE_END(name)[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_RO(type, name);				\
+	LINKTABLE_INIT_WEAK(name,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT_DATA(name, ~) LINKTABLE_END(name)[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 = LINKTABLE_START(tbl);				\
+	     pointer < LINKTABLE_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 < LINKTABLE_SIZE(tbl); i++)			\
+		(LINKTABLE_START(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 < LINKTABLE_SIZE(tbl); i++)		\
+		err = (LINKTABLE_START(tbl)[i]).func(args);		\
+	err;								\
+})
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_LINKER_TABLES_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 05/14] kbuild: enable option to force compile force-obj-y and force-lib-y
  2017-01-15 21:10         ` Luis R. Rodriguez
  (?)
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Linux provides a rich array of features, enabling each feature
however increases the size of the kernel and there are many
features which users often want disabled. The traditional
solution to this problem is for each feature to have its own
Kconfig symbol, followed by a series of #ifdef statements
in C code and header files, allowing the feature to be compiled
only when desirable. As the variability of Linux increases build
tests can and are often done with random kernel configurations,
allyesconfig, and allmodconfig to help find code issues. This
however doesn't catch all errors and as a consequence code that
is typically not enabled often can suffer from bit-rot over time.

An alternative approach for subsystems, which refer to as the 'build-all
link-selectively philosophy' is to keep the Kconfig symbols, replace
the #ifdef approach by having each feature implemented it its own C file,
and force compilation for all features to avoid the code bit-rot problem.
With this strategy only features that are enabled via Kconfig get
linked into the kernel, so the forced compilation has no size impact
on the kernel. The practice of having each feature implemented in its own
C file is already prevalent in many subsystems, however #ifdefs are still
typically required during feature initialization. For instance in:

  #ifdef CONFIG_FOO
  foo_init();
  #endif

We cannot remove the #ifdef and leave foo_init() as we'd either
need to always enable the feature or add a respective #ifdef in a
foo.h which makes foo_init() do nothing when CONFIG_FOO is disabled.

Linker tables enable lifting the requirement to use of #ifdefs during
initialization. With linker tables initialization sequences can instead
be aggregated into a custom ELF section at link time, during run time
the table can be iterated over and each init sequence enabled can be
called. A feature's init routine is only added to a table when its
respective Kconfig symbols has been enabled and therefore linked in.
Linker tables enable subsystems to completely do away with #ifdefs if
one is comfortable in accepting all subsystem's feature's structural
size implications.

Subsystems which want to follow the 'build-all link-selectively
philosophy' still need a way to easily express and annotate that they
wish for all code to always be compiled to help avoid code bit rot,
as such two new targets force-obj-y and force-lib-y are provided to
help with this. Its not fair to require everyone to force compilation
of all features of a subsystem though, so as a compromise, the new
targets only force compilation when CONFIG_BUILD_AVOID_BITROT is
enabled.

Only built-in features are supported at the moment. Module support
is expected to be added after a generic solution to add linker
tables to modules more easily is developed.

v4: this patch was added to this series, it was split off from the
    linker tables addition due to the confusion over the code bit
    rot alternatives that are possible with linker tables.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/kbuild/makefiles.txt       | 36 ++++++++++++++++
 Documentation/sections/linker-tables.rst | 15 +++++++
 include/linux/tables.h                   | 71 ++++++++++++++++++++++++++++++++
 init/Kconfig                             | 22 ++++++++++
 scripts/Makefile.build                   |  7 ++--
 scripts/Makefile.clean                   |  2 +
 scripts/Makefile.lib                     | 11 +++++
 7 files changed, 161 insertions(+), 3 deletions(-)

diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 9b9c4797fc55..1af275cd4879 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -1090,6 +1090,42 @@ When kbuild executes, the following steps are followed (roughly):
 	In this example, extra-y is used to list object files that
 	shall be built, but shall not be linked as part of built-in.o.
 
+    force-obj-y force-lib-y
+
+	When CONFIG_BUILD_AVOID_BITROT is enabled using these targets for your
+	kconfig symbols forces compilation of the associated objects if the
+	kconfig's symbol's dependencies are met, the objects however are only
+	linked into to the kernel if and only if the kconfig symbol was
+	enabled. If CONFIG_BUILD_AVOID_BITROT is disabled the force-obj-y and
+	force-lib-y targets are functionally equilvalent to obj-y and lib-y
+	respectively.
+
+	Using force-obj-y and force-lib-y are part of a code architecture and
+	build philosophy further enabled by linker tables, for more details
+	refer to the documention in include/linux/tables.h, refer to the
+	sections:
+
+		o The code bit-rot problem
+		o The build-all selective-link philosophy
+		o Avoiding the code bit-rot problem with linker tables
+		o Linker table module support
+
+	Modules support is expected to be enhanced in the future, so for now
+	only built-in features are supported.
+
+	Example use:
+
+		force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	An alternative to using force-obj-y, is to use extra-y followed by the
+	respective obj-y:
+
+		extra-y += foo.o
+		obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	Using force-obj-y and force-lib-y can be used to help annotate the
+	targets follow the 'build-all selective-link philosophy' further
+	enabled by linker tables.
 
 --- 6.7 Commands useful for building a boot image
 
diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index 780a292d2d00..bc2d9f46cde6 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -30,6 +30,21 @@ How linker tables simplify initialization code
 .. kernel-doc:: include/linux/tables.h
    :doc: How linker tables simplify initialization code
 
+The code bit-rot problem
+------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The code bit-rot problem
+
+The build-all selective-link philosophy
+---------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The build-all selective-link philosophy
+
+Avoiding the code bit-rot problem with linker tables
+----------------------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: Avoiding the code bit-rot problem with linker tables
+
 Using linker tables in Linux
 ==============
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
index 82da59c4266d..f295fbe74734 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -169,6 +169,77 @@
  */
 
 /**
+ * DOC: The code bit-rot problem
+ *
+ * Linux provides a rich array of features, enabling each feature
+ * however increases the size of the kernel and there are many
+ * features which users often want disabled. The traditional
+ * solution to this problem is for each feature to have its own
+ * Kconfig symbol, followed by a series of #ifdef statements
+ * in C code and header files, allowing the feature to be compiled
+ * only when desirable. As the variability of Linux increases build
+ * tests can and are often done with random kernel configurations,
+ * allyesconfig, and allmodconfig to help find code issues. This
+ * however doesn't catch all errors and as a consequence code that
+ * is typically not enabled often can suffer from bit-rot over time.
+ */
+
+/**
+ * DOC: The build-all selective-link philosophy
+ *
+ * A code architecture philosophy to help avoid code bit-rot consists
+ * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
+ * by instead having each feature implemented it its own C file, and force
+ * compilation for all features. Only features that are enabled get linked in,
+ * the forced compilation therefore has no size impact on the final result of
+ * the kernel. The practice of having each feature implemented in its own C
+ * file is already prevalent in many subsystems, however #ifdefs are still
+ * typically required during feature initialization. For instance in::
+ *
+ *	#ifdef CONFIG_FOO
+ *	foo_init();
+ *	#endif
+ *
+ * We cannot remove the #ifdef and leave foo_init() as we'd either
+ * need to always enable the feature or add a respective #ifdef in a
+ * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem with linker tables
+ *
+ * Linker tables can be used to further help avoid the code bit-rot problem
+ * when embracing the 'build-all selective-link philosophy' by lifting the
+ * requirement to use of #ifdefs during initialization. With linker tables
+ * initialization sequences can be aggregated into a custom ELF section at
+ * link time, during run time the table can be iterated over and each init
+ * sequence enabled can be called. A feature's init routine is only added to a
+ * table when its respective Kconfig symbols has been enabled and therefore
+ * linked in. Linker tables enable subsystems to completely do away with
+ * #ifdefs if one is comfortable in accepting all subsystem's feature's
+ * structural size implications.
+ *
+ * To further help with this the Linux build system supports two special
+ * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
+ * follow the 'build-all selective-link philosophy' can use these targets for a
+ * feature's kconfig symbol. Using these targets will always require
+ * compilation of the kconfig's objects if the kconfig symbol's dependencies
+ * are met but only link the objects into the kernel, and therefore enable the
+ * feature, if and only if the kconfig symbol has been enabled.
+ *
+ * Not all users or build systems may want to opt-in to compile all objects
+ * following the 'build-all selective-link philosophy', as such the targets
+ * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
+ * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
+ * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
+ * ``obj-y`` and ``lib-y`` respectively.
+ *
+ * Example use::
+ *
+ *	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+ */
+
+/**
  * DOC: Linker table module support
  *
  * Modules can use linker tables, however the linker table definition
diff --git a/init/Kconfig b/init/Kconfig
index 536c2a00d972..6272f4fdcc86 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -63,6 +63,28 @@ config CROSS_COMPILE
 	  need to set this unless you want the configured kernel build
 	  directory to select the cross-compiler automatically.
 
+config BUILD_AVOID_BITROT
+	bool "Enable force building of force-obj-y and force-lib-y"
+	default n
+	help
+	  When enabled objects under the force-obj-y and force-lib-y targets
+	  using a Kconfig symbol will be forced to compile if the Kconfig
+	  symbol's dependencies are met but only linked into the kernel if
+	  the Kconfig symbol is enabled. If a Kconfig symbol on a force-obj-y
+	  or force-lib-y target is disabled, it will be compiled but not linked
+	  into the kernel.
+
+	  The force-obj-y and force-lib-y targets can be used by subsystems
+	  which wish to want to follow the 'build-all selective-link philosophy'
+	  documented under include/linux/tables.h.
+
+	  Say Y if you have a decent build machine and would like to help test
+	  building code for more subsystems. Say N if you do you not have a
+	  good build machine or only want to compile what you've enabled for
+	  your kernel.
+
+	  Enabling this option never increases the size of your kernel.
+
 config COMPILE_TEST
 	bool "Compile also drivers which will not load"
 	depends on !UML
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index eadcd4d359d9..c34af839d47c 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -92,7 +92,8 @@ modorder-target := $(obj)/modules.order
 
 # We keep a list of all modules in $(MODVERDIR)
 
-__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
+__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y) \
+				$(force-obj-y)) \
 	 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
 	 $(subdir-ym) $(always)
 	@:
@@ -392,8 +393,8 @@ endif
 $(obj)/%.o: $(src)/%.S $(objtool_obj) FORCE
 	$(call if_changed_rule,as_o_S)
 
-targets += $(real-objs-y) $(real-objs-m) $(lib-y)
-targets += $(extra-y) $(MAKECMDGOALS) $(always)
+targets += $(real-objs-y) $(real-objs-m) $(lib-y) $(force-lib-y)
+targets += $(extra-y) $(force-obj-y) $(MAKECMDGOALS) $(always)
 
 # Linker scripts preprocessor (.lds.S -> .lds)
 # ---------------------------------------------------------------------------
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-) \
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 0a07f9014944..d1cb0cfdf1bf 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -12,6 +12,15 @@ export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y)
 # Figure out what we need to build from the various variables
 # ===================================== 
+ifeq ($(CONFIG_BUILD_AVOID_BITROT),y)
+extra-y += $(force-obj-) $(force-lib-)
+endif
+
+obj-m += $(force-obj-m)
+obj-y += $(force-obj-y)
+lib-m += $(force-lib-m)
+lib-y += $(force-lib-y)
+
 # When an object is listed to be built compiled-in and modular,
 # only build the compiled-in version
 
@@ -72,6 +81,8 @@ real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)
 # Add subdir path
 
 extra-y		:= $(addprefix $(obj)/,$(extra-y))
+force-obj-y		:= $(addprefix $(obj)/,$(force-obj-y))
+force-obj-m		:= $(addprefix $(obj)/,$(force-obj-m))
 always		:= $(addprefix $(obj)/,$(always))
 targets		:= $(addprefix $(obj)/,$(targets))
 modorder	:= $(addprefix $(obj)/,$(modorder))
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 05/14] kbuild: enable option to force compile force-obj-y and force-lib-y
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Linux provides a rich array of features, enabling each feature
however increases the size of the kernel and there are many
features which users often want disabled. The traditional
solution to this problem is for each feature to have its own
Kconfig symbol, followed by a series of #ifdef statements
in C code and header files, allowing the feature to be compiled
only when desirable. As the variability of Linux increases build
tests can and are often done with random kernel configurations,
allyesconfig, and allmodconfig to help find code issues. This
however doesn't catch all errors and as a consequence code that
is typically not enabled often can suffer from bit-rot over time.

An alternative approach for subsystems, which refer to as the 'build-all
link-selectively philosophy' is to keep the Kconfig symbols, replace
the #ifdef approach by having each feature implemented it its own C file,
and force compilation for all features to avoid the code bit-rot problem.
With this strategy only features that are enabled via Kconfig get
linked into the kernel, so the forced compilation has no size impact
on the kernel. The practice of having each feature implemented in its own
C file is already prevalent in many subsystems, however #ifdefs are still
typically required during feature initialization. For instance in:

  #ifdef CONFIG_FOO
  foo_init();
  #endif

We cannot remove the #ifdef and leave foo_init() as we'd either
need to always enable the feature or add a respective #ifdef in a
foo.h which makes foo_init() do nothing when CONFIG_FOO is disabled.

Linker tables enable lifting the requirement to use of #ifdefs during
initialization. With linker tables initialization sequences can instead
be aggregated into a custom ELF section at link time, during run time
the table can be iterated over and each init sequence enabled can be
called. A feature's init routine is only added to a table when its
respective Kconfig symbols has been enabled and therefore linked in.
Linker tables enable subsystems to completely do away with #ifdefs if
one is comfortable in accepting all subsystem's feature's structural
size implications.

Subsystems which want to follow the 'build-all link-selectively
philosophy' still need a way to easily express and annotate that they
wish for all code to always be compiled to help avoid code bit rot,
as such two new targets force-obj-y and force-lib-y are provided to
help with this. Its not fair to require everyone to force compilation
of all features of a subsystem though, so as a compromise, the new
targets only force compilation when CONFIG_BUILD_AVOID_BITROT is
enabled.

Only built-in features are supported at the moment. Module support
is expected to be added after a generic solution to add linker
tables to modules more easily is developed.

v4: this patch was added to this series, it was split off from the
    linker tables addition due to the confusion over the code bit
    rot alternatives that are possible with linker tables.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/kbuild/makefiles.txt       | 36 ++++++++++++++++
 Documentation/sections/linker-tables.rst | 15 +++++++
 include/linux/tables.h                   | 71 ++++++++++++++++++++++++++++++++
 init/Kconfig                             | 22 ++++++++++
 scripts/Makefile.build                   |  7 ++--
 scripts/Makefile.clean                   |  2 +
 scripts/Makefile.lib                     | 11 +++++
 7 files changed, 161 insertions(+), 3 deletions(-)

diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 9b9c4797fc55..1af275cd4879 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -1090,6 +1090,42 @@ When kbuild executes, the following steps are followed (roughly):
 	In this example, extra-y is used to list object files that
 	shall be built, but shall not be linked as part of built-in.o.
 
+    force-obj-y force-lib-y
+
+	When CONFIG_BUILD_AVOID_BITROT is enabled using these targets for your
+	kconfig symbols forces compilation of the associated objects if the
+	kconfig's symbol's dependencies are met, the objects however are only
+	linked into to the kernel if and only if the kconfig symbol was
+	enabled. If CONFIG_BUILD_AVOID_BITROT is disabled the force-obj-y and
+	force-lib-y targets are functionally equilvalent to obj-y and lib-y
+	respectively.
+
+	Using force-obj-y and force-lib-y are part of a code architecture and
+	build philosophy further enabled by linker tables, for more details
+	refer to the documention in include/linux/tables.h, refer to the
+	sections:
+
+		o The code bit-rot problem
+		o The build-all selective-link philosophy
+		o Avoiding the code bit-rot problem with linker tables
+		o Linker table module support
+
+	Modules support is expected to be enhanced in the future, so for now
+	only built-in features are supported.
+
+	Example use:
+
+		force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	An alternative to using force-obj-y, is to use extra-y followed by the
+	respective obj-y:
+
+		extra-y += foo.o
+		obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	Using force-obj-y and force-lib-y can be used to help annotate the
+	targets follow the 'build-all selective-link philosophy' further
+	enabled by linker tables.
 
 --- 6.7 Commands useful for building a boot image
 
diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index 780a292d2d00..bc2d9f46cde6 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -30,6 +30,21 @@ How linker tables simplify initialization code
 .. kernel-doc:: include/linux/tables.h
    :doc: How linker tables simplify initialization code
 
+The code bit-rot problem
+------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The code bit-rot problem
+
+The build-all selective-link philosophy
+---------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The build-all selective-link philosophy
+
+Avoiding the code bit-rot problem with linker tables
+----------------------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: Avoiding the code bit-rot problem with linker tables
+
 Using linker tables in Linux
 ============================
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
index 82da59c4266d..f295fbe74734 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -169,6 +169,77 @@
  */
 
 /**
+ * DOC: The code bit-rot problem
+ *
+ * Linux provides a rich array of features, enabling each feature
+ * however increases the size of the kernel and there are many
+ * features which users often want disabled. The traditional
+ * solution to this problem is for each feature to have its own
+ * Kconfig symbol, followed by a series of #ifdef statements
+ * in C code and header files, allowing the feature to be compiled
+ * only when desirable. As the variability of Linux increases build
+ * tests can and are often done with random kernel configurations,
+ * allyesconfig, and allmodconfig to help find code issues. This
+ * however doesn't catch all errors and as a consequence code that
+ * is typically not enabled often can suffer from bit-rot over time.
+ */
+
+/**
+ * DOC: The build-all selective-link philosophy
+ *
+ * A code architecture philosophy to help avoid code bit-rot consists
+ * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
+ * by instead having each feature implemented it its own C file, and force
+ * compilation for all features. Only features that are enabled get linked in,
+ * the forced compilation therefore has no size impact on the final result of
+ * the kernel. The practice of having each feature implemented in its own C
+ * file is already prevalent in many subsystems, however #ifdefs are still
+ * typically required during feature initialization. For instance in::
+ *
+ *	#ifdef CONFIG_FOO
+ *	foo_init();
+ *	#endif
+ *
+ * We cannot remove the #ifdef and leave foo_init() as we'd either
+ * need to always enable the feature or add a respective #ifdef in a
+ * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem with linker tables
+ *
+ * Linker tables can be used to further help avoid the code bit-rot problem
+ * when embracing the 'build-all selective-link philosophy' by lifting the
+ * requirement to use of #ifdefs during initialization. With linker tables
+ * initialization sequences can be aggregated into a custom ELF section at
+ * link time, during run time the table can be iterated over and each init
+ * sequence enabled can be called. A feature's init routine is only added to a
+ * table when its respective Kconfig symbols has been enabled and therefore
+ * linked in. Linker tables enable subsystems to completely do away with
+ * #ifdefs if one is comfortable in accepting all subsystem's feature's
+ * structural size implications.
+ *
+ * To further help with this the Linux build system supports two special
+ * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
+ * follow the 'build-all selective-link philosophy' can use these targets for a
+ * feature's kconfig symbol. Using these targets will always require
+ * compilation of the kconfig's objects if the kconfig symbol's dependencies
+ * are met but only link the objects into the kernel, and therefore enable the
+ * feature, if and only if the kconfig symbol has been enabled.
+ *
+ * Not all users or build systems may want to opt-in to compile all objects
+ * following the 'build-all selective-link philosophy', as such the targets
+ * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
+ * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
+ * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
+ * ``obj-y`` and ``lib-y`` respectively.
+ *
+ * Example use::
+ *
+ *	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+ */
+
+/**
  * DOC: Linker table module support
  *
  * Modules can use linker tables, however the linker table definition
diff --git a/init/Kconfig b/init/Kconfig
index 536c2a00d972..6272f4fdcc86 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -63,6 +63,28 @@ config CROSS_COMPILE
 	  need to set this unless you want the configured kernel build
 	  directory to select the cross-compiler automatically.
 
+config BUILD_AVOID_BITROT
+	bool "Enable force building of force-obj-y and force-lib-y"
+	default n
+	help
+	  When enabled objects under the force-obj-y and force-lib-y targets
+	  using a Kconfig symbol will be forced to compile if the Kconfig
+	  symbol's dependencies are met but only linked into the kernel if
+	  the Kconfig symbol is enabled. If a Kconfig symbol on a force-obj-y
+	  or force-lib-y target is disabled, it will be compiled but not linked
+	  into the kernel.
+
+	  The force-obj-y and force-lib-y targets can be used by subsystems
+	  which wish to want to follow the 'build-all selective-link philosophy'
+	  documented under include/linux/tables.h.
+
+	  Say Y if you have a decent build machine and would like to help test
+	  building code for more subsystems. Say N if you do you not have a
+	  good build machine or only want to compile what you've enabled for
+	  your kernel.
+
+	  Enabling this option never increases the size of your kernel.
+
 config COMPILE_TEST
 	bool "Compile also drivers which will not load"
 	depends on !UML
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index eadcd4d359d9..c34af839d47c 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -92,7 +92,8 @@ modorder-target := $(obj)/modules.order
 
 # We keep a list of all modules in $(MODVERDIR)
 
-__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
+__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y) \
+				$(force-obj-y)) \
 	 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
 	 $(subdir-ym) $(always)
 	@:
@@ -392,8 +393,8 @@ endif
 $(obj)/%.o: $(src)/%.S $(objtool_obj) FORCE
 	$(call if_changed_rule,as_o_S)
 
-targets += $(real-objs-y) $(real-objs-m) $(lib-y)
-targets += $(extra-y) $(MAKECMDGOALS) $(always)
+targets += $(real-objs-y) $(real-objs-m) $(lib-y) $(force-lib-y)
+targets += $(extra-y) $(force-obj-y) $(MAKECMDGOALS) $(always)
 
 # Linker scripts preprocessor (.lds.S -> .lds)
 # ---------------------------------------------------------------------------
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-) \
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 0a07f9014944..d1cb0cfdf1bf 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -12,6 +12,15 @@ export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y)
 # Figure out what we need to build from the various variables
 # ===========================================================================
 
+ifeq ($(CONFIG_BUILD_AVOID_BITROT),y)
+extra-y += $(force-obj-) $(force-lib-)
+endif
+
+obj-m += $(force-obj-m)
+obj-y += $(force-obj-y)
+lib-m += $(force-lib-m)
+lib-y += $(force-lib-y)
+
 # When an object is listed to be built compiled-in and modular,
 # only build the compiled-in version
 
@@ -72,6 +81,8 @@ real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)
 # Add subdir path
 
 extra-y		:= $(addprefix $(obj)/,$(extra-y))
+force-obj-y		:= $(addprefix $(obj)/,$(force-obj-y))
+force-obj-m		:= $(addprefix $(obj)/,$(force-obj-m))
 always		:= $(addprefix $(obj)/,$(always))
 targets		:= $(addprefix $(obj)/,$(targets))
 modorder	:= $(addprefix $(obj)/,$(modorder))
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 05/14] kbuild: enable option to force compile force-obj-y and force-lib-y
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

Linux provides a rich array of features, enabling each feature
however increases the size of the kernel and there are many
features which users often want disabled. The traditional
solution to this problem is for each feature to have its own
Kconfig symbol, followed by a series of #ifdef statements
in C code and header files, allowing the feature to be compiled
only when desirable. As the variability of Linux increases build
tests can and are often done with random kernel configurations,
allyesconfig, and allmodconfig to help find code issues. This
however doesn't catch all errors and as a consequence code that
is typically not enabled often can suffer from bit-rot over time.

An alternative approach for subsystems, which refer to as the 'build-all
link-selectively philosophy' is to keep the Kconfig symbols, replace
the #ifdef approach by having each feature implemented it its own C file,
and force compilation for all features to avoid the code bit-rot problem.
With this strategy only features that are enabled via Kconfig get
linked into the kernel, so the forced compilation has no size impact
on the kernel. The practice of having each feature implemented in its own
C file is already prevalent in many subsystems, however #ifdefs are still
typically required during feature initialization. For instance in:

  #ifdef CONFIG_FOO
  foo_init();
  #endif

We cannot remove the #ifdef and leave foo_init() as we'd either
need to always enable the feature or add a respective #ifdef in a
foo.h which makes foo_init() do nothing when CONFIG_FOO is disabled.

Linker tables enable lifting the requirement to use of #ifdefs during
initialization. With linker tables initialization sequences can instead
be aggregated into a custom ELF section at link time, during run time
the table can be iterated over and each init sequence enabled can be
called. A feature's init routine is only added to a table when its
respective Kconfig symbols has been enabled and therefore linked in.
Linker tables enable subsystems to completely do away with #ifdefs if
one is comfortable in accepting all subsystem's feature's structural
size implications.

Subsystems which want to follow the 'build-all link-selectively
philosophy' still need a way to easily express and annotate that they
wish for all code to always be compiled to help avoid code bit rot,
as such two new targets force-obj-y and force-lib-y are provided to
help with this. Its not fair to require everyone to force compilation
of all features of a subsystem though, so as a compromise, the new
targets only force compilation when CONFIG_BUILD_AVOID_BITROT is
enabled.

Only built-in features are supported at the moment. Module support
is expected to be added after a generic solution to add linker
tables to modules more easily is developed.

v4: this patch was added to this series, it was split off from the
    linker tables addition due to the confusion over the code bit
    rot alternatives that are possible with linker tables.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/kbuild/makefiles.txt       | 36 ++++++++++++++++
 Documentation/sections/linker-tables.rst | 15 +++++++
 include/linux/tables.h                   | 71 ++++++++++++++++++++++++++++++++
 init/Kconfig                             | 22 ++++++++++
 scripts/Makefile.build                   |  7 ++--
 scripts/Makefile.clean                   |  2 +
 scripts/Makefile.lib                     | 11 +++++
 7 files changed, 161 insertions(+), 3 deletions(-)

diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 9b9c4797fc55..1af275cd4879 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -1090,6 +1090,42 @@ When kbuild executes, the following steps are followed (roughly):
 	In this example, extra-y is used to list object files that
 	shall be built, but shall not be linked as part of built-in.o.
 
+    force-obj-y force-lib-y
+
+	When CONFIG_BUILD_AVOID_BITROT is enabled using these targets for your
+	kconfig symbols forces compilation of the associated objects if the
+	kconfig's symbol's dependencies are met, the objects however are only
+	linked into to the kernel if and only if the kconfig symbol was
+	enabled. If CONFIG_BUILD_AVOID_BITROT is disabled the force-obj-y and
+	force-lib-y targets are functionally equilvalent to obj-y and lib-y
+	respectively.
+
+	Using force-obj-y and force-lib-y are part of a code architecture and
+	build philosophy further enabled by linker tables, for more details
+	refer to the documention in include/linux/tables.h, refer to the
+	sections:
+
+		o The code bit-rot problem
+		o The build-all selective-link philosophy
+		o Avoiding the code bit-rot problem with linker tables
+		o Linker table module support
+
+	Modules support is expected to be enhanced in the future, so for now
+	only built-in features are supported.
+
+	Example use:
+
+		force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	An alternative to using force-obj-y, is to use extra-y followed by the
+	respective obj-y:
+
+		extra-y += foo.o
+		obj-$(CONFIG_FEATURE_FOO) += foo.o
+
+	Using force-obj-y and force-lib-y can be used to help annotate the
+	targets follow the 'build-all selective-link philosophy' further
+	enabled by linker tables.
 
 --- 6.7 Commands useful for building a boot image
 
diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index 780a292d2d00..bc2d9f46cde6 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -30,6 +30,21 @@ How linker tables simplify initialization code
 .. kernel-doc:: include/linux/tables.h
    :doc: How linker tables simplify initialization code
 
+The code bit-rot problem
+------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The code bit-rot problem
+
+The build-all selective-link philosophy
+---------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: The build-all selective-link philosophy
+
+Avoiding the code bit-rot problem with linker tables
+----------------------------------------------------
+.. kernel-doc:: include/linux/tables.h
+   :doc: Avoiding the code bit-rot problem with linker tables
+
 Using linker tables in Linux
 ============================
 
diff --git a/include/linux/tables.h b/include/linux/tables.h
index 82da59c4266d..f295fbe74734 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -169,6 +169,77 @@
  */
 
 /**
+ * DOC: The code bit-rot problem
+ *
+ * Linux provides a rich array of features, enabling each feature
+ * however increases the size of the kernel and there are many
+ * features which users often want disabled. The traditional
+ * solution to this problem is for each feature to have its own
+ * Kconfig symbol, followed by a series of #ifdef statements
+ * in C code and header files, allowing the feature to be compiled
+ * only when desirable. As the variability of Linux increases build
+ * tests can and are often done with random kernel configurations,
+ * allyesconfig, and allmodconfig to help find code issues. This
+ * however doesn't catch all errors and as a consequence code that
+ * is typically not enabled often can suffer from bit-rot over time.
+ */
+
+/**
+ * DOC: The build-all selective-link philosophy
+ *
+ * A code architecture philosophy to help avoid code bit-rot consists
+ * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
+ * by instead having each feature implemented it its own C file, and force
+ * compilation for all features. Only features that are enabled get linked in,
+ * the forced compilation therefore has no size impact on the final result of
+ * the kernel. The practice of having each feature implemented in its own C
+ * file is already prevalent in many subsystems, however #ifdefs are still
+ * typically required during feature initialization. For instance in::
+ *
+ *	#ifdef CONFIG_FOO
+ *	foo_init();
+ *	#endif
+ *
+ * We cannot remove the #ifdef and leave foo_init() as we'd either
+ * need to always enable the feature or add a respective #ifdef in a
+ * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem with linker tables
+ *
+ * Linker tables can be used to further help avoid the code bit-rot problem
+ * when embracing the 'build-all selective-link philosophy' by lifting the
+ * requirement to use of #ifdefs during initialization. With linker tables
+ * initialization sequences can be aggregated into a custom ELF section at
+ * link time, during run time the table can be iterated over and each init
+ * sequence enabled can be called. A feature's init routine is only added to a
+ * table when its respective Kconfig symbols has been enabled and therefore
+ * linked in. Linker tables enable subsystems to completely do away with
+ * #ifdefs if one is comfortable in accepting all subsystem's feature's
+ * structural size implications.
+ *
+ * To further help with this the Linux build system supports two special
+ * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
+ * follow the 'build-all selective-link philosophy' can use these targets for a
+ * feature's kconfig symbol. Using these targets will always require
+ * compilation of the kconfig's objects if the kconfig symbol's dependencies
+ * are met but only link the objects into the kernel, and therefore enable the
+ * feature, if and only if the kconfig symbol has been enabled.
+ *
+ * Not all users or build systems may want to opt-in to compile all objects
+ * following the 'build-all selective-link philosophy', as such the targets
+ * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
+ * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
+ * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
+ * ``obj-y`` and ``lib-y`` respectively.
+ *
+ * Example use::
+ *
+ *	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+ */
+
+/**
  * DOC: Linker table module support
  *
  * Modules can use linker tables, however the linker table definition
diff --git a/init/Kconfig b/init/Kconfig
index 536c2a00d972..6272f4fdcc86 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -63,6 +63,28 @@ config CROSS_COMPILE
 	  need to set this unless you want the configured kernel build
 	  directory to select the cross-compiler automatically.
 
+config BUILD_AVOID_BITROT
+	bool "Enable force building of force-obj-y and force-lib-y"
+	default n
+	help
+	  When enabled objects under the force-obj-y and force-lib-y targets
+	  using a Kconfig symbol will be forced to compile if the Kconfig
+	  symbol's dependencies are met but only linked into the kernel if
+	  the Kconfig symbol is enabled. If a Kconfig symbol on a force-obj-y
+	  or force-lib-y target is disabled, it will be compiled but not linked
+	  into the kernel.
+
+	  The force-obj-y and force-lib-y targets can be used by subsystems
+	  which wish to want to follow the 'build-all selective-link philosophy'
+	  documented under include/linux/tables.h.
+
+	  Say Y if you have a decent build machine and would like to help test
+	  building code for more subsystems. Say N if you do you not have a
+	  good build machine or only want to compile what you've enabled for
+	  your kernel.
+
+	  Enabling this option never increases the size of your kernel.
+
 config COMPILE_TEST
 	bool "Compile also drivers which will not load"
 	depends on !UML
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index eadcd4d359d9..c34af839d47c 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -92,7 +92,8 @@ modorder-target := $(obj)/modules.order
 
 # We keep a list of all modules in $(MODVERDIR)
 
-__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
+__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y) \
+				$(force-obj-y)) \
 	 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
 	 $(subdir-ym) $(always)
 	@:
@@ -392,8 +393,8 @@ endif
 $(obj)/%.o: $(src)/%.S $(objtool_obj) FORCE
 	$(call if_changed_rule,as_o_S)
 
-targets += $(real-objs-y) $(real-objs-m) $(lib-y)
-targets += $(extra-y) $(MAKECMDGOALS) $(always)
+targets += $(real-objs-y) $(real-objs-m) $(lib-y) $(force-lib-y)
+targets += $(extra-y) $(force-obj-y) $(MAKECMDGOALS) $(always)
 
 # Linker scripts preprocessor (.lds.S -> .lds)
 # ---------------------------------------------------------------------------
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-) \
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 0a07f9014944..d1cb0cfdf1bf 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -12,6 +12,15 @@ export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y)
 # Figure out what we need to build from the various variables
 # ===========================================================================
 
+ifeq ($(CONFIG_BUILD_AVOID_BITROT),y)
+extra-y += $(force-obj-) $(force-lib-)
+endif
+
+obj-m += $(force-obj-m)
+obj-y += $(force-obj-y)
+lib-m += $(force-lib-m)
+lib-y += $(force-lib-y)
+
 # When an object is listed to be built compiled-in and modular,
 # only build the compiled-in version
 
@@ -72,6 +81,8 @@ real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)
 # Add subdir path
 
 extra-y		:= $(addprefix $(obj)/,$(extra-y))
+force-obj-y		:= $(addprefix $(obj)/,$(force-obj-y))
+force-obj-m		:= $(addprefix $(obj)/,$(force-obj-m))
 always		:= $(addprefix $(obj)/,$(always))
 targets		:= $(addprefix $(obj)/,$(targets))
 modorder	:= $(addprefix $(obj)/,$(modorder))
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 06/14] firmware/Makefile: force recompilation if makefile changes
  2017-01-15 21:10         ` Luis R. Rodriguez
  (?)
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

If you modify the target asm we currently do not force the
recompilation of the firmware files. The target asm is in
the firmware/Makefile, peg this file as a dependency to
require re-compilation of firmware targets when the asm
changes.

v3: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 firmware/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/firmware/Makefile b/firmware/Makefile
index e297e1b52636..fa3e81c2a97b 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -176,7 +176,8 @@ quiet_cmd_fwbin = MK_FW   $@
 wordsize_deps := $(wildcard include/config/64bit.h include/config/32bit.h \
 		include/config/ppc32.h include/config/ppc64.h \
 		include/config/superh32.h include/config/superh64.h \
-		include/config/x86_32.h include/config/x86_64.h)
+		include/config/x86_32.h include/config/x86_64.h \
+		firmware/Makefile)
 
 $(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)): %: $(wordsize_deps)
 	$(call cmd,fwbin,$(patsubst %.gen.S,%,$@))
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 06/14] firmware/Makefile: force recompilation if makefile changes
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

If you modify the target asm we currently do not force the
recompilation of the firmware files. The target asm is in
the firmware/Makefile, peg this file as a dependency to
require re-compilation of firmware targets when the asm
changes.

v3: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 firmware/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/firmware/Makefile b/firmware/Makefile
index e297e1b52636..fa3e81c2a97b 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -176,7 +176,8 @@ quiet_cmd_fwbin = MK_FW   $@
 wordsize_deps := $(wildcard include/config/64bit.h include/config/32bit.h \
 		include/config/ppc32.h include/config/ppc64.h \
 		include/config/superh32.h include/config/superh64.h \
-		include/config/x86_32.h include/config/x86_64.h)
+		include/config/x86_32.h include/config/x86_64.h \
+		firmware/Makefile)
 
 $(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)): %: $(wordsize_deps)
 	$(call cmd,fwbin,$(patsubst %.gen.S,%,$@))
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 06/14] firmware/Makefile: force recompilation if makefile changes
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

If you modify the target asm we currently do not force the
recompilation of the firmware files. The target asm is in
the firmware/Makefile, peg this file as a dependency to
require re-compilation of firmware targets when the asm
changes.

v3: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 firmware/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/firmware/Makefile b/firmware/Makefile
index e297e1b52636..fa3e81c2a97b 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -176,7 +176,8 @@ quiet_cmd_fwbin = MK_FW   $@
 wordsize_deps := $(wildcard include/config/64bit.h include/config/32bit.h \
 		include/config/ppc32.h include/config/ppc64.h \
 		include/config/superh32.h include/config/superh64.h \
-		include/config/x86_32.h include/config/x86_64.h)
+		include/config/x86_32.h include/config/x86_64.h \
+		firmware/Makefile)
 
 $(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)): %: $(wordsize_deps)
 	$(call cmd,fwbin,$(patsubst %.gen.S,%,$@))
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 07/14] firmware: port built-in section to linker table
  2017-01-15 21:10         ` Luis R. Rodriguez
  (?)
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This ports built-in firmware to use linker tables,
this replaces the custom section solution with a
generic solution.

This also demos the use of the .rodata linker table.

Tested with 0 built-in firmware, 1 and 2 built-in
firmwares successfully.

v6: rename table macro as suggested by Andy Shevchenko

v5:

o since we dropped SECTION_ORDER_ANY, use 'any' order level explicitly

v4:

o work around c6x toolchain bug by using SECTION_TBL_RO

o fix compilation on blackfin

v3:
o explicitly include tables.h as we no longer include
  tables.h from sections.h

o use new section_tbl_asmtype() helper on firmware/Makefile
  to enable having to unfold things on our own.

v2: introduced this file in this version of the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/x86/kernel/cpu/microcode/core.c |  8 ++++----
 drivers/base/firmware_class.c        | 12 ++++++------
 firmware/Makefile                    |  3 ++-
 include/asm-generic/vmlinux.lds.h    |  7 -------
 4 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 2af69d27da62..2c5004343b45 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -31,6 +31,7 @@
 #include <linux/cpu.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/tables.h>
 
 #include <asm/microcode_intel.h>
 #include <asm/cpu_device_id.h>
@@ -110,15 +111,14 @@ static bool __init check_loader_disabled_bsp(void)
 	return *res;
 }
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DECLARE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 bool get_builtin_firmware(struct cpio_data *cd, const char *name)
 {
 #ifdef CONFIG_FW_LOADER
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	linktable_for_each(b_fw, builtin_fw) {
 		if (!strcmp(name, b_fw->name)) {
 			cd->size = b_fw->size;
 			cd->data = b_fw->data;
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 4497d263209f..b9ac348e8d33 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -31,6 +31,7 @@
 #include <linux/reboot.h>
 #include <linux/security.h>
 #include <linux/swait.h>
+#include <linux/tables.h>
 
 #include <generated/utsrelease.h>
 
@@ -44,15 +45,14 @@ MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_FW_LOADER
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DEFINE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 				    void *buf, size_t size)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	linktable_for_each(b_fw, builtin_fw) {
 		if (strcmp(name, b_fw->name) = 0) {
 			fw->size = b_fw->size;
 			fw->data = b_fw->data;
@@ -68,9 +68,9 @@ static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 
 static bool fw_is_builtin_firmware(const struct firmware *fw)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++)
+	linktable_for_each(b_fw, builtin_fw)
 		if (fw->data = b_fw->data)
 			return true;
 
diff --git a/firmware/Makefile b/firmware/Makefile
index fa3e81c2a97b..9c8cae144ede 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -155,6 +155,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  ASM_ALIGN=$(if $(CONFIG_64BIT),3,2);			     \
 		  PROGBITS=$(if $(CONFIG_ARM),%,@)progbits;		     \
 		  echo "/* Generated by firmware/Makefile */"		> $@;\
+		  echo "\#include <asm/tables.h>"			>>$@;\
 		  echo "    .section .rodata"				>>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_bin:"				>>$@;\
@@ -164,7 +165,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_name:"				>>$@;\
 		  echo "    .string \"$$FWNAME\""			>>$@;\
-		  echo "    .section .builtin_fw,\"a\",$${PROGBITS}"	>>$@;\
+		  echo "    set_section_tbl_type(SECTION_TBL_RO, builtin_fw, any, a,$${PROGBITS})" >>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_name"		>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_bin"		>>$@;\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index ce1e9a310ada..8a5325d75932 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -324,13 +324,6 @@
 		VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .;	\
 	}								\
 									\
-	/* Built-in firmware blobs */					\
-	.builtin_fw        : AT(ADDR(.builtin_fw) - LOAD_OFFSET) {	\
-		VMLINUX_SYMBOL(__start_builtin_fw) = .;			\
-		KEEP(*(.builtin_fw))					\
-		VMLINUX_SYMBOL(__end_builtin_fw) = .;			\
-	}								\
-									\
 	TRACEDATA							\
 									\
 	/* Kernel symbol table: Normal symbols */			\
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 07/14] firmware: port built-in section to linker table
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This ports built-in firmware to use linker tables,
this replaces the custom section solution with a
generic solution.

This also demos the use of the .rodata linker table.

Tested with 0 built-in firmware, 1 and 2 built-in
firmwares successfully.

v6: rename table macro as suggested by Andy Shevchenko

v5:

o since we dropped SECTION_ORDER_ANY, use 'any' order level explicitly

v4:

o work around c6x toolchain bug by using SECTION_TBL_RO

o fix compilation on blackfin

v3:
o explicitly include tables.h as we no longer include
  tables.h from sections.h

o use new section_tbl_asmtype() helper on firmware/Makefile
  to enable having to unfold things on our own.

v2: introduced this file in this version of the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/x86/kernel/cpu/microcode/core.c |  8 ++++----
 drivers/base/firmware_class.c        | 12 ++++++------
 firmware/Makefile                    |  3 ++-
 include/asm-generic/vmlinux.lds.h    |  7 -------
 4 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 2af69d27da62..2c5004343b45 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -31,6 +31,7 @@
 #include <linux/cpu.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/tables.h>
 
 #include <asm/microcode_intel.h>
 #include <asm/cpu_device_id.h>
@@ -110,15 +111,14 @@ static bool __init check_loader_disabled_bsp(void)
 	return *res;
 }
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DECLARE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 bool get_builtin_firmware(struct cpio_data *cd, const char *name)
 {
 #ifdef CONFIG_FW_LOADER
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	linktable_for_each(b_fw, builtin_fw) {
 		if (!strcmp(name, b_fw->name)) {
 			cd->size = b_fw->size;
 			cd->data = b_fw->data;
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 4497d263209f..b9ac348e8d33 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -31,6 +31,7 @@
 #include <linux/reboot.h>
 #include <linux/security.h>
 #include <linux/swait.h>
+#include <linux/tables.h>
 
 #include <generated/utsrelease.h>
 
@@ -44,15 +45,14 @@ MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_FW_LOADER
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DEFINE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 				    void *buf, size_t size)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	linktable_for_each(b_fw, builtin_fw) {
 		if (strcmp(name, b_fw->name) == 0) {
 			fw->size = b_fw->size;
 			fw->data = b_fw->data;
@@ -68,9 +68,9 @@ static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 
 static bool fw_is_builtin_firmware(const struct firmware *fw)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++)
+	linktable_for_each(b_fw, builtin_fw)
 		if (fw->data == b_fw->data)
 			return true;
 
diff --git a/firmware/Makefile b/firmware/Makefile
index fa3e81c2a97b..9c8cae144ede 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -155,6 +155,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  ASM_ALIGN=$(if $(CONFIG_64BIT),3,2);			     \
 		  PROGBITS=$(if $(CONFIG_ARM),%,@)progbits;		     \
 		  echo "/* Generated by firmware/Makefile */"		> $@;\
+		  echo "\#include <asm/tables.h>"			>>$@;\
 		  echo "    .section .rodata"				>>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_bin:"				>>$@;\
@@ -164,7 +165,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_name:"				>>$@;\
 		  echo "    .string \"$$FWNAME\""			>>$@;\
-		  echo "    .section .builtin_fw,\"a\",$${PROGBITS}"	>>$@;\
+		  echo "    set_section_tbl_type(SECTION_TBL_RO, builtin_fw, any, a,$${PROGBITS})" >>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_name"		>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_bin"		>>$@;\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index ce1e9a310ada..8a5325d75932 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -324,13 +324,6 @@
 		VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .;	\
 	}								\
 									\
-	/* Built-in firmware blobs */					\
-	.builtin_fw        : AT(ADDR(.builtin_fw) - LOAD_OFFSET) {	\
-		VMLINUX_SYMBOL(__start_builtin_fw) = .;			\
-		KEEP(*(.builtin_fw))					\
-		VMLINUX_SYMBOL(__end_builtin_fw) = .;			\
-	}								\
-									\
 	TRACEDATA							\
 									\
 	/* Kernel symbol table: Normal symbols */			\
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 07/14] firmware: port built-in section to linker table
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez, Barry Song, Mike Frysinger, Michael Matz,
	Fengguang Wu

This ports built-in firmware to use linker tables,
this replaces the custom section solution with a
generic solution.

This also demos the use of the .rodata linker table.

Tested with 0 built-in firmware, 1 and 2 built-in
firmwares successfully.

v6: rename table macro as suggested by Andy Shevchenko

v5:

o since we dropped SECTION_ORDER_ANY, use 'any' order level explicitly

v4:

o work around c6x toolchain bug by using SECTION_TBL_RO

o fix compilation on blackfin

v3:
o explicitly include tables.h as we no longer include
  tables.h from sections.h

o use new section_tbl_asmtype() helper on firmware/Makefile
  to enable having to unfold things on our own.

v2: introduced this file in this version of the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/x86/kernel/cpu/microcode/core.c |  8 ++++----
 drivers/base/firmware_class.c        | 12 ++++++------
 firmware/Makefile                    |  3 ++-
 include/asm-generic/vmlinux.lds.h    |  7 -------
 4 files changed, 12 insertions(+), 18 deletions(-)

diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 2af69d27da62..2c5004343b45 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -31,6 +31,7 @@
 #include <linux/cpu.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/tables.h>
 
 #include <asm/microcode_intel.h>
 #include <asm/cpu_device_id.h>
@@ -110,15 +111,14 @@ static bool __init check_loader_disabled_bsp(void)
 	return *res;
 }
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DECLARE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 bool get_builtin_firmware(struct cpio_data *cd, const char *name)
 {
 #ifdef CONFIG_FW_LOADER
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	linktable_for_each(b_fw, builtin_fw) {
 		if (!strcmp(name, b_fw->name)) {
 			cd->size = b_fw->size;
 			cd->data = b_fw->data;
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 4497d263209f..b9ac348e8d33 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -31,6 +31,7 @@
 #include <linux/reboot.h>
 #include <linux/security.h>
 #include <linux/swait.h>
+#include <linux/tables.h>
 
 #include <generated/utsrelease.h>
 
@@ -44,15 +45,14 @@ MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_FW_LOADER
 
-extern struct builtin_fw __start_builtin_fw[];
-extern struct builtin_fw __end_builtin_fw[];
+DEFINE_LINKTABLE_RO(struct builtin_fw, builtin_fw);
 
 static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 				    void *buf, size_t size)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
+	linktable_for_each(b_fw, builtin_fw) {
 		if (strcmp(name, b_fw->name) == 0) {
 			fw->size = b_fw->size;
 			fw->data = b_fw->data;
@@ -68,9 +68,9 @@ static bool fw_get_builtin_firmware(struct firmware *fw, const char *name,
 
 static bool fw_is_builtin_firmware(const struct firmware *fw)
 {
-	struct builtin_fw *b_fw;
+	const struct builtin_fw *b_fw;
 
-	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++)
+	linktable_for_each(b_fw, builtin_fw)
 		if (fw->data == b_fw->data)
 			return true;
 
diff --git a/firmware/Makefile b/firmware/Makefile
index fa3e81c2a97b..9c8cae144ede 100644
--- a/firmware/Makefile
+++ b/firmware/Makefile
@@ -155,6 +155,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  ASM_ALIGN=$(if $(CONFIG_64BIT),3,2);			     \
 		  PROGBITS=$(if $(CONFIG_ARM),%,@)progbits;		     \
 		  echo "/* Generated by firmware/Makefile */"		> $@;\
+		  echo "\#include <asm/tables.h>"			>>$@;\
 		  echo "    .section .rodata"				>>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_bin:"				>>$@;\
@@ -164,7 +165,7 @@ quiet_cmd_fwbin = MK_FW   $@
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "_fw_$${FWSTR}_name:"				>>$@;\
 		  echo "    .string \"$$FWNAME\""			>>$@;\
-		  echo "    .section .builtin_fw,\"a\",$${PROGBITS}"	>>$@;\
+		  echo "    set_section_tbl_type(SECTION_TBL_RO, builtin_fw, any, a,$${PROGBITS})" >>$@;\
 		  echo "    .p2align $${ASM_ALIGN}"			>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_name"		>>$@;\
 		  echo "    $${ASM_WORD} _fw_$${FWSTR}_bin"		>>$@;\
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index ce1e9a310ada..8a5325d75932 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -324,13 +324,6 @@
 		VMLINUX_SYMBOL(__end_pci_fixups_suspend_late) = .;	\
 	}								\
 									\
-	/* Built-in firmware blobs */					\
-	.builtin_fw        : AT(ADDR(.builtin_fw) - LOAD_OFFSET) {	\
-		VMLINUX_SYMBOL(__start_builtin_fw) = .;			\
-		KEEP(*(.builtin_fw))					\
-		VMLINUX_SYMBOL(__end_builtin_fw) = .;			\
-	}								\
-									\
 	TRACEDATA							\
 									\
 	/* Kernel symbol table: Normal symbols */			\
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 08/14] jump_label: move guard #endif down where it belongs
  2017-01-15 21:10         ` Luis R. Rodriguez
  (?)
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

The ending header guard is misplaced. This has no
functional change, this is just an eye-sore.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/linux/jump_label.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index a0547c571800..b63d6b7b0db0 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -402,6 +402,6 @@ extern bool ____wrong_branch_error(void);
 #define static_branch_enable(x)		static_key_enable(&(x)->key)
 #define static_branch_disable(x)	static_key_disable(&(x)->key)
 
-#endif	/* _LINUX_JUMP_LABEL_H */
-
 #endif /* __ASSEMBLY__ */
+
+#endif	/* _LINUX_JUMP_LABEL_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 08/14] jump_label: move guard #endif down where it belongs
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

The ending header guard is misplaced. This has no
functional change, this is just an eye-sore.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/linux/jump_label.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index a0547c571800..b63d6b7b0db0 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -402,6 +402,6 @@ extern bool ____wrong_branch_error(void);
 #define static_branch_enable(x)		static_key_enable(&(x)->key)
 #define static_branch_disable(x)	static_key_disable(&(x)->key)
 
-#endif	/* _LINUX_JUMP_LABEL_H */
-
 #endif /* __ASSEMBLY__ */
+
+#endif	/* _LINUX_JUMP_LABEL_H */
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 08/14] jump_label: move guard #endif down where it belongs
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

The ending header guard is misplaced. This has no
functional change, this is just an eye-sore.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/linux/jump_label.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index a0547c571800..b63d6b7b0db0 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -402,6 +402,6 @@ extern bool ____wrong_branch_error(void);
 #define static_branch_enable(x)		static_key_enable(&(x)->key)
 #define static_branch_disable(x)	static_key_disable(&(x)->key)
 
-#endif	/* _LINUX_JUMP_LABEL_H */
-
 #endif /* __ASSEMBLY__ */
+
+#endif	/* _LINUX_JUMP_LABEL_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 09/14] jump_label: port __jump_table to linker tables
  2017-01-15 21:10         ` Luis R. Rodriguez
  (?)
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Move the __jump_table from the a custom section solution
to a generic solution, this avoiding extra vmlinux.lds.h
customizations.

This also demos the use of the .data linker table and of
the shared asm call push_section_tbl().

Built-in kernel functionality was tested with CONFIG_STATIC_KEYS_SELFTEST.
Moduler  kernel functionality was tested with CONFIG_TEST_STATIC_KEYS.
Both work as expected.

Since __jump_table sections are also supported per
module this also required expanding module-common.lds.S
to capture and fold all .data.tlb.__jump_table.* onto
the the section __jump_table -- in this case for modules
need to keep a reference in place, given the alternative
is to use DEFINE_LINKTABLE(struct jump_entry, __jump_table)
per module -- and later through macro hacks instantiate
the jump entries per module upon init. This is doable but
we'd loose out on the sorting of the table using the
linker, to sort we'd always still need to expand the
module common linker script. An alternative mechanism
is possible which would make these custom module sections
extensions dynamic without requiring manual changes, this
however is best done later through a separate evolution
once linker tables are in place.

A careful reviewer may note that some architectures use
"\n\t" to separate asm code, while others just use a new line.
Upon review last time it was deemed reasonable to for all
architectures to just use "\n", this is defined as ASM_CMD_SEP,
and if an architecture needs to override they can do so on their
architecture sections.h prior to including asm-generic/sections.h

v6: rename table macro as suggested by Andy Shevchenko

v5:

o Use ..tbl instead of .tbl as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

o Use LINKTABLE_START() and LINKTABLE_END()

o fixed tile jump label port -- tile got jump label support as of
  commit 65a792e84f25d1 ("tile/jump_label: add jump label support
  for TILE-Gx"), as such we just needed to adjust the asm to account
  for the new linker table API use. This commit was merged as of v4.5-rc1.

v4:

o Some architectures allow linker scripts to follow including header
  files, some others do not, so if you need a helper on a linker script
  you need to explicitly include it. So for instance although
  scripts/module-common.lds.S includes <asm/tables.h> and this file
  includes <asm/section-core.h>, you still need to explicitly
  include it on the linker script. This issue is present on ARM.

o as per Josh Poimboeuf open code the section table name instead
  of including the kernel section headers, the simplicity and
  independence from the kernel is preferred.

v3:

o More elaborate tests performed
o first modular support use case, module tested was
  CONFIG_TEST_STATIC_KEYS (lib/test_static_keys.ko), this
  required us to extend module-common.lds.S
o use generic push_section_tbl_any() for all architectures
o Makes use of ASM_CMD_SEP to enable architectures to override later
  if needed
o guard tables.h inclusion and table definition with __KERNEL__

v2: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arm/include/asm/jump_label.h     |  6 ++++--
 arch/arm64/include/asm/jump_label.h   |  6 ++++--
 arch/mips/include/asm/jump_label.h    |  6 ++++--
 arch/powerpc/include/asm/jump_label.h |  8 +++++---
 arch/s390/include/asm/jump_label.h    |  6 ++++--
 arch/sparc/include/asm/jump_label.h   |  6 ++++--
 arch/tile/include/asm/jump_label.h    |  5 +++--
 arch/x86/include/asm/jump_label.h     | 10 ++++++----
 include/asm-generic/vmlinux.lds.h     |  5 -----
 include/linux/jump_label.h            |  4 ++--
 kernel/jump_label.c                   | 17 ++++++++++-------
 scripts/module-common.lds             |  1 +
 tools/objtool/special.c               |  2 +-
 13 files changed, 48 insertions(+), 34 deletions(-)

diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h
index 34f7b6980d21..609e0592a942 100644
--- a/arch/arm/include/asm/jump_label.h
+++ b/arch/arm/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_ARM_JUMP_LABEL_H
 #define _ASM_ARM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(nop) "\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
@@ -26,7 +28,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(b) " %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
diff --git a/arch/arm64/include/asm/jump_label.h b/arch/arm64/include/asm/jump_label.h
index 1b5e0e843c3a..bb56ac4fafb5 100644
--- a/arch/arm64/include/asm/jump_label.h
+++ b/arch/arm64/include/asm/jump_label.h
@@ -19,6 +19,8 @@
 #ifndef __ASM_JUMP_LABEL_H
 #define __ASM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -29,7 +31,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm goto("1: nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
@@ -43,7 +45,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm goto("1: b %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
diff --git a/arch/mips/include/asm/jump_label.h b/arch/mips/include/asm/jump_label.h
index e77672539e8e..07289a1b1bcd 100644
--- a/arch/mips/include/asm/jump_label.h
+++ b/arch/mips/include/asm/jump_label.h
@@ -8,6 +8,8 @@
 #ifndef _ASM_MIPS_JUMP_LABEL_H
 #define _ASM_MIPS_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -30,7 +32,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\t" NOP_INSN "\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -44,7 +46,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\tj %l[l_yes]\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
index 9a287e0ac8b1..7a75623740d0 100644
--- a/arch/powerpc/include/asm/jump_label.h
+++ b/arch/powerpc/include/asm/jump_label.h
@@ -10,6 +10,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
 
@@ -23,7 +25,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 "nop # arch_static_branch\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -37,7 +39,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes] # arch_static_branch_jump\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -62,7 +64,7 @@ struct jump_entry {
 #else
 #define ARCH_STATIC_BRANCH(LABEL, KEY)		\
 1098:	nop;					\
-	.pushsection __jump_table, "aw";	\
+	push_section_tbl_any(.data, __jump_table, aw); \
 	FTR_ENTRY_LONG 1098b, LABEL, KEY;	\
 	.popsection
 #endif
diff --git a/arch/s390/include/asm/jump_label.h b/arch/s390/include/asm/jump_label.h
index 9be198f5ee79..58e53af49e7e 100644
--- a/arch/s390/include/asm/jump_label.h
+++ b/arch/s390/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_S390_JUMP_LABEL_H
 #define _ASM_S390_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -16,7 +18,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 0,"__stringify(JUMP_LABEL_NOP_OFFSET)"\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
@@ -30,7 +32,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 15, %l[label]\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
diff --git a/arch/sparc/include/asm/jump_label.h b/arch/sparc/include/asm/jump_label.h
index 62d0354d1727..35d3e5d31821 100644
--- a/arch/sparc/include/asm/jump_label.h
+++ b/arch/sparc/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_SPARC_JUMP_LABEL_H
 #define _ASM_SPARC_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 	asm_volatile_goto("1:\n\t"
 		 "nop\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
@@ -28,7 +30,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes]\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
diff --git a/arch/tile/include/asm/jump_label.h b/arch/tile/include/asm/jump_label.h
index cde7573f397b..9bd989daad4a 100644
--- a/arch/tile/include/asm/jump_label.h
+++ b/arch/tile/include/asm/jump_label.h
@@ -16,6 +16,7 @@
 #define _ASM_TILE_JUMP_LABEL_H
 
 #include <arch/opcode.h>
+#include <asm/tables.h>
 
 #define JUMP_LABEL_NOP_SIZE	TILE_BUNDLE_SIZE_IN_BYTES
 
@@ -24,7 +25,7 @@ static __always_inline bool arch_static_branch(struct static_key *key,
 {
 	asm_volatile_goto("1:\n\t"
 		"nop" "\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".quad 1b, %l[l_yes], %0 + %1 \n\t"
 		".popsection\n\t"
 		: :  "i" (key), "i" (branch) : : l_yes);
@@ -38,7 +39,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key,
 {
 	asm_volatile_goto("1:\n\t"
 		"j %l[l_yes]" "\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".quad 1b, %l[l_yes], %0 + %1 \n\t"
 		".popsection\n\t"
 		: :  "i" (key), "i" (branch) : : l_yes);
diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h
index adc54c12cbd1..627df4752db0 100644
--- a/arch/x86/include/asm/jump_label.h
+++ b/arch/x86/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_JUMP_LABEL_H
 #define _ASM_X86_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef HAVE_JUMP_LABEL
 /*
  * For better or for worse, if jump labels (the gcc extension) are missing,
@@ -34,7 +36,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:"
 		".byte " __stringify(STATIC_KEY_INIT_NOP) "\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -50,7 +52,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:"
 		".byte 0xe9\n\t .long %l[l_yes] - 2f\n\t"
 		"2:\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -85,7 +87,7 @@ struct jump_entry {
 	.else
 	.byte		STATIC_KEY_INIT_NOP
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(.data, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key
 	.popsection
@@ -101,7 +103,7 @@ struct jump_entry {
 	.long		\target - .Lstatic_jump_after_\@
 .Lstatic_jump_after_\@:
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(.data, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key + 1
 	.popsection
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 8a5325d75932..887d844f0406 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -216,11 +216,6 @@
 	*(.data.unlikely)						\
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
-	/* implement dynamic printk debug */				\
-	. = ALIGN(8);                                                   \
-	VMLINUX_SYMBOL(__start___jump_table) = .;                       \
-	KEEP(*(__jump_table))                                           \
-	VMLINUX_SYMBOL(__stop___jump_table) = .;                        \
 	. = ALIGN(8);							\
 	VMLINUX_SYMBOL(__start___verbose) = .;                          \
 	KEEP(*(__verbose))                                              \
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index b63d6b7b0db0..e6277888b558 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -117,6 +117,7 @@ enum jump_label_type {
 struct module;
 
 #ifdef HAVE_JUMP_LABEL
+#include <linux/tables.h>
 
 #define JUMP_TYPE_FALSE	0UL
 #define JUMP_TYPE_TRUE	1UL
@@ -132,8 +133,7 @@ static __always_inline bool static_key_true(struct static_key *key)
 	return !arch_static_branch(key, true);
 }
 
-extern struct jump_entry __start___jump_table[];
-extern struct jump_entry __stop___jump_table[];
+DECLARE_LINKTABLE(struct jump_entry, __jump_table);
 
 extern void jump_label_init(void);
 extern void jump_label_lock(void);
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 93ad6c1fb9b6..4252f17eaeb5 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -15,9 +15,12 @@
 #include <linux/static_key.h>
 #include <linux/jump_label_ratelimit.h>
 #include <linux/bug.h>
+#include <linux/tables.h>
 
 #ifdef HAVE_JUMP_LABEL
 
+DEFINE_LINKTABLE(struct jump_entry, __jump_table);
+
 /* mutex to protect coming/going of the the jump_label table */
 static DEFINE_MUTEX(jump_label_mutex);
 
@@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
 
 void __init jump_label_init(void)
 {
-	struct jump_entry *iter_start = __start___jump_table;
-	struct jump_entry *iter_stop = __stop___jump_table;
 	struct static_key *key = NULL;
 	struct jump_entry *iter;
 
@@ -292,9 +293,10 @@ void __init jump_label_init(void)
 		return;
 
 	jump_label_lock();
-	jump_label_sort_entries(iter_start, iter_stop);
+	jump_label_sort_entries(LINKTABLE_START(__jump_table),
+				LINKTABLE_END(__jump_table));
 
-	for (iter = iter_start; iter < iter_stop; iter++) {
+	linktable_for_each(iter, __jump_table) {
 		struct static_key *iterk;
 
 		/* rewrite NOPs */
@@ -539,8 +541,9 @@ early_initcall(jump_label_init_module);
  */
 int jump_label_text_reserved(void *start, void *end)
 {
-	int ret = __jump_label_text_reserved(__start___jump_table,
-			__stop___jump_table, start, end);
+	int ret = __jump_label_text_reserved(LINKTABLE_START(__jump_table),
+					     LINKTABLE_END(__jump_table),
+					     start, end);
 
 	if (ret)
 		return ret;
@@ -553,7 +556,7 @@ int jump_label_text_reserved(void *start, void *end)
 
 static void jump_label_update(struct static_key *key)
 {
-	struct jump_entry *stop = __stop___jump_table;
+	struct jump_entry *stop = LINKTABLE_END(__jump_table);
 	struct jump_entry *entry = static_key_entries(key);
 #ifdef CONFIG_MODULES
 	struct module *mod;
diff --git a/scripts/module-common.lds b/scripts/module-common.lds
index 73a2c7da0e55..db0e724556c5 100644
--- a/scripts/module-common.lds
+++ b/scripts/module-common.lds
@@ -16,6 +16,7 @@ SECTIONS {
 	__kcrctab_unused	0 : { *(SORT(___kcrctab_unused+*)) }
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
+	__jump_table		0 : { *(SORT(.data..tbl.__jump_table.*)) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
diff --git a/tools/objtool/special.c b/tools/objtool/special.c
index bff8abb3a4aa..79968e118294 100644
--- a/tools/objtool/special.c
+++ b/tools/objtool/special.c
@@ -63,7 +63,7 @@ struct special_entry entries[] = {
 		.feature = ALT_FEATURE_OFFSET,
 	},
 	{
-		.sec = "__jump_table",
+		.sec = ".data..tbl.__jump_table.any",
 		.jump_or_nop = true,
 		.size = JUMP_ENTRY_SIZE,
 		.orig = JUMP_ORIG_OFFSET,
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 09/14] jump_label: port __jump_table to linker tables
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Move the __jump_table from the a custom section solution
to a generic solution, this avoiding extra vmlinux.lds.h
customizations.

This also demos the use of the .data linker table and of
the shared asm call push_section_tbl().

Built-in kernel functionality was tested with CONFIG_STATIC_KEYS_SELFTEST.
Moduler  kernel functionality was tested with CONFIG_TEST_STATIC_KEYS.
Both work as expected.

Since __jump_table sections are also supported per
module this also required expanding module-common.lds.S
to capture and fold all .data.tlb.__jump_table.* onto
the the section __jump_table -- in this case for modules
need to keep a reference in place, given the alternative
is to use DEFINE_LINKTABLE(struct jump_entry, __jump_table)
per module -- and later through macro hacks instantiate
the jump entries per module upon init. This is doable but
we'd loose out on the sorting of the table using the
linker, to sort we'd always still need to expand the
module common linker script. An alternative mechanism
is possible which would make these custom module sections
extensions dynamic without requiring manual changes, this
however is best done later through a separate evolution
once linker tables are in place.

A careful reviewer may note that some architectures use
"\n\t" to separate asm code, while others just use a new line.
Upon review last time it was deemed reasonable to for all
architectures to just use "\n", this is defined as ASM_CMD_SEP,
and if an architecture needs to override they can do so on their
architecture sections.h prior to including asm-generic/sections.h

v6: rename table macro as suggested by Andy Shevchenko

v5:

o Use ..tbl instead of .tbl as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

o Use LINKTABLE_START() and LINKTABLE_END()

o fixed tile jump label port -- tile got jump label support as of
  commit 65a792e84f25d1 ("tile/jump_label: add jump label support
  for TILE-Gx"), as such we just needed to adjust the asm to account
  for the new linker table API use. This commit was merged as of v4.5-rc1.

v4:

o Some architectures allow linker scripts to follow including header
  files, some others do not, so if you need a helper on a linker script
  you need to explicitly include it. So for instance although
  scripts/module-common.lds.S includes <asm/tables.h> and this file
  includes <asm/section-core.h>, you still need to explicitly
  include it on the linker script. This issue is present on ARM.

o as per Josh Poimboeuf open code the section table name instead
  of including the kernel section headers, the simplicity and
  independence from the kernel is preferred.

v3:

o More elaborate tests performed
o first modular support use case, module tested was
  CONFIG_TEST_STATIC_KEYS (lib/test_static_keys.ko), this
  required us to extend module-common.lds.S
o use generic push_section_tbl_any() for all architectures
o Makes use of ASM_CMD_SEP to enable architectures to override later
  if needed
o guard tables.h inclusion and table definition with __KERNEL__

v2: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arm/include/asm/jump_label.h     |  6 ++++--
 arch/arm64/include/asm/jump_label.h   |  6 ++++--
 arch/mips/include/asm/jump_label.h    |  6 ++++--
 arch/powerpc/include/asm/jump_label.h |  8 +++++---
 arch/s390/include/asm/jump_label.h    |  6 ++++--
 arch/sparc/include/asm/jump_label.h   |  6 ++++--
 arch/tile/include/asm/jump_label.h    |  5 +++--
 arch/x86/include/asm/jump_label.h     | 10 ++++++----
 include/asm-generic/vmlinux.lds.h     |  5 -----
 include/linux/jump_label.h            |  4 ++--
 kernel/jump_label.c                   | 17 ++++++++++-------
 scripts/module-common.lds             |  1 +
 tools/objtool/special.c               |  2 +-
 13 files changed, 48 insertions(+), 34 deletions(-)

diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h
index 34f7b6980d21..609e0592a942 100644
--- a/arch/arm/include/asm/jump_label.h
+++ b/arch/arm/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_ARM_JUMP_LABEL_H
 #define _ASM_ARM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(nop) "\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
@@ -26,7 +28,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(b) " %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
diff --git a/arch/arm64/include/asm/jump_label.h b/arch/arm64/include/asm/jump_label.h
index 1b5e0e843c3a..bb56ac4fafb5 100644
--- a/arch/arm64/include/asm/jump_label.h
+++ b/arch/arm64/include/asm/jump_label.h
@@ -19,6 +19,8 @@
 #ifndef __ASM_JUMP_LABEL_H
 #define __ASM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -29,7 +31,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm goto("1: nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
@@ -43,7 +45,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm goto("1: b %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
diff --git a/arch/mips/include/asm/jump_label.h b/arch/mips/include/asm/jump_label.h
index e77672539e8e..07289a1b1bcd 100644
--- a/arch/mips/include/asm/jump_label.h
+++ b/arch/mips/include/asm/jump_label.h
@@ -8,6 +8,8 @@
 #ifndef _ASM_MIPS_JUMP_LABEL_H
 #define _ASM_MIPS_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -30,7 +32,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\t" NOP_INSN "\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -44,7 +46,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\tj %l[l_yes]\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
index 9a287e0ac8b1..7a75623740d0 100644
--- a/arch/powerpc/include/asm/jump_label.h
+++ b/arch/powerpc/include/asm/jump_label.h
@@ -10,6 +10,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
 
@@ -23,7 +25,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 "nop # arch_static_branch\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -37,7 +39,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes] # arch_static_branch_jump\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -62,7 +64,7 @@ struct jump_entry {
 #else
 #define ARCH_STATIC_BRANCH(LABEL, KEY)		\
 1098:	nop;					\
-	.pushsection __jump_table, "aw";	\
+	push_section_tbl_any(.data, __jump_table, aw); \
 	FTR_ENTRY_LONG 1098b, LABEL, KEY;	\
 	.popsection
 #endif
diff --git a/arch/s390/include/asm/jump_label.h b/arch/s390/include/asm/jump_label.h
index 9be198f5ee79..58e53af49e7e 100644
--- a/arch/s390/include/asm/jump_label.h
+++ b/arch/s390/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_S390_JUMP_LABEL_H
 #define _ASM_S390_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -16,7 +18,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 0,"__stringify(JUMP_LABEL_NOP_OFFSET)"\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
@@ -30,7 +32,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 15, %l[label]\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
diff --git a/arch/sparc/include/asm/jump_label.h b/arch/sparc/include/asm/jump_label.h
index 62d0354d1727..35d3e5d31821 100644
--- a/arch/sparc/include/asm/jump_label.h
+++ b/arch/sparc/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_SPARC_JUMP_LABEL_H
 #define _ASM_SPARC_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 	asm_volatile_goto("1:\n\t"
 		 "nop\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
@@ -28,7 +30,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes]\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
diff --git a/arch/tile/include/asm/jump_label.h b/arch/tile/include/asm/jump_label.h
index cde7573f397b..9bd989daad4a 100644
--- a/arch/tile/include/asm/jump_label.h
+++ b/arch/tile/include/asm/jump_label.h
@@ -16,6 +16,7 @@
 #define _ASM_TILE_JUMP_LABEL_H
 
 #include <arch/opcode.h>
+#include <asm/tables.h>
 
 #define JUMP_LABEL_NOP_SIZE	TILE_BUNDLE_SIZE_IN_BYTES
 
@@ -24,7 +25,7 @@ static __always_inline bool arch_static_branch(struct static_key *key,
 {
 	asm_volatile_goto("1:\n\t"
 		"nop" "\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".quad 1b, %l[l_yes], %0 + %1 \n\t"
 		".popsection\n\t"
 		: :  "i" (key), "i" (branch) : : l_yes);
@@ -38,7 +39,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key,
 {
 	asm_volatile_goto("1:\n\t"
 		"j %l[l_yes]" "\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".quad 1b, %l[l_yes], %0 + %1 \n\t"
 		".popsection\n\t"
 		: :  "i" (key), "i" (branch) : : l_yes);
diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h
index adc54c12cbd1..627df4752db0 100644
--- a/arch/x86/include/asm/jump_label.h
+++ b/arch/x86/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_JUMP_LABEL_H
 #define _ASM_X86_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef HAVE_JUMP_LABEL
 /*
  * For better or for worse, if jump labels (the gcc extension) are missing,
@@ -34,7 +36,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:"
 		".byte " __stringify(STATIC_KEY_INIT_NOP) "\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -50,7 +52,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:"
 		".byte 0xe9\n\t .long %l[l_yes] - 2f\n\t"
 		"2:\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -85,7 +87,7 @@ struct jump_entry {
 	.else
 	.byte		STATIC_KEY_INIT_NOP
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(.data, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key
 	.popsection
@@ -101,7 +103,7 @@ struct jump_entry {
 	.long		\target - .Lstatic_jump_after_\@
 .Lstatic_jump_after_\@:
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(.data, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key + 1
 	.popsection
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 8a5325d75932..887d844f0406 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -216,11 +216,6 @@
 	*(.data.unlikely)						\
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
-	/* implement dynamic printk debug */				\
-	. = ALIGN(8);                                                   \
-	VMLINUX_SYMBOL(__start___jump_table) = .;                       \
-	KEEP(*(__jump_table))                                           \
-	VMLINUX_SYMBOL(__stop___jump_table) = .;                        \
 	. = ALIGN(8);							\
 	VMLINUX_SYMBOL(__start___verbose) = .;                          \
 	KEEP(*(__verbose))                                              \
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index b63d6b7b0db0..e6277888b558 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -117,6 +117,7 @@ enum jump_label_type {
 struct module;
 
 #ifdef HAVE_JUMP_LABEL
+#include <linux/tables.h>
 
 #define JUMP_TYPE_FALSE	0UL
 #define JUMP_TYPE_TRUE	1UL
@@ -132,8 +133,7 @@ static __always_inline bool static_key_true(struct static_key *key)
 	return !arch_static_branch(key, true);
 }
 
-extern struct jump_entry __start___jump_table[];
-extern struct jump_entry __stop___jump_table[];
+DECLARE_LINKTABLE(struct jump_entry, __jump_table);
 
 extern void jump_label_init(void);
 extern void jump_label_lock(void);
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 93ad6c1fb9b6..4252f17eaeb5 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -15,9 +15,12 @@
 #include <linux/static_key.h>
 #include <linux/jump_label_ratelimit.h>
 #include <linux/bug.h>
+#include <linux/tables.h>
 
 #ifdef HAVE_JUMP_LABEL
 
+DEFINE_LINKTABLE(struct jump_entry, __jump_table);
+
 /* mutex to protect coming/going of the the jump_label table */
 static DEFINE_MUTEX(jump_label_mutex);
 
@@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
 
 void __init jump_label_init(void)
 {
-	struct jump_entry *iter_start = __start___jump_table;
-	struct jump_entry *iter_stop = __stop___jump_table;
 	struct static_key *key = NULL;
 	struct jump_entry *iter;
 
@@ -292,9 +293,10 @@ void __init jump_label_init(void)
 		return;
 
 	jump_label_lock();
-	jump_label_sort_entries(iter_start, iter_stop);
+	jump_label_sort_entries(LINKTABLE_START(__jump_table),
+				LINKTABLE_END(__jump_table));
 
-	for (iter = iter_start; iter < iter_stop; iter++) {
+	linktable_for_each(iter, __jump_table) {
 		struct static_key *iterk;
 
 		/* rewrite NOPs */
@@ -539,8 +541,9 @@ early_initcall(jump_label_init_module);
  */
 int jump_label_text_reserved(void *start, void *end)
 {
-	int ret = __jump_label_text_reserved(__start___jump_table,
-			__stop___jump_table, start, end);
+	int ret = __jump_label_text_reserved(LINKTABLE_START(__jump_table),
+					     LINKTABLE_END(__jump_table),
+					     start, end);
 
 	if (ret)
 		return ret;
@@ -553,7 +556,7 @@ int jump_label_text_reserved(void *start, void *end)
 
 static void jump_label_update(struct static_key *key)
 {
-	struct jump_entry *stop = __stop___jump_table;
+	struct jump_entry *stop = LINKTABLE_END(__jump_table);
 	struct jump_entry *entry = static_key_entries(key);
 #ifdef CONFIG_MODULES
 	struct module *mod;
diff --git a/scripts/module-common.lds b/scripts/module-common.lds
index 73a2c7da0e55..db0e724556c5 100644
--- a/scripts/module-common.lds
+++ b/scripts/module-common.lds
@@ -16,6 +16,7 @@ SECTIONS {
 	__kcrctab_unused	0 : { *(SORT(___kcrctab_unused+*)) }
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
+	__jump_table		0 : { *(SORT(.data..tbl.__jump_table.*)) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
diff --git a/tools/objtool/special.c b/tools/objtool/special.c
index bff8abb3a4aa..79968e118294 100644
--- a/tools/objtool/special.c
+++ b/tools/objtool/special.c
@@ -63,7 +63,7 @@ struct special_entry entries[] = {
 		.feature = ALT_FEATURE_OFFSET,
 	},
 	{
-		.sec = "__jump_table",
+		.sec = ".data..tbl.__jump_table.any",
 		.jump_or_nop = true,
 		.size = JUMP_ENTRY_SIZE,
 		.orig = JUMP_ORIG_OFFSET,
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 09/14] jump_label: port __jump_table to linker tables
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

Move the __jump_table from the a custom section solution
to a generic solution, this avoiding extra vmlinux.lds.h
customizations.

This also demos the use of the .data linker table and of
the shared asm call push_section_tbl().

Built-in kernel functionality was tested with CONFIG_STATIC_KEYS_SELFTEST.
Moduler  kernel functionality was tested with CONFIG_TEST_STATIC_KEYS.
Both work as expected.

Since __jump_table sections are also supported per
module this also required expanding module-common.lds.S
to capture and fold all .data.tlb.__jump_table.* onto
the the section __jump_table -- in this case for modules
need to keep a reference in place, given the alternative
is to use DEFINE_LINKTABLE(struct jump_entry, __jump_table)
per module -- and later through macro hacks instantiate
the jump entries per module upon init. This is doable but
we'd loose out on the sorting of the table using the
linker, to sort we'd always still need to expand the
module common linker script. An alternative mechanism
is possible which would make these custom module sections
extensions dynamic without requiring manual changes, this
however is best done later through a separate evolution
once linker tables are in place.

A careful reviewer may note that some architectures use
"\n\t" to separate asm code, while others just use a new line.
Upon review last time it was deemed reasonable to for all
architectures to just use "\n", this is defined as ASM_CMD_SEP,
and if an architecture needs to override they can do so on their
architecture sections.h prior to including asm-generic/sections.h

v6: rename table macro as suggested by Andy Shevchenko

v5:

o Use ..tbl instead of .tbl as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

o Use LINKTABLE_START() and LINKTABLE_END()

o fixed tile jump label port -- tile got jump label support as of
  commit 65a792e84f25d1 ("tile/jump_label: add jump label support
  for TILE-Gx"), as such we just needed to adjust the asm to account
  for the new linker table API use. This commit was merged as of v4.5-rc1.

v4:

o Some architectures allow linker scripts to follow including header
  files, some others do not, so if you need a helper on a linker script
  you need to explicitly include it. So for instance although
  scripts/module-common.lds.S includes <asm/tables.h> and this file
  includes <asm/section-core.h>, you still need to explicitly
  include it on the linker script. This issue is present on ARM.

o as per Josh Poimboeuf open code the section table name instead
  of including the kernel section headers, the simplicity and
  independence from the kernel is preferred.

v3:

o More elaborate tests performed
o first modular support use case, module tested was
  CONFIG_TEST_STATIC_KEYS (lib/test_static_keys.ko), this
  required us to extend module-common.lds.S
o use generic push_section_tbl_any() for all architectures
o Makes use of ASM_CMD_SEP to enable architectures to override later
  if needed
o guard tables.h inclusion and table definition with __KERNEL__

v2: introduced in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arm/include/asm/jump_label.h     |  6 ++++--
 arch/arm64/include/asm/jump_label.h   |  6 ++++--
 arch/mips/include/asm/jump_label.h    |  6 ++++--
 arch/powerpc/include/asm/jump_label.h |  8 +++++---
 arch/s390/include/asm/jump_label.h    |  6 ++++--
 arch/sparc/include/asm/jump_label.h   |  6 ++++--
 arch/tile/include/asm/jump_label.h    |  5 +++--
 arch/x86/include/asm/jump_label.h     | 10 ++++++----
 include/asm-generic/vmlinux.lds.h     |  5 -----
 include/linux/jump_label.h            |  4 ++--
 kernel/jump_label.c                   | 17 ++++++++++-------
 scripts/module-common.lds             |  1 +
 tools/objtool/special.c               |  2 +-
 13 files changed, 48 insertions(+), 34 deletions(-)

diff --git a/arch/arm/include/asm/jump_label.h b/arch/arm/include/asm/jump_label.h
index 34f7b6980d21..609e0592a942 100644
--- a/arch/arm/include/asm/jump_label.h
+++ b/arch/arm/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_ARM_JUMP_LABEL_H
 #define _ASM_ARM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(nop) "\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
@@ -26,7 +28,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 WASM(b) " %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
 		 : :  "i" (&((char *)key)[branch]) :  : l_yes);
diff --git a/arch/arm64/include/asm/jump_label.h b/arch/arm64/include/asm/jump_label.h
index 1b5e0e843c3a..bb56ac4fafb5 100644
--- a/arch/arm64/include/asm/jump_label.h
+++ b/arch/arm64/include/asm/jump_label.h
@@ -19,6 +19,8 @@
 #ifndef __ASM_JUMP_LABEL_H
 #define __ASM_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -29,7 +31,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm goto("1: nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
@@ -43,7 +45,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm goto("1: b %l[l_yes]\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 3\n\t"
 		 ".quad 1b, %l[l_yes], %c0\n\t"
 		 ".popsection\n\t"
diff --git a/arch/mips/include/asm/jump_label.h b/arch/mips/include/asm/jump_label.h
index e77672539e8e..07289a1b1bcd 100644
--- a/arch/mips/include/asm/jump_label.h
+++ b/arch/mips/include/asm/jump_label.h
@@ -8,6 +8,8 @@
 #ifndef _ASM_MIPS_JUMP_LABEL_H
 #define _ASM_MIPS_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -30,7 +32,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\t" NOP_INSN "\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -44,7 +46,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\tj %l[l_yes]\n\t"
 		"nop\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		WORD_INSN " 1b, %l[l_yes], %0\n\t"
 		".popsection\n\t"
 		: :  "i" (&((char *)key)[branch]) : : l_yes);
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h
index 9a287e0ac8b1..7a75623740d0 100644
--- a/arch/powerpc/include/asm/jump_label.h
+++ b/arch/powerpc/include/asm/jump_label.h
@@ -10,6 +10,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
 
@@ -23,7 +25,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:\n\t"
 		 "nop # arch_static_branch\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -37,7 +39,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 {
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes] # arch_static_branch_jump\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
 		 : :  "i" (&((char *)key)[branch]) : : l_yes);
@@ -62,7 +64,7 @@ struct jump_entry {
 #else
 #define ARCH_STATIC_BRANCH(LABEL, KEY)		\
 1098:	nop;					\
-	.pushsection __jump_table, "aw";	\
+	push_section_tbl_any(.data, __jump_table, aw); \
 	FTR_ENTRY_LONG 1098b, LABEL, KEY;	\
 	.popsection
 #endif
diff --git a/arch/s390/include/asm/jump_label.h b/arch/s390/include/asm/jump_label.h
index 9be198f5ee79..58e53af49e7e 100644
--- a/arch/s390/include/asm/jump_label.h
+++ b/arch/s390/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_S390_JUMP_LABEL_H
 #define _ASM_S390_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -16,7 +18,7 @@
 static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 0,"__stringify(JUMP_LABEL_NOP_OFFSET)"\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
@@ -30,7 +32,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
 {
 	asm_volatile_goto("0:	brcl 15, %l[label]\n"
-		".pushsection __jump_table, \"aw\"\n"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".balign 8\n"
 		".quad 0b, %l[label], %0\n"
 		".popsection\n"
diff --git a/arch/sparc/include/asm/jump_label.h b/arch/sparc/include/asm/jump_label.h
index 62d0354d1727..35d3e5d31821 100644
--- a/arch/sparc/include/asm/jump_label.h
+++ b/arch/sparc/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_SPARC_JUMP_LABEL_H
 #define _ASM_SPARC_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -12,7 +14,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 	asm_volatile_goto("1:\n\t"
 		 "nop\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
@@ -28,7 +30,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:\n\t"
 		 "b %l[l_yes]\n\t"
 		 "nop\n\t"
-		 ".pushsection __jump_table,  \"aw\"\n\t"
+		 push_section_tbl_any(.data, __jump_table, aw)
 		 ".align 4\n\t"
 		 ".word 1b, %l[l_yes], %c0\n\t"
 		 ".popsection \n\t"
diff --git a/arch/tile/include/asm/jump_label.h b/arch/tile/include/asm/jump_label.h
index cde7573f397b..9bd989daad4a 100644
--- a/arch/tile/include/asm/jump_label.h
+++ b/arch/tile/include/asm/jump_label.h
@@ -16,6 +16,7 @@
 #define _ASM_TILE_JUMP_LABEL_H
 
 #include <arch/opcode.h>
+#include <asm/tables.h>
 
 #define JUMP_LABEL_NOP_SIZE	TILE_BUNDLE_SIZE_IN_BYTES
 
@@ -24,7 +25,7 @@ static __always_inline bool arch_static_branch(struct static_key *key,
 {
 	asm_volatile_goto("1:\n\t"
 		"nop" "\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".quad 1b, %l[l_yes], %0 + %1 \n\t"
 		".popsection\n\t"
 		: :  "i" (key), "i" (branch) : : l_yes);
@@ -38,7 +39,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key,
 {
 	asm_volatile_goto("1:\n\t"
 		"j %l[l_yes]" "\n\t"
-		".pushsection __jump_table,  \"aw\"\n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		".quad 1b, %l[l_yes], %0 + %1 \n\t"
 		".popsection\n\t"
 		: :  "i" (key), "i" (branch) : : l_yes);
diff --git a/arch/x86/include/asm/jump_label.h b/arch/x86/include/asm/jump_label.h
index adc54c12cbd1..627df4752db0 100644
--- a/arch/x86/include/asm/jump_label.h
+++ b/arch/x86/include/asm/jump_label.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_JUMP_LABEL_H
 #define _ASM_X86_JUMP_LABEL_H
 
+#include <asm/tables.h>
+
 #ifndef HAVE_JUMP_LABEL
 /*
  * For better or for worse, if jump labels (the gcc extension) are missing,
@@ -34,7 +36,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
 {
 	asm_volatile_goto("1:"
 		".byte " __stringify(STATIC_KEY_INIT_NOP) "\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -50,7 +52,7 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool
 	asm_volatile_goto("1:"
 		".byte 0xe9\n\t .long %l[l_yes] - 2f\n\t"
 		"2:\n\t"
-		".pushsection __jump_table,  \"aw\" \n\t"
+		push_section_tbl_any(.data, __jump_table, aw)
 		_ASM_ALIGN "\n\t"
 		_ASM_PTR "1b, %l[l_yes], %c0 + %c1 \n\t"
 		".popsection \n\t"
@@ -85,7 +87,7 @@ struct jump_entry {
 	.else
 	.byte		STATIC_KEY_INIT_NOP
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(.data, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key
 	.popsection
@@ -101,7 +103,7 @@ struct jump_entry {
 	.long		\target - .Lstatic_jump_after_\@
 .Lstatic_jump_after_\@:
 	.endif
-	.pushsection __jump_table, "aw"
+	push_section_tbl_any(.data, __jump_table, aw)
 	_ASM_ALIGN
 	_ASM_PTR	.Lstatic_jump_\@, \target, \key + 1
 	.popsection
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 8a5325d75932..887d844f0406 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -216,11 +216,6 @@
 	*(.data.unlikely)						\
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
-	/* implement dynamic printk debug */				\
-	. = ALIGN(8);                                                   \
-	VMLINUX_SYMBOL(__start___jump_table) = .;                       \
-	KEEP(*(__jump_table))                                           \
-	VMLINUX_SYMBOL(__stop___jump_table) = .;                        \
 	. = ALIGN(8);							\
 	VMLINUX_SYMBOL(__start___verbose) = .;                          \
 	KEEP(*(__verbose))                                              \
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index b63d6b7b0db0..e6277888b558 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -117,6 +117,7 @@ enum jump_label_type {
 struct module;
 
 #ifdef HAVE_JUMP_LABEL
+#include <linux/tables.h>
 
 #define JUMP_TYPE_FALSE	0UL
 #define JUMP_TYPE_TRUE	1UL
@@ -132,8 +133,7 @@ static __always_inline bool static_key_true(struct static_key *key)
 	return !arch_static_branch(key, true);
 }
 
-extern struct jump_entry __start___jump_table[];
-extern struct jump_entry __stop___jump_table[];
+DECLARE_LINKTABLE(struct jump_entry, __jump_table);
 
 extern void jump_label_init(void);
 extern void jump_label_lock(void);
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 93ad6c1fb9b6..4252f17eaeb5 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -15,9 +15,12 @@
 #include <linux/static_key.h>
 #include <linux/jump_label_ratelimit.h>
 #include <linux/bug.h>
+#include <linux/tables.h>
 
 #ifdef HAVE_JUMP_LABEL
 
+DEFINE_LINKTABLE(struct jump_entry, __jump_table);
+
 /* mutex to protect coming/going of the the jump_label table */
 static DEFINE_MUTEX(jump_label_mutex);
 
@@ -274,8 +277,6 @@ static void __jump_label_update(struct static_key *key,
 
 void __init jump_label_init(void)
 {
-	struct jump_entry *iter_start = __start___jump_table;
-	struct jump_entry *iter_stop = __stop___jump_table;
 	struct static_key *key = NULL;
 	struct jump_entry *iter;
 
@@ -292,9 +293,10 @@ void __init jump_label_init(void)
 		return;
 
 	jump_label_lock();
-	jump_label_sort_entries(iter_start, iter_stop);
+	jump_label_sort_entries(LINKTABLE_START(__jump_table),
+				LINKTABLE_END(__jump_table));
 
-	for (iter = iter_start; iter < iter_stop; iter++) {
+	linktable_for_each(iter, __jump_table) {
 		struct static_key *iterk;
 
 		/* rewrite NOPs */
@@ -539,8 +541,9 @@ early_initcall(jump_label_init_module);
  */
 int jump_label_text_reserved(void *start, void *end)
 {
-	int ret = __jump_label_text_reserved(__start___jump_table,
-			__stop___jump_table, start, end);
+	int ret = __jump_label_text_reserved(LINKTABLE_START(__jump_table),
+					     LINKTABLE_END(__jump_table),
+					     start, end);
 
 	if (ret)
 		return ret;
@@ -553,7 +556,7 @@ int jump_label_text_reserved(void *start, void *end)
 
 static void jump_label_update(struct static_key *key)
 {
-	struct jump_entry *stop = __stop___jump_table;
+	struct jump_entry *stop = LINKTABLE_END(__jump_table);
 	struct jump_entry *entry = static_key_entries(key);
 #ifdef CONFIG_MODULES
 	struct module *mod;
diff --git a/scripts/module-common.lds b/scripts/module-common.lds
index 73a2c7da0e55..db0e724556c5 100644
--- a/scripts/module-common.lds
+++ b/scripts/module-common.lds
@@ -16,6 +16,7 @@ SECTIONS {
 	__kcrctab_unused	0 : { *(SORT(___kcrctab_unused+*)) }
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
+	__jump_table		0 : { *(SORT(.data..tbl.__jump_table.*)) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
diff --git a/tools/objtool/special.c b/tools/objtool/special.c
index bff8abb3a4aa..79968e118294 100644
--- a/tools/objtool/special.c
+++ b/tools/objtool/special.c
@@ -63,7 +63,7 @@ struct special_entry entries[] = {
 		.feature = ALT_FEATURE_OFFSET,
 	},
 	{
-		.sec = "__jump_table",
+		.sec = ".data..tbl.__jump_table.any",
 		.jump_or_nop = true,
 		.size = JUMP_ENTRY_SIZE,
 		.orig = JUMP_ORIG_OFFSET,
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 10/14] dynamic_debug: port to use linker tables
  2017-01-15 21:10         ` Luis R. Rodriguez
  (?)
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This removes the custom vmlinux.lds.h hacks and uses
the generalized solution for .data entries.

There is much more potential for further fine tuning here
in the future though. For instance, linker tables enable
an extra postfix for order level annotations, this could
easily be used as the KBUILD_MODNAME and with a bit of
linker table changes we may be able to get a direct O(1)
count of the entries for that KBUILD_MODNAME: it would
just be a count on the number of entries for the given
order level. This should help make dynamic_debug_init()
cleaner and also reduce the amount of time it takes at
boot time. Instead of iterating over each print until we
have all for a KBUILD_MODNAME, we'd instead directly
operate on each KBUILD_MODNAME directly. We can work on
this later to make this change easier to review.

Tested dynamic debug with dyndbg query and debugfs control
and it works as expected, for both built-in code and modules.

v6: rename table macro as suggested by Andy Shevchenko

v5:

o Use ..tbl instead of .tbl as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names,
  use LINKTABLE_EMPTY(), LINKTABLE_START()

v4: fix compilation on blackfin
v3: added modular support
v2: introduced this patch into the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/asm-generic/vmlinux.lds.h |  4 ----
 include/linux/dynamic_debug.h     |  5 +++--
 lib/dynamic_debug.c               | 13 ++++++-------
 scripts/module-common.lds         |  1 +
 4 files changed, 10 insertions(+), 13 deletions(-)

diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 887d844f0406..37b99537d5a9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -216,10 +216,6 @@
 	*(.data.unlikely)						\
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
-	. = ALIGN(8);							\
-	VMLINUX_SYMBOL(__start___verbose) = .;                          \
-	KEEP(*(__verbose))                                              \
-	VMLINUX_SYMBOL(__stop___verbose) = .;				\
 	LIKELY_PROFILE()		       				\
 	BRANCH_PROFILE()						\
 	TRACE_PRINTKS()							\
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 546d68057e3b..a52618a77b09 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -4,6 +4,7 @@
 #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
 #include <linux/jump_label.h>
 #endif
+#include <linux/tables.h>
 
 /*
  * An instance of this structure is created in a special
@@ -50,6 +51,7 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
 				const char *modname);
 
 #if defined(CONFIG_DYNAMIC_DEBUG)
+DECLARE_LINKTABLE(struct _ddebug, __verbose);
 extern int ddebug_remove_module(const char *mod_name);
 extern __printf(2, 3)
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
@@ -71,8 +73,7 @@ void __dynamic_netdev_dbg(struct _ddebug *descriptor,
 			  const char *fmt, ...);
 
 #define DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, key, init)	\
-	static struct _ddebug  __aligned(8)			\
-	__attribute__((section("__verbose"))) name = {		\
+	static LINKTABLE(__verbose, SECTION_ORDER_ANY) name = {	\
 		.modname = KBUILD_MODNAME,			\
 		.function = __func__,				\
 		.filename = __FILE__,				\
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index da796e2dc4f5..27a335e3b1f3 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -37,8 +37,7 @@
 #include <linux/device.h>
 #include <linux/netdevice.h>
 
-extern struct _ddebug __start___verbose[];
-extern struct _ddebug __stop___verbose[];
+DEFINE_LINKTABLE(struct _ddebug, __verbose);
 
 struct ddebug_table {
 	struct list_head link;
@@ -978,14 +977,14 @@ static int __init dynamic_debug_init(void)
 	int n = 0, entries = 0, modct = 0;
 	int verbose_bytes = 0;
 
-	if (__start___verbose = __stop___verbose) {
-		pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
+	if (LINKTABLE_EMPTY(__verbose)) {
+		pr_warn("dynamic debug linker table empty on CONFIG_DYNAMIC_DEBUG build\n");
 		return 1;
 	}
-	iter = __start___verbose;
+	iter = LINKTABLE_START(__verbose);
 	modname = iter->modname;
 	iter_start = iter;
-	for (; iter < __stop___verbose; iter++) {
+	linktable_for_each(iter, __verbose) {
 		entries++;
 		verbose_bytes += strlen(iter->modname) + strlen(iter->function)
 			+ strlen(iter->filename) + strlen(iter->format);
@@ -1008,7 +1007,7 @@ static int __init dynamic_debug_init(void)
 	ddebug_init_success = 1;
 	vpr_info("%d modules, %d entries and %d bytes in ddebug tables, %d bytes in (readonly) verbose section\n",
 		 modct, entries, (int)(modct * sizeof(struct ddebug_table)),
-		 verbose_bytes + (int)(__stop___verbose - __start___verbose));
+		 verbose_bytes + (int)(LINKTABLE_SIZE(__verbose)));
 
 	/* apply ddebug_query boot param, dont unload tables on err */
 	if (ddebug_setup_string[0] != '\0') {
diff --git a/scripts/module-common.lds b/scripts/module-common.lds
index db0e724556c5..25755d458f09 100644
--- a/scripts/module-common.lds
+++ b/scripts/module-common.lds
@@ -17,6 +17,7 @@ SECTIONS {
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
 	__jump_table		0 : { *(SORT(.data..tbl.__jump_table.*)) }
+	__verbose		0 : { *(SORT(.data..tbl.__verbose.*)) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 10/14] dynamic_debug: port to use linker tables
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This removes the custom vmlinux.lds.h hacks and uses
the generalized solution for .data entries.

There is much more potential for further fine tuning here
in the future though. For instance, linker tables enable
an extra postfix for order level annotations, this could
easily be used as the KBUILD_MODNAME and with a bit of
linker table changes we may be able to get a direct O(1)
count of the entries for that KBUILD_MODNAME: it would
just be a count on the number of entries for the given
order level. This should help make dynamic_debug_init()
cleaner and also reduce the amount of time it takes at
boot time. Instead of iterating over each print until we
have all for a KBUILD_MODNAME, we'd instead directly
operate on each KBUILD_MODNAME directly. We can work on
this later to make this change easier to review.

Tested dynamic debug with dyndbg query and debugfs control
and it works as expected, for both built-in code and modules.

v6: rename table macro as suggested by Andy Shevchenko

v5:

o Use ..tbl instead of .tbl as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names,
  use LINKTABLE_EMPTY(), LINKTABLE_START()

v4: fix compilation on blackfin
v3: added modular support
v2: introduced this patch into the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/asm-generic/vmlinux.lds.h |  4 ----
 include/linux/dynamic_debug.h     |  5 +++--
 lib/dynamic_debug.c               | 13 ++++++-------
 scripts/module-common.lds         |  1 +
 4 files changed, 10 insertions(+), 13 deletions(-)

diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 887d844f0406..37b99537d5a9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -216,10 +216,6 @@
 	*(.data.unlikely)						\
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
-	. = ALIGN(8);							\
-	VMLINUX_SYMBOL(__start___verbose) = .;                          \
-	KEEP(*(__verbose))                                              \
-	VMLINUX_SYMBOL(__stop___verbose) = .;				\
 	LIKELY_PROFILE()		       				\
 	BRANCH_PROFILE()						\
 	TRACE_PRINTKS()							\
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 546d68057e3b..a52618a77b09 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -4,6 +4,7 @@
 #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
 #include <linux/jump_label.h>
 #endif
+#include <linux/tables.h>
 
 /*
  * An instance of this structure is created in a special
@@ -50,6 +51,7 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
 				const char *modname);
 
 #if defined(CONFIG_DYNAMIC_DEBUG)
+DECLARE_LINKTABLE(struct _ddebug, __verbose);
 extern int ddebug_remove_module(const char *mod_name);
 extern __printf(2, 3)
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
@@ -71,8 +73,7 @@ void __dynamic_netdev_dbg(struct _ddebug *descriptor,
 			  const char *fmt, ...);
 
 #define DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, key, init)	\
-	static struct _ddebug  __aligned(8)			\
-	__attribute__((section("__verbose"))) name = {		\
+	static LINKTABLE(__verbose, SECTION_ORDER_ANY) name = {	\
 		.modname = KBUILD_MODNAME,			\
 		.function = __func__,				\
 		.filename = __FILE__,				\
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index da796e2dc4f5..27a335e3b1f3 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -37,8 +37,7 @@
 #include <linux/device.h>
 #include <linux/netdevice.h>
 
-extern struct _ddebug __start___verbose[];
-extern struct _ddebug __stop___verbose[];
+DEFINE_LINKTABLE(struct _ddebug, __verbose);
 
 struct ddebug_table {
 	struct list_head link;
@@ -978,14 +977,14 @@ static int __init dynamic_debug_init(void)
 	int n = 0, entries = 0, modct = 0;
 	int verbose_bytes = 0;
 
-	if (__start___verbose == __stop___verbose) {
-		pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
+	if (LINKTABLE_EMPTY(__verbose)) {
+		pr_warn("dynamic debug linker table empty on CONFIG_DYNAMIC_DEBUG build\n");
 		return 1;
 	}
-	iter = __start___verbose;
+	iter = LINKTABLE_START(__verbose);
 	modname = iter->modname;
 	iter_start = iter;
-	for (; iter < __stop___verbose; iter++) {
+	linktable_for_each(iter, __verbose) {
 		entries++;
 		verbose_bytes += strlen(iter->modname) + strlen(iter->function)
 			+ strlen(iter->filename) + strlen(iter->format);
@@ -1008,7 +1007,7 @@ static int __init dynamic_debug_init(void)
 	ddebug_init_success = 1;
 	vpr_info("%d modules, %d entries and %d bytes in ddebug tables, %d bytes in (readonly) verbose section\n",
 		 modct, entries, (int)(modct * sizeof(struct ddebug_table)),
-		 verbose_bytes + (int)(__stop___verbose - __start___verbose));
+		 verbose_bytes + (int)(LINKTABLE_SIZE(__verbose)));
 
 	/* apply ddebug_query boot param, dont unload tables on err */
 	if (ddebug_setup_string[0] != '\0') {
diff --git a/scripts/module-common.lds b/scripts/module-common.lds
index db0e724556c5..25755d458f09 100644
--- a/scripts/module-common.lds
+++ b/scripts/module-common.lds
@@ -17,6 +17,7 @@ SECTIONS {
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
 	__jump_table		0 : { *(SORT(.data..tbl.__jump_table.*)) }
+	__verbose		0 : { *(SORT(.data..tbl.__verbose.*)) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 10/14] dynamic_debug: port to use linker tables
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez, Barry Song, Mike Frysinger, Michael Matz,
	Fengguang Wu

This removes the custom vmlinux.lds.h hacks and uses
the generalized solution for .data entries.

There is much more potential for further fine tuning here
in the future though. For instance, linker tables enable
an extra postfix for order level annotations, this could
easily be used as the KBUILD_MODNAME and with a bit of
linker table changes we may be able to get a direct O(1)
count of the entries for that KBUILD_MODNAME: it would
just be a count on the number of entries for the given
order level. This should help make dynamic_debug_init()
cleaner and also reduce the amount of time it takes at
boot time. Instead of iterating over each print until we
have all for a KBUILD_MODNAME, we'd instead directly
operate on each KBUILD_MODNAME directly. We can work on
this later to make this change easier to review.

Tested dynamic debug with dyndbg query and debugfs control
and it works as expected, for both built-in code and modules.

v6: rename table macro as suggested by Andy Shevchenko

v5:

o Use ..tbl instead of .tbl as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names,
  use LINKTABLE_EMPTY(), LINKTABLE_START()

v4: fix compilation on blackfin
v3: added modular support
v2: introduced this patch into the series

Cc: Barry Song <barry.song@analog.com>
Cc: Mike Frysinger <vapier@gentoo.org>
Cc: Steven Miao <realmz6@gmail.com>
Cc: Michael Matz <matz@suse.de>
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 include/asm-generic/vmlinux.lds.h |  4 ----
 include/linux/dynamic_debug.h     |  5 +++--
 lib/dynamic_debug.c               | 13 ++++++-------
 scripts/module-common.lds         |  1 +
 4 files changed, 10 insertions(+), 13 deletions(-)

diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 887d844f0406..37b99537d5a9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -216,10 +216,6 @@
 	*(.data.unlikely)						\
 	STRUCT_ALIGN();							\
 	*(__tracepoints)						\
-	. = ALIGN(8);							\
-	VMLINUX_SYMBOL(__start___verbose) = .;                          \
-	KEEP(*(__verbose))                                              \
-	VMLINUX_SYMBOL(__stop___verbose) = .;				\
 	LIKELY_PROFILE()		       				\
 	BRANCH_PROFILE()						\
 	TRACE_PRINTKS()							\
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 546d68057e3b..a52618a77b09 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -4,6 +4,7 @@
 #if defined(CC_HAVE_ASM_GOTO) && defined(CONFIG_JUMP_LABEL)
 #include <linux/jump_label.h>
 #endif
+#include <linux/tables.h>
 
 /*
  * An instance of this structure is created in a special
@@ -50,6 +51,7 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
 				const char *modname);
 
 #if defined(CONFIG_DYNAMIC_DEBUG)
+DECLARE_LINKTABLE(struct _ddebug, __verbose);
 extern int ddebug_remove_module(const char *mod_name);
 extern __printf(2, 3)
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...);
@@ -71,8 +73,7 @@ void __dynamic_netdev_dbg(struct _ddebug *descriptor,
 			  const char *fmt, ...);
 
 #define DEFINE_DYNAMIC_DEBUG_METADATA_KEY(name, fmt, key, init)	\
-	static struct _ddebug  __aligned(8)			\
-	__attribute__((section("__verbose"))) name = {		\
+	static LINKTABLE(__verbose, SECTION_ORDER_ANY) name = {	\
 		.modname = KBUILD_MODNAME,			\
 		.function = __func__,				\
 		.filename = __FILE__,				\
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index da796e2dc4f5..27a335e3b1f3 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -37,8 +37,7 @@
 #include <linux/device.h>
 #include <linux/netdevice.h>
 
-extern struct _ddebug __start___verbose[];
-extern struct _ddebug __stop___verbose[];
+DEFINE_LINKTABLE(struct _ddebug, __verbose);
 
 struct ddebug_table {
 	struct list_head link;
@@ -978,14 +977,14 @@ static int __init dynamic_debug_init(void)
 	int n = 0, entries = 0, modct = 0;
 	int verbose_bytes = 0;
 
-	if (__start___verbose == __stop___verbose) {
-		pr_warn("_ddebug table is empty in a CONFIG_DYNAMIC_DEBUG build\n");
+	if (LINKTABLE_EMPTY(__verbose)) {
+		pr_warn("dynamic debug linker table empty on CONFIG_DYNAMIC_DEBUG build\n");
 		return 1;
 	}
-	iter = __start___verbose;
+	iter = LINKTABLE_START(__verbose);
 	modname = iter->modname;
 	iter_start = iter;
-	for (; iter < __stop___verbose; iter++) {
+	linktable_for_each(iter, __verbose) {
 		entries++;
 		verbose_bytes += strlen(iter->modname) + strlen(iter->function)
 			+ strlen(iter->filename) + strlen(iter->format);
@@ -1008,7 +1007,7 @@ static int __init dynamic_debug_init(void)
 	ddebug_init_success = 1;
 	vpr_info("%d modules, %d entries and %d bytes in ddebug tables, %d bytes in (readonly) verbose section\n",
 		 modct, entries, (int)(modct * sizeof(struct ddebug_table)),
-		 verbose_bytes + (int)(__stop___verbose - __start___verbose));
+		 verbose_bytes + (int)(LINKTABLE_SIZE(__verbose)));
 
 	/* apply ddebug_query boot param, dont unload tables on err */
 	if (ddebug_setup_string[0] != '\0') {
diff --git a/scripts/module-common.lds b/scripts/module-common.lds
index db0e724556c5..25755d458f09 100644
--- a/scripts/module-common.lds
+++ b/scripts/module-common.lds
@@ -17,6 +17,7 @@ SECTIONS {
 	__kcrctab_unused_gpl	0 : { *(SORT(___kcrctab_unused_gpl+*)) }
 	__kcrctab_gpl_future	0 : { *(SORT(___kcrctab_gpl_future+*)) }
 	__jump_table		0 : { *(SORT(.data..tbl.__jump_table.*)) }
+	__verbose		0 : { *(SORT(.data..tbl.__verbose.*)) }
 
 	. = ALIGN(8);
 	.init_array		0 : { *(SORT(.init_array.*)) *(.init_array) }
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 11/14] kprobes: move kprobe declarations to asm-generic/kprobes.h
  2017-01-15 21:10         ` Luis R. Rodriguez
  (?)
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Often all is needed is these small helpers, instead of compiler.h
or a full kprobes.h. This is important for asm helpers, in fact even
some asm/kprobes.h make use of these helpers... instead just keep a
generic asm file with helpers useful for asm code with the least amount
of clutter as possible.

Likewise we need now to also address what to do about this file for both
when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
for when architectures have CONFIG_HAVE_KPROBES but have disabled
CONFIG_KPROBES.

Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
this means most architecture code cannot include asm/kprobes.h safely.
Correct this and add guards for architectures missing them. Additionally
provide architectures that not have kprobes support with the default
asm-generic solution. This lets us force asm/kprobes.h on the header
include/linux/kprobes.h always, but most importantly we can now safely
include just asm/kprobes.h on architecture code without bringing
the full kitchen sink of header files.

Two architectures already provided a guard against CONFIG_KPROBES on
its kprobes.h: sh, arch. The rest of the architectures needed gaurds
added. We avoid including any not-needed headers on asm/kprobes.h
unless kprobes have been enabled.

In a subsequent atomic change we can try now to remove compiler.h from
include/linux/kprobes.h.

During this sweep I've also identified a few architectures defining
a common macro needed for both kprobes and ftrace, that of the
definition of the breakput instruction up. Some refer to this as
BREAKPOINT_INSTRUCTION. This must be kept outside of the #ifdef
CONFIG_KPROBES guard.

v5:

o fix BREAKPOINT_INSTRUCTION dependency with kernel architecture
  ftrace implementations:  Although its correct to #ifdef CONFIG_KPROBES
  on the architecture arch/$(ARCH)/include/asm/kprobes.h when
  architectures support ftrace they will rely on the
  BREAKPOINT_INSTRUCTION definition, this needs to be kept out from
  CONFIG_KPROBES as ftrace can be enabled without kprobes. This
  fixes compilation on x86 where kprobes is disabled but ftrace is
  left enabled.

o include <asm/kprobes.h> on arch/arm64/kernel/probes/decode-insn.h

v4: introduced this patch into the series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 MAINTAINERS                            |  1 +
 arch/alpha/include/asm/Kbuild          |  1 +
 arch/arc/include/asm/kprobes.h         |  6 ++++--
 arch/arm/include/asm/kprobes.h         |  4 ++++
 arch/arm/probes/decode.h               |  1 +
 arch/arm64/include/asm/kprobes.h       |  4 ++++
 arch/arm64/kernel/insn.c               |  1 +
 arch/arm64/kernel/probes/decode-insn.h |  2 ++
 arch/avr32/include/asm/kprobes.h       |  7 ++++++-
 arch/blackfin/include/asm/Kbuild       |  1 +
 arch/c6x/include/asm/Kbuild            |  1 +
 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/kprobes.h        | 12 +++++++++---
 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/kprobes.h        |  6 +++++-
 arch/mn10300/include/asm/kprobes.h     |  7 ++++++-
 arch/nios2/include/asm/Kbuild          |  1 +
 arch/openrisc/include/asm/Kbuild       |  1 +
 arch/parisc/include/asm/Kbuild         |  1 +
 arch/powerpc/include/asm/kprobes.h     |  3 +++
 arch/s390/include/asm/kprobes.h        |  7 ++++++-
 arch/score/include/asm/Kbuild          |  1 +
 arch/sh/include/asm/kprobes.h          |  5 ++++-
 arch/sparc/include/asm/kprobes.h       | 10 ++++++++--
 arch/tile/include/asm/kprobes.h        |  6 +++++-
 arch/um/include/asm/Kbuild             |  1 +
 arch/unicore32/include/asm/Kbuild      |  1 +
 arch/x86/include/asm/kprobes.h         |  9 ++++++++-
 arch/xtensa/include/asm/Kbuild         |  1 +
 include/asm-generic/kprobes.h          | 25 +++++++++++++++++++++++++
 include/linux/compiler.h               |  8 --------
 include/linux/kprobes.h                | 19 +++----------------
 38 files changed, 123 insertions(+), 38 deletions(-)
 create mode 100644 include/asm-generic/kprobes.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 99ca436e76d9..cee1efd50e04 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7250,6 +7250,7 @@ M:	Masami Hiramatsu <mhiramat@kernel.org>
 S:	Maintained
 F:	Documentation/kprobes.txt
 F:	include/linux/kprobes.h
+F:	include/asm-generic/kprobes.h
 F:	kernel/kprobes.c
 
 KS0108 LCD CONTROLLER DRIVER
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index f3bdc31d3c97..54d388fd026f 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += trace_clock.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/arc/include/asm/kprobes.h b/arch/arc/include/asm/kprobes.h
index 944dbedb38b5..00bdbe167615 100644
--- a/arch/arc/include/asm/kprobes.h
+++ b/arch/arc/include/asm/kprobes.h
@@ -9,6 +9,8 @@
 #ifndef _ARC_KPROBES_H
 #define _ARC_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
 #ifdef CONFIG_KPROBES
 
 typedef u16 kprobe_opcode_t;
@@ -55,6 +57,6 @@ void trap_is_kprobe(unsigned long address, struct pt_regs *regs);
 static void trap_is_kprobe(unsigned long address, struct pt_regs *regs)
 {
 }
-#endif
+#endif /* CONFIG_KPROBES */
 
-#endif
+#endif /* _ARC_KPROBES_H */
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index 3ea9be559726..59655459da59 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/notifier.h>
@@ -83,4 +86,5 @@ struct arch_optimized_insn {
 	 */
 };
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm/probes/decode.h b/arch/arm/probes/decode.h
index f9b08ba7fe73..548d622a3159 100644
--- a/arch/arm/probes/decode.h
+++ b/arch/arm/probes/decode.h
@@ -22,6 +22,7 @@
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <asm/probes.h>
+#include <asm/kprobes.h>
 
 void __init arm_probes_decode_init(void);
 
diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
index 1737aecfcc5e..6deb8d726041 100644
--- a/arch/arm64/include/asm/kprobes.h
+++ b/arch/arm64/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -57,4 +60,5 @@ int kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr);
 void kretprobe_trampoline(void);
 void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 022d4a9d1738..4e02fd369bf9 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -31,6 +31,7 @@
 #include <asm/debug-monitors.h>
 #include <asm/fixmap.h>
 #include <asm/insn.h>
+#include <asm/kprobes.h>
 
 #define AARCH64_INSN_SF_BIT	BIT(31)
 #define AARCH64_INSN_N_BIT	BIT(22)
diff --git a/arch/arm64/kernel/probes/decode-insn.h b/arch/arm64/kernel/probes/decode-insn.h
index 76d3f315407f..192ab007bacb 100644
--- a/arch/arm64/kernel/probes/decode-insn.h
+++ b/arch/arm64/kernel/probes/decode-insn.h
@@ -16,6 +16,8 @@
 #ifndef _ARM_KERNEL_KPROBES_ARM64_H
 #define _ARM_KERNEL_KPROBES_ARM64_H
 
+#include <asm/kprobes.h>
+
 /*
  * ARM strongly recommends a limit of 128 bytes between LoadExcl and
  * StoreExcl instructions in a single thread of execution. So keep the
diff --git a/arch/avr32/include/asm/kprobes.h b/arch/avr32/include/asm/kprobes.h
index 45f563ed73fd..28dfc61ad384 100644
--- a/arch/avr32/include/asm/kprobes.h
+++ b/arch/avr32/include/asm/kprobes.h
@@ -11,10 +11,14 @@
 #ifndef __ASM_AVR32_KPROBES_H
 #define __ASM_AVR32_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xd673	/* breakpoint */
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 
 typedef u16	kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xd673	/* breakpoint */
 #define MAX_INSN_SIZE		2
 #define MAX_STACK_SIZE		64	/* 32 would probably be OK */
 
@@ -46,4 +50,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif /* __ASM_AVR32_KPROBES_H */
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 9115b215fc7e..52351d3fd36e 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -50,3 +50,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index cede2a950fbf..c54f7cc1f63e 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
+generic-y += kprobes.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 7062c1be7913..051d355feae3 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 4a59cbda5091..b58b9fc49383 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index d79968d93c12..cfca7de52b37 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -78,3 +78,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index d59ac1c1858b..d7cc35451f30 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/ia64/include/asm/kprobes.h b/arch/ia64/include/asm/kprobes.h
index d5505d6f2382..0302b3664789 100644
--- a/arch/ia64/include/asm/kprobes.h
+++ b/arch/ia64/include/asm/kprobes.h
@@ -23,14 +23,19 @@
  * 2005-Apr     Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
  *              <anil.s.keshavamurthy@intel.com> adapted from i386
  */
+#include <asm-generic/kprobes.h>
+#include <asm/break.h>
+
+#define BREAK_INST	(long)(__IA64_BREAK_KPROBE << 6)
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
-#include <asm/break.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
 #define MAX_INSN_SIZE   2	/* last half is for kprobe-booster */
-#define BREAK_INST	(long)(__IA64_BREAK_KPROBE << 6)
 #define NOP_M_INST	(long)(1<<27)
 #define BRL_INST(i1, i2) ((long)((0xcL << 37) |	/* brl */ \
 				(0x1L << 12) |	/* many */ \
@@ -124,4 +129,5 @@ extern void invalidate_stacked_regs(void);
 extern void flush_register_stack(void);
 extern void arch_remove_kprobe(struct kprobe *p);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index f3f1e51dd5be..60024b49b6bb 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -15,3 +15,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index c28bcdecc764..412dd23ab946 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -37,3 +37,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index c836f7e2a5e7..8371cc9b1b3c 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -58,3 +58,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index 01afb1b420f5..865ce3d96443 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/mips/include/asm/kprobes.h b/arch/mips/include/asm/kprobes.h
index daba1f9a4f79..291846d9ba83 100644
--- a/arch/mips/include/asm/kprobes.h
+++ b/arch/mips/include/asm/kprobes.h
@@ -22,6 +22,9 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/ptrace.h>
 #include <linux/types.h>
 
@@ -94,4 +97,5 @@ struct kprobe_ctlblk {
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/mn10300/include/asm/kprobes.h b/arch/mn10300/include/asm/kprobes.h
index c800b590183a..7abea0bdb549 100644
--- a/arch/mn10300/include/asm/kprobes.h
+++ b/arch/mn10300/include/asm/kprobes.h
@@ -21,13 +21,17 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xff
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 
 struct kprobe;
 
 typedef unsigned char kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xff
 #define MAX_INSN_SIZE 8
 #define MAX_STACK_SIZE 128
 
@@ -47,4 +51,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 extern void arch_remove_kprobe(struct kprobe *p);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_KPROBES_H */
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index ee6220dac1e8..d6ce7edee7e0 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -66,3 +66,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index ceafe458e295..1bf89a67317c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -74,3 +74,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index aaae8a9f6099..19d5b7e12ecf 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -31,3 +31,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h
index 97b8c1f83453..c7ee3fcbd6e2 100644
--- a/arch/powerpc/include/asm/kprobes.h
+++ b/arch/powerpc/include/asm/kprobes.h
@@ -1,5 +1,8 @@
 #ifndef _ASM_POWERPC_KPROBES_H
 #define _ASM_POWERPC_KPROBES_H
+
+#include <asm-generic/kprobes.h>
+
 #ifdef __KERNEL__
 /*
  *  Kernel Probes (KProbes)
diff --git a/arch/s390/include/asm/kprobes.h b/arch/s390/include/asm/kprobes.h
index 591e5a5279b0..84c0f9086483 100644
--- a/arch/s390/include/asm/kprobes.h
+++ b/arch/s390/include/asm/kprobes.h
@@ -27,6 +27,11 @@
  * 2005-Dec	Used as a template for s390 by Mike Grundy
  *		<grundym@us.ibm.com>
  */
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0x0002
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -37,7 +42,6 @@ struct pt_regs;
 struct kprobe;
 
 typedef u16 kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0x0002
 
 /* Maximum instruction size is 3 (16bit) halfwords: */
 #define MAX_INSN_SIZE		0x0003
@@ -91,4 +95,5 @@ int probe_is_insn_relative_long(u16 *insn);
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif	/* _ASM_S390_KPROBES_H */
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index 16ea15a3e432..6ac8a7f5c768 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -17,3 +17,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h
index 134f3980e44a..f0986f9b3844 100644
--- a/arch/sh/include/asm/kprobes.h
+++ b/arch/sh/include/asm/kprobes.h
@@ -1,13 +1,16 @@
 #ifndef __ASM_SH_KPROBES_H
 #define __ASM_SH_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xc33a
+
 #ifdef CONFIG_KPROBES
 
 #include <linux/types.h>
 #include <linux/ptrace.h>
 
 typedef insn_size_t kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xc33a
 
 #define MAX_INSN_SIZE 16
 #define MAX_STACK_SIZE 64
diff --git a/arch/sparc/include/asm/kprobes.h b/arch/sparc/include/asm/kprobes.h
index a145d798e112..49f8402035d7 100644
--- a/arch/sparc/include/asm/kprobes.h
+++ b/arch/sparc/include/asm/kprobes.h
@@ -1,13 +1,17 @@
 #ifndef _SPARC64_KPROBES_H
 #define _SPARC64_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION   0x91d02070 /* ta 0x70 */
+#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/percpu.h>
 
 typedef u32 kprobe_opcode_t;
 
-#define BREAKPOINT_INSTRUCTION   0x91d02070 /* ta 0x70 */
-#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
 #define MAX_INSN_SIZE 2
 
 #define kretprobe_blacklist_size 0
@@ -48,4 +52,6 @@ int kprobe_exceptions_notify(struct notifier_block *self,
 int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
 				      struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _SPARC64_KPROBES_H */
diff --git a/arch/tile/include/asm/kprobes.h b/arch/tile/include/asm/kprobes.h
index d8f9a83943b1..4a8b1cadca24 100644
--- a/arch/tile/include/asm/kprobes.h
+++ b/arch/tile/include/asm/kprobes.h
@@ -17,10 +17,13 @@
 #ifndef _ASM_TILE_KPROBES_H
 #define _ASM_TILE_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
-
 #include <arch/opcode.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
@@ -76,4 +79,5 @@ void arch_remove_kprobe(struct kprobe *);
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 			     unsigned long val, void *data);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_TILE_KPROBES_H */
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index d2867aa09e23..ccc5ffeaeef5 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 6671a1f08ead..5aacafb6d385 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h
index d1d1e5094c28..200581691c6e 100644
--- a/arch/x86/include/asm/kprobes.h
+++ b/arch/x86/include/asm/kprobes.h
@@ -21,6 +21,12 @@
  *
  * See arch/x86/kernel/kprobes.c for x86 kprobes history.
  */
+
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xcc
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -32,7 +38,6 @@ struct pt_regs;
 struct kprobe;
 
 typedef u8 kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xcc
 #define RELATIVEJUMP_OPCODE 0xe9
 #define RELATIVEJUMP_SIZE 5
 #define RELATIVECALL_OPCODE 0xe8
@@ -116,4 +121,6 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 extern int kprobe_int3_handler(struct pt_regs *regs);
 extern int kprobe_debug_handler(struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_X86_KPROBES_H */
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index 7b41f32a2ba0..20f524ded00e 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
new file mode 100644
index 000000000000..57af9f21d148
--- /dev/null
+++ b/include/asm-generic/kprobes.h
@@ -0,0 +1,25 @@
+#ifndef _ASM_GENERIC_KPROBES_H
+#define _ASM_GENERIC_KPROBES_H
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#ifdef CONFIG_KPROBES
+/*
+ * Blacklist ganerating macro. Specify functions which is not probed
+ * by using this macro.
+ */
+# define __NOKPROBE_SYMBOL(fname)				\
+static unsigned long __used					\
+	__attribute__((__section__("_kprobe_blacklist")))	\
+	_kbl_addr_##fname = (unsigned long)fname;
+# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
+/* Use this to forbid a kprobes attach on very low level functions */
+# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define nokprobe_inline	__always_inline
+#else
+# define NOKPROBE_SYMBOL(fname)
+# define __kprobes
+# define nokprobe_inline	inline
+#endif
+#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
+
+#endif /* _ASM_GENERIC_KPROBES_H */
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index cf0fa5d86059..dca49b4099da 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -566,12 +566,4 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 	(_________p1); \
 })
 
-/* Ignore/forbid kprobes attach on very low level functions marked by this attribute: */
-#ifdef CONFIG_KPROBES
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
-# define nokprobe_inline	__always_inline
-#else
-# define __kprobes
-# define nokprobe_inline	inline
-#endif
 #endif /* __LINUX_COMPILER_H */
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 8f6849084248..985ed79ef431 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -29,7 +29,7 @@
  *		<jkenisto@us.ibm.com>  and Prasanna S Panchamukhi
  *		<prasanna@in.ibm.com> added function-return probes.
  */
-#include <linux/compiler.h>	/* for __kprobes */
+#include <linux/compiler.h>
 #include <linux/linkage.h>
 #include <linux/list.h>
 #include <linux/notifier.h>
@@ -40,9 +40,9 @@
 #include <linux/rcupdate.h>
 #include <linux/mutex.h>
 #include <linux/ftrace.h>
+#include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
-#include <asm/kprobes.h>
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
@@ -51,6 +51,7 @@
 #define KPROBE_HIT_SSDONE	0x00000008
 
 #else /* CONFIG_KPROBES */
+#include <asm-generic/kprobes.h>
 typedef int kprobe_opcode_t;
 struct arch_specific_insn {
 	int dummy;
@@ -481,18 +482,4 @@ static inline int enable_jprobe(struct jprobe *jp)
 	return enable_kprobe(&jp->kp);
 }
 
-#ifdef CONFIG_KPROBES
-/*
- * Blacklist ganerating macro. Specify functions which is not probed
- * by using this macro.
- */
-#define __NOKPROBE_SYMBOL(fname)			\
-static unsigned long __used				\
-	__attribute__((section("_kprobe_blacklist")))	\
-	_kbl_addr_##fname = (unsigned long)fname;
-#define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
-#else
-#define NOKPROBE_SYMBOL(fname)
-#endif
-
 #endif /* _LINUX_KPROBES_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 11/14] kprobes: move kprobe declarations to asm-generic/kprobes.h
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Often all is needed is these small helpers, instead of compiler.h
or a full kprobes.h. This is important for asm helpers, in fact even
some asm/kprobes.h make use of these helpers... instead just keep a
generic asm file with helpers useful for asm code with the least amount
of clutter as possible.

Likewise we need now to also address what to do about this file for both
when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
for when architectures have CONFIG_HAVE_KPROBES but have disabled
CONFIG_KPROBES.

Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
this means most architecture code cannot include asm/kprobes.h safely.
Correct this and add guards for architectures missing them. Additionally
provide architectures that not have kprobes support with the default
asm-generic solution. This lets us force asm/kprobes.h on the header
include/linux/kprobes.h always, but most importantly we can now safely
include just asm/kprobes.h on architecture code without bringing
the full kitchen sink of header files.

Two architectures already provided a guard against CONFIG_KPROBES on
its kprobes.h: sh, arch. The rest of the architectures needed gaurds
added. We avoid including any not-needed headers on asm/kprobes.h
unless kprobes have been enabled.

In a subsequent atomic change we can try now to remove compiler.h from
include/linux/kprobes.h.

During this sweep I've also identified a few architectures defining
a common macro needed for both kprobes and ftrace, that of the
definition of the breakput instruction up. Some refer to this as
BREAKPOINT_INSTRUCTION. This must be kept outside of the #ifdef
CONFIG_KPROBES guard.

v5:

o fix BREAKPOINT_INSTRUCTION dependency with kernel architecture
  ftrace implementations:  Although its correct to #ifdef CONFIG_KPROBES
  on the architecture arch/$(ARCH)/include/asm/kprobes.h when
  architectures support ftrace they will rely on the
  BREAKPOINT_INSTRUCTION definition, this needs to be kept out from
  CONFIG_KPROBES as ftrace can be enabled without kprobes. This
  fixes compilation on x86 where kprobes is disabled but ftrace is
  left enabled.

o include <asm/kprobes.h> on arch/arm64/kernel/probes/decode-insn.h

v4: introduced this patch into the series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 MAINTAINERS                            |  1 +
 arch/alpha/include/asm/Kbuild          |  1 +
 arch/arc/include/asm/kprobes.h         |  6 ++++--
 arch/arm/include/asm/kprobes.h         |  4 ++++
 arch/arm/probes/decode.h               |  1 +
 arch/arm64/include/asm/kprobes.h       |  4 ++++
 arch/arm64/kernel/insn.c               |  1 +
 arch/arm64/kernel/probes/decode-insn.h |  2 ++
 arch/avr32/include/asm/kprobes.h       |  7 ++++++-
 arch/blackfin/include/asm/Kbuild       |  1 +
 arch/c6x/include/asm/Kbuild            |  1 +
 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/kprobes.h        | 12 +++++++++---
 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/kprobes.h        |  6 +++++-
 arch/mn10300/include/asm/kprobes.h     |  7 ++++++-
 arch/nios2/include/asm/Kbuild          |  1 +
 arch/openrisc/include/asm/Kbuild       |  1 +
 arch/parisc/include/asm/Kbuild         |  1 +
 arch/powerpc/include/asm/kprobes.h     |  3 +++
 arch/s390/include/asm/kprobes.h        |  7 ++++++-
 arch/score/include/asm/Kbuild          |  1 +
 arch/sh/include/asm/kprobes.h          |  5 ++++-
 arch/sparc/include/asm/kprobes.h       | 10 ++++++++--
 arch/tile/include/asm/kprobes.h        |  6 +++++-
 arch/um/include/asm/Kbuild             |  1 +
 arch/unicore32/include/asm/Kbuild      |  1 +
 arch/x86/include/asm/kprobes.h         |  9 ++++++++-
 arch/xtensa/include/asm/Kbuild         |  1 +
 include/asm-generic/kprobes.h          | 25 +++++++++++++++++++++++++
 include/linux/compiler.h               |  8 --------
 include/linux/kprobes.h                | 19 +++----------------
 38 files changed, 123 insertions(+), 38 deletions(-)
 create mode 100644 include/asm-generic/kprobes.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 99ca436e76d9..cee1efd50e04 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7250,6 +7250,7 @@ M:	Masami Hiramatsu <mhiramat@kernel.org>
 S:	Maintained
 F:	Documentation/kprobes.txt
 F:	include/linux/kprobes.h
+F:	include/asm-generic/kprobes.h
 F:	kernel/kprobes.c
 
 KS0108 LCD CONTROLLER DRIVER
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index f3bdc31d3c97..54d388fd026f 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += trace_clock.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/arc/include/asm/kprobes.h b/arch/arc/include/asm/kprobes.h
index 944dbedb38b5..00bdbe167615 100644
--- a/arch/arc/include/asm/kprobes.h
+++ b/arch/arc/include/asm/kprobes.h
@@ -9,6 +9,8 @@
 #ifndef _ARC_KPROBES_H
 #define _ARC_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
 #ifdef CONFIG_KPROBES
 
 typedef u16 kprobe_opcode_t;
@@ -55,6 +57,6 @@ void trap_is_kprobe(unsigned long address, struct pt_regs *regs);
 static void trap_is_kprobe(unsigned long address, struct pt_regs *regs)
 {
 }
-#endif
+#endif /* CONFIG_KPROBES */
 
-#endif
+#endif /* _ARC_KPROBES_H */
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index 3ea9be559726..59655459da59 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/notifier.h>
@@ -83,4 +86,5 @@ struct arch_optimized_insn {
 	 */
 };
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm/probes/decode.h b/arch/arm/probes/decode.h
index f9b08ba7fe73..548d622a3159 100644
--- a/arch/arm/probes/decode.h
+++ b/arch/arm/probes/decode.h
@@ -22,6 +22,7 @@
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <asm/probes.h>
+#include <asm/kprobes.h>
 
 void __init arm_probes_decode_init(void);
 
diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
index 1737aecfcc5e..6deb8d726041 100644
--- a/arch/arm64/include/asm/kprobes.h
+++ b/arch/arm64/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -57,4 +60,5 @@ int kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr);
 void kretprobe_trampoline(void);
 void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 022d4a9d1738..4e02fd369bf9 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -31,6 +31,7 @@
 #include <asm/debug-monitors.h>
 #include <asm/fixmap.h>
 #include <asm/insn.h>
+#include <asm/kprobes.h>
 
 #define AARCH64_INSN_SF_BIT	BIT(31)
 #define AARCH64_INSN_N_BIT	BIT(22)
diff --git a/arch/arm64/kernel/probes/decode-insn.h b/arch/arm64/kernel/probes/decode-insn.h
index 76d3f315407f..192ab007bacb 100644
--- a/arch/arm64/kernel/probes/decode-insn.h
+++ b/arch/arm64/kernel/probes/decode-insn.h
@@ -16,6 +16,8 @@
 #ifndef _ARM_KERNEL_KPROBES_ARM64_H
 #define _ARM_KERNEL_KPROBES_ARM64_H
 
+#include <asm/kprobes.h>
+
 /*
  * ARM strongly recommends a limit of 128 bytes between LoadExcl and
  * StoreExcl instructions in a single thread of execution. So keep the
diff --git a/arch/avr32/include/asm/kprobes.h b/arch/avr32/include/asm/kprobes.h
index 45f563ed73fd..28dfc61ad384 100644
--- a/arch/avr32/include/asm/kprobes.h
+++ b/arch/avr32/include/asm/kprobes.h
@@ -11,10 +11,14 @@
 #ifndef __ASM_AVR32_KPROBES_H
 #define __ASM_AVR32_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xd673	/* breakpoint */
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 
 typedef u16	kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xd673	/* breakpoint */
 #define MAX_INSN_SIZE		2
 #define MAX_STACK_SIZE		64	/* 32 would probably be OK */
 
@@ -46,4 +50,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif /* __ASM_AVR32_KPROBES_H */
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 9115b215fc7e..52351d3fd36e 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -50,3 +50,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index cede2a950fbf..c54f7cc1f63e 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
+generic-y += kprobes.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 7062c1be7913..051d355feae3 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 4a59cbda5091..b58b9fc49383 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index d79968d93c12..cfca7de52b37 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -78,3 +78,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index d59ac1c1858b..d7cc35451f30 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/ia64/include/asm/kprobes.h b/arch/ia64/include/asm/kprobes.h
index d5505d6f2382..0302b3664789 100644
--- a/arch/ia64/include/asm/kprobes.h
+++ b/arch/ia64/include/asm/kprobes.h
@@ -23,14 +23,19 @@
  * 2005-Apr     Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
  *              <anil.s.keshavamurthy@intel.com> adapted from i386
  */
+#include <asm-generic/kprobes.h>
+#include <asm/break.h>
+
+#define BREAK_INST	(long)(__IA64_BREAK_KPROBE << 6)
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
-#include <asm/break.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
 #define MAX_INSN_SIZE   2	/* last half is for kprobe-booster */
-#define BREAK_INST	(long)(__IA64_BREAK_KPROBE << 6)
 #define NOP_M_INST	(long)(1<<27)
 #define BRL_INST(i1, i2) ((long)((0xcL << 37) |	/* brl */ \
 				(0x1L << 12) |	/* many */ \
@@ -124,4 +129,5 @@ extern void invalidate_stacked_regs(void);
 extern void flush_register_stack(void);
 extern void arch_remove_kprobe(struct kprobe *p);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index f3f1e51dd5be..60024b49b6bb 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -15,3 +15,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index c28bcdecc764..412dd23ab946 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -37,3 +37,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index c836f7e2a5e7..8371cc9b1b3c 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -58,3 +58,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index 01afb1b420f5..865ce3d96443 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/mips/include/asm/kprobes.h b/arch/mips/include/asm/kprobes.h
index daba1f9a4f79..291846d9ba83 100644
--- a/arch/mips/include/asm/kprobes.h
+++ b/arch/mips/include/asm/kprobes.h
@@ -22,6 +22,9 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/ptrace.h>
 #include <linux/types.h>
 
@@ -94,4 +97,5 @@ struct kprobe_ctlblk {
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/mn10300/include/asm/kprobes.h b/arch/mn10300/include/asm/kprobes.h
index c800b590183a..7abea0bdb549 100644
--- a/arch/mn10300/include/asm/kprobes.h
+++ b/arch/mn10300/include/asm/kprobes.h
@@ -21,13 +21,17 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xff
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 
 struct kprobe;
 
 typedef unsigned char kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xff
 #define MAX_INSN_SIZE 8
 #define MAX_STACK_SIZE 128
 
@@ -47,4 +51,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 extern void arch_remove_kprobe(struct kprobe *p);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_KPROBES_H */
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index ee6220dac1e8..d6ce7edee7e0 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -66,3 +66,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index ceafe458e295..1bf89a67317c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -74,3 +74,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index aaae8a9f6099..19d5b7e12ecf 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -31,3 +31,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h
index 97b8c1f83453..c7ee3fcbd6e2 100644
--- a/arch/powerpc/include/asm/kprobes.h
+++ b/arch/powerpc/include/asm/kprobes.h
@@ -1,5 +1,8 @@
 #ifndef _ASM_POWERPC_KPROBES_H
 #define _ASM_POWERPC_KPROBES_H
+
+#include <asm-generic/kprobes.h>
+
 #ifdef __KERNEL__
 /*
  *  Kernel Probes (KProbes)
diff --git a/arch/s390/include/asm/kprobes.h b/arch/s390/include/asm/kprobes.h
index 591e5a5279b0..84c0f9086483 100644
--- a/arch/s390/include/asm/kprobes.h
+++ b/arch/s390/include/asm/kprobes.h
@@ -27,6 +27,11 @@
  * 2005-Dec	Used as a template for s390 by Mike Grundy
  *		<grundym@us.ibm.com>
  */
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0x0002
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -37,7 +42,6 @@ struct pt_regs;
 struct kprobe;
 
 typedef u16 kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0x0002
 
 /* Maximum instruction size is 3 (16bit) halfwords: */
 #define MAX_INSN_SIZE		0x0003
@@ -91,4 +95,5 @@ int probe_is_insn_relative_long(u16 *insn);
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif	/* _ASM_S390_KPROBES_H */
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index 16ea15a3e432..6ac8a7f5c768 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -17,3 +17,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h
index 134f3980e44a..f0986f9b3844 100644
--- a/arch/sh/include/asm/kprobes.h
+++ b/arch/sh/include/asm/kprobes.h
@@ -1,13 +1,16 @@
 #ifndef __ASM_SH_KPROBES_H
 #define __ASM_SH_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xc33a
+
 #ifdef CONFIG_KPROBES
 
 #include <linux/types.h>
 #include <linux/ptrace.h>
 
 typedef insn_size_t kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xc33a
 
 #define MAX_INSN_SIZE 16
 #define MAX_STACK_SIZE 64
diff --git a/arch/sparc/include/asm/kprobes.h b/arch/sparc/include/asm/kprobes.h
index a145d798e112..49f8402035d7 100644
--- a/arch/sparc/include/asm/kprobes.h
+++ b/arch/sparc/include/asm/kprobes.h
@@ -1,13 +1,17 @@
 #ifndef _SPARC64_KPROBES_H
 #define _SPARC64_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION   0x91d02070 /* ta 0x70 */
+#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/percpu.h>
 
 typedef u32 kprobe_opcode_t;
 
-#define BREAKPOINT_INSTRUCTION   0x91d02070 /* ta 0x70 */
-#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
 #define MAX_INSN_SIZE 2
 
 #define kretprobe_blacklist_size 0
@@ -48,4 +52,6 @@ int kprobe_exceptions_notify(struct notifier_block *self,
 int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
 				      struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _SPARC64_KPROBES_H */
diff --git a/arch/tile/include/asm/kprobes.h b/arch/tile/include/asm/kprobes.h
index d8f9a83943b1..4a8b1cadca24 100644
--- a/arch/tile/include/asm/kprobes.h
+++ b/arch/tile/include/asm/kprobes.h
@@ -17,10 +17,13 @@
 #ifndef _ASM_TILE_KPROBES_H
 #define _ASM_TILE_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
-
 #include <arch/opcode.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
@@ -76,4 +79,5 @@ void arch_remove_kprobe(struct kprobe *);
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 			     unsigned long val, void *data);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_TILE_KPROBES_H */
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index d2867aa09e23..ccc5ffeaeef5 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 6671a1f08ead..5aacafb6d385 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h
index d1d1e5094c28..200581691c6e 100644
--- a/arch/x86/include/asm/kprobes.h
+++ b/arch/x86/include/asm/kprobes.h
@@ -21,6 +21,12 @@
  *
  * See arch/x86/kernel/kprobes.c for x86 kprobes history.
  */
+
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xcc
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -32,7 +38,6 @@ struct pt_regs;
 struct kprobe;
 
 typedef u8 kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xcc
 #define RELATIVEJUMP_OPCODE 0xe9
 #define RELATIVEJUMP_SIZE 5
 #define RELATIVECALL_OPCODE 0xe8
@@ -116,4 +121,6 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 extern int kprobe_int3_handler(struct pt_regs *regs);
 extern int kprobe_debug_handler(struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_X86_KPROBES_H */
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index 7b41f32a2ba0..20f524ded00e 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
new file mode 100644
index 000000000000..57af9f21d148
--- /dev/null
+++ b/include/asm-generic/kprobes.h
@@ -0,0 +1,25 @@
+#ifndef _ASM_GENERIC_KPROBES_H
+#define _ASM_GENERIC_KPROBES_H
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#ifdef CONFIG_KPROBES
+/*
+ * Blacklist ganerating macro. Specify functions which is not probed
+ * by using this macro.
+ */
+# define __NOKPROBE_SYMBOL(fname)				\
+static unsigned long __used					\
+	__attribute__((__section__("_kprobe_blacklist")))	\
+	_kbl_addr_##fname = (unsigned long)fname;
+# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
+/* Use this to forbid a kprobes attach on very low level functions */
+# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define nokprobe_inline	__always_inline
+#else
+# define NOKPROBE_SYMBOL(fname)
+# define __kprobes
+# define nokprobe_inline	inline
+#endif
+#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
+
+#endif /* _ASM_GENERIC_KPROBES_H */
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index cf0fa5d86059..dca49b4099da 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -566,12 +566,4 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 	(_________p1); \
 })
 
-/* Ignore/forbid kprobes attach on very low level functions marked by this attribute: */
-#ifdef CONFIG_KPROBES
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
-# define nokprobe_inline	__always_inline
-#else
-# define __kprobes
-# define nokprobe_inline	inline
-#endif
 #endif /* __LINUX_COMPILER_H */
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 8f6849084248..985ed79ef431 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -29,7 +29,7 @@
  *		<jkenisto@us.ibm.com>  and Prasanna S Panchamukhi
  *		<prasanna@in.ibm.com> added function-return probes.
  */
-#include <linux/compiler.h>	/* for __kprobes */
+#include <linux/compiler.h>
 #include <linux/linkage.h>
 #include <linux/list.h>
 #include <linux/notifier.h>
@@ -40,9 +40,9 @@
 #include <linux/rcupdate.h>
 #include <linux/mutex.h>
 #include <linux/ftrace.h>
+#include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
-#include <asm/kprobes.h>
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
@@ -51,6 +51,7 @@
 #define KPROBE_HIT_SSDONE	0x00000008
 
 #else /* CONFIG_KPROBES */
+#include <asm-generic/kprobes.h>
 typedef int kprobe_opcode_t;
 struct arch_specific_insn {
 	int dummy;
@@ -481,18 +482,4 @@ static inline int enable_jprobe(struct jprobe *jp)
 	return enable_kprobe(&jp->kp);
 }
 
-#ifdef CONFIG_KPROBES
-/*
- * Blacklist ganerating macro. Specify functions which is not probed
- * by using this macro.
- */
-#define __NOKPROBE_SYMBOL(fname)			\
-static unsigned long __used				\
-	__attribute__((section("_kprobe_blacklist")))	\
-	_kbl_addr_##fname = (unsigned long)fname;
-#define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
-#else
-#define NOKPROBE_SYMBOL(fname)
-#endif
-
 #endif /* _LINUX_KPROBES_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 11/14] kprobes: move kprobe declarations to asm-generic/kprobes.h
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

Often all is needed is these small helpers, instead of compiler.h
or a full kprobes.h. This is important for asm helpers, in fact even
some asm/kprobes.h make use of these helpers... instead just keep a
generic asm file with helpers useful for asm code with the least amount
of clutter as possible.

Likewise we need now to also address what to do about this file for both
when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
for when architectures have CONFIG_HAVE_KPROBES but have disabled
CONFIG_KPROBES.

Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
this means most architecture code cannot include asm/kprobes.h safely.
Correct this and add guards for architectures missing them. Additionally
provide architectures that not have kprobes support with the default
asm-generic solution. This lets us force asm/kprobes.h on the header
include/linux/kprobes.h always, but most importantly we can now safely
include just asm/kprobes.h on architecture code without bringing
the full kitchen sink of header files.

Two architectures already provided a guard against CONFIG_KPROBES on
its kprobes.h: sh, arch. The rest of the architectures needed gaurds
added. We avoid including any not-needed headers on asm/kprobes.h
unless kprobes have been enabled.

In a subsequent atomic change we can try now to remove compiler.h from
include/linux/kprobes.h.

During this sweep I've also identified a few architectures defining
a common macro needed for both kprobes and ftrace, that of the
definition of the breakput instruction up. Some refer to this as
BREAKPOINT_INSTRUCTION. This must be kept outside of the #ifdef
CONFIG_KPROBES guard.

v5:

o fix BREAKPOINT_INSTRUCTION dependency with kernel architecture
  ftrace implementations:  Although its correct to #ifdef CONFIG_KPROBES
  on the architecture arch/$(ARCH)/include/asm/kprobes.h when
  architectures support ftrace they will rely on the
  BREAKPOINT_INSTRUCTION definition, this needs to be kept out from
  CONFIG_KPROBES as ftrace can be enabled without kprobes. This
  fixes compilation on x86 where kprobes is disabled but ftrace is
  left enabled.

o include <asm/kprobes.h> on arch/arm64/kernel/probes/decode-insn.h

v4: introduced this patch into the series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 MAINTAINERS                            |  1 +
 arch/alpha/include/asm/Kbuild          |  1 +
 arch/arc/include/asm/kprobes.h         |  6 ++++--
 arch/arm/include/asm/kprobes.h         |  4 ++++
 arch/arm/probes/decode.h               |  1 +
 arch/arm64/include/asm/kprobes.h       |  4 ++++
 arch/arm64/kernel/insn.c               |  1 +
 arch/arm64/kernel/probes/decode-insn.h |  2 ++
 arch/avr32/include/asm/kprobes.h       |  7 ++++++-
 arch/blackfin/include/asm/Kbuild       |  1 +
 arch/c6x/include/asm/Kbuild            |  1 +
 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/kprobes.h        | 12 +++++++++---
 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/kprobes.h        |  6 +++++-
 arch/mn10300/include/asm/kprobes.h     |  7 ++++++-
 arch/nios2/include/asm/Kbuild          |  1 +
 arch/openrisc/include/asm/Kbuild       |  1 +
 arch/parisc/include/asm/Kbuild         |  1 +
 arch/powerpc/include/asm/kprobes.h     |  3 +++
 arch/s390/include/asm/kprobes.h        |  7 ++++++-
 arch/score/include/asm/Kbuild          |  1 +
 arch/sh/include/asm/kprobes.h          |  5 ++++-
 arch/sparc/include/asm/kprobes.h       | 10 ++++++++--
 arch/tile/include/asm/kprobes.h        |  6 +++++-
 arch/um/include/asm/Kbuild             |  1 +
 arch/unicore32/include/asm/Kbuild      |  1 +
 arch/x86/include/asm/kprobes.h         |  9 ++++++++-
 arch/xtensa/include/asm/Kbuild         |  1 +
 include/asm-generic/kprobes.h          | 25 +++++++++++++++++++++++++
 include/linux/compiler.h               |  8 --------
 include/linux/kprobes.h                | 19 +++----------------
 38 files changed, 123 insertions(+), 38 deletions(-)
 create mode 100644 include/asm-generic/kprobes.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 99ca436e76d9..cee1efd50e04 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7250,6 +7250,7 @@ M:	Masami Hiramatsu <mhiramat@kernel.org>
 S:	Maintained
 F:	Documentation/kprobes.txt
 F:	include/linux/kprobes.h
+F:	include/asm-generic/kprobes.h
 F:	kernel/kprobes.c
 
 KS0108 LCD CONTROLLER DRIVER
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild
index f3bdc31d3c97..54d388fd026f 100644
--- a/arch/alpha/include/asm/Kbuild
+++ b/arch/alpha/include/asm/Kbuild
@@ -13,3 +13,4 @@ generic-y += trace_clock.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/arc/include/asm/kprobes.h b/arch/arc/include/asm/kprobes.h
index 944dbedb38b5..00bdbe167615 100644
--- a/arch/arc/include/asm/kprobes.h
+++ b/arch/arc/include/asm/kprobes.h
@@ -9,6 +9,8 @@
 #ifndef _ARC_KPROBES_H
 #define _ARC_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
 #ifdef CONFIG_KPROBES
 
 typedef u16 kprobe_opcode_t;
@@ -55,6 +57,6 @@ void trap_is_kprobe(unsigned long address, struct pt_regs *regs);
 static void trap_is_kprobe(unsigned long address, struct pt_regs *regs)
 {
 }
-#endif
+#endif /* CONFIG_KPROBES */
 
-#endif
+#endif /* _ARC_KPROBES_H */
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index 3ea9be559726..59655459da59 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/notifier.h>
@@ -83,4 +86,5 @@ struct arch_optimized_insn {
 	 */
 };
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm/probes/decode.h b/arch/arm/probes/decode.h
index f9b08ba7fe73..548d622a3159 100644
--- a/arch/arm/probes/decode.h
+++ b/arch/arm/probes/decode.h
@@ -22,6 +22,7 @@
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <asm/probes.h>
+#include <asm/kprobes.h>
 
 void __init arm_probes_decode_init(void);
 
diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
index 1737aecfcc5e..6deb8d726041 100644
--- a/arch/arm64/include/asm/kprobes.h
+++ b/arch/arm64/include/asm/kprobes.h
@@ -16,6 +16,9 @@
 #ifndef _ARM_KPROBES_H
 #define _ARM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -57,4 +60,5 @@ int kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr);
 void kretprobe_trampoline(void);
 void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ARM_KPROBES_H */
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index 022d4a9d1738..4e02fd369bf9 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -31,6 +31,7 @@
 #include <asm/debug-monitors.h>
 #include <asm/fixmap.h>
 #include <asm/insn.h>
+#include <asm/kprobes.h>
 
 #define AARCH64_INSN_SF_BIT	BIT(31)
 #define AARCH64_INSN_N_BIT	BIT(22)
diff --git a/arch/arm64/kernel/probes/decode-insn.h b/arch/arm64/kernel/probes/decode-insn.h
index 76d3f315407f..192ab007bacb 100644
--- a/arch/arm64/kernel/probes/decode-insn.h
+++ b/arch/arm64/kernel/probes/decode-insn.h
@@ -16,6 +16,8 @@
 #ifndef _ARM_KERNEL_KPROBES_ARM64_H
 #define _ARM_KERNEL_KPROBES_ARM64_H
 
+#include <asm/kprobes.h>
+
 /*
  * ARM strongly recommends a limit of 128 bytes between LoadExcl and
  * StoreExcl instructions in a single thread of execution. So keep the
diff --git a/arch/avr32/include/asm/kprobes.h b/arch/avr32/include/asm/kprobes.h
index 45f563ed73fd..28dfc61ad384 100644
--- a/arch/avr32/include/asm/kprobes.h
+++ b/arch/avr32/include/asm/kprobes.h
@@ -11,10 +11,14 @@
 #ifndef __ASM_AVR32_KPROBES_H
 #define __ASM_AVR32_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xd673	/* breakpoint */
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 
 typedef u16	kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xd673	/* breakpoint */
 #define MAX_INSN_SIZE		2
 #define MAX_STACK_SIZE		64	/* 32 would probably be OK */
 
@@ -46,4 +50,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif /* __ASM_AVR32_KPROBES_H */
diff --git a/arch/blackfin/include/asm/Kbuild b/arch/blackfin/include/asm/Kbuild
index 9115b215fc7e..52351d3fd36e 100644
--- a/arch/blackfin/include/asm/Kbuild
+++ b/arch/blackfin/include/asm/Kbuild
@@ -50,3 +50,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild
index cede2a950fbf..c54f7cc1f63e 100644
--- a/arch/c6x/include/asm/Kbuild
+++ b/arch/c6x/include/asm/Kbuild
@@ -64,3 +64,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
+generic-y += kprobes.h
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 7062c1be7913..051d355feae3 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -48,3 +48,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild
index 4a59cbda5091..b58b9fc49383 100644
--- a/arch/frv/include/asm/Kbuild
+++ b/arch/frv/include/asm/Kbuild
@@ -11,3 +11,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index d79968d93c12..cfca7de52b37 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -78,3 +78,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/hexagon/include/asm/Kbuild b/arch/hexagon/include/asm/Kbuild
index d59ac1c1858b..d7cc35451f30 100644
--- a/arch/hexagon/include/asm/Kbuild
+++ b/arch/hexagon/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/ia64/include/asm/kprobes.h b/arch/ia64/include/asm/kprobes.h
index d5505d6f2382..0302b3664789 100644
--- a/arch/ia64/include/asm/kprobes.h
+++ b/arch/ia64/include/asm/kprobes.h
@@ -23,14 +23,19 @@
  * 2005-Apr     Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
  *              <anil.s.keshavamurthy@intel.com> adapted from i386
  */
+#include <asm-generic/kprobes.h>
+#include <asm/break.h>
+
+#define BREAK_INST	(long)(__IA64_BREAK_KPROBE << 6)
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
-#include <asm/break.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
 #define MAX_INSN_SIZE   2	/* last half is for kprobe-booster */
-#define BREAK_INST	(long)(__IA64_BREAK_KPROBE << 6)
 #define NOP_M_INST	(long)(1<<27)
 #define BRL_INST(i1, i2) ((long)((0xcL << 37) |	/* brl */ \
 				(0x1L << 12) |	/* many */ \
@@ -124,4 +129,5 @@ extern void invalidate_stacked_regs(void);
 extern void flush_register_stack(void);
 extern void arch_remove_kprobe(struct kprobe *p);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild
index f3f1e51dd5be..60024b49b6bb 100644
--- a/arch/m32r/include/asm/Kbuild
+++ b/arch/m32r/include/asm/Kbuild
@@ -15,3 +15,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild
index c28bcdecc764..412dd23ab946 100644
--- a/arch/m68k/include/asm/Kbuild
+++ b/arch/m68k/include/asm/Kbuild
@@ -37,3 +37,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/metag/include/asm/Kbuild b/arch/metag/include/asm/Kbuild
index c836f7e2a5e7..8371cc9b1b3c 100644
--- a/arch/metag/include/asm/Kbuild
+++ b/arch/metag/include/asm/Kbuild
@@ -58,3 +58,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild
index 01afb1b420f5..865ce3d96443 100644
--- a/arch/microblaze/include/asm/Kbuild
+++ b/arch/microblaze/include/asm/Kbuild
@@ -14,3 +14,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/mips/include/asm/kprobes.h b/arch/mips/include/asm/kprobes.h
index daba1f9a4f79..291846d9ba83 100644
--- a/arch/mips/include/asm/kprobes.h
+++ b/arch/mips/include/asm/kprobes.h
@@ -22,6 +22,9 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
 #include <linux/ptrace.h>
 #include <linux/types.h>
 
@@ -94,4 +97,5 @@ struct kprobe_ctlblk {
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 
-#endif				/* _ASM_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _ASM_KPROBES_H */
diff --git a/arch/mn10300/include/asm/kprobes.h b/arch/mn10300/include/asm/kprobes.h
index c800b590183a..7abea0bdb549 100644
--- a/arch/mn10300/include/asm/kprobes.h
+++ b/arch/mn10300/include/asm/kprobes.h
@@ -21,13 +21,17 @@
 #ifndef _ASM_KPROBES_H
 #define _ASM_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xff
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 
 struct kprobe;
 
 typedef unsigned char kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xff
 #define MAX_INSN_SIZE 8
 #define MAX_STACK_SIZE 128
 
@@ -47,4 +51,5 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 
 extern void arch_remove_kprobe(struct kprobe *p);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_KPROBES_H */
diff --git a/arch/nios2/include/asm/Kbuild b/arch/nios2/include/asm/Kbuild
index ee6220dac1e8..d6ce7edee7e0 100644
--- a/arch/nios2/include/asm/Kbuild
+++ b/arch/nios2/include/asm/Kbuild
@@ -66,3 +66,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/openrisc/include/asm/Kbuild b/arch/openrisc/include/asm/Kbuild
index ceafe458e295..1bf89a67317c 100644
--- a/arch/openrisc/include/asm/Kbuild
+++ b/arch/openrisc/include/asm/Kbuild
@@ -74,3 +74,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild
index aaae8a9f6099..19d5b7e12ecf 100644
--- a/arch/parisc/include/asm/Kbuild
+++ b/arch/parisc/include/asm/Kbuild
@@ -31,3 +31,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h
index 97b8c1f83453..c7ee3fcbd6e2 100644
--- a/arch/powerpc/include/asm/kprobes.h
+++ b/arch/powerpc/include/asm/kprobes.h
@@ -1,5 +1,8 @@
 #ifndef _ASM_POWERPC_KPROBES_H
 #define _ASM_POWERPC_KPROBES_H
+
+#include <asm-generic/kprobes.h>
+
 #ifdef __KERNEL__
 /*
  *  Kernel Probes (KProbes)
diff --git a/arch/s390/include/asm/kprobes.h b/arch/s390/include/asm/kprobes.h
index 591e5a5279b0..84c0f9086483 100644
--- a/arch/s390/include/asm/kprobes.h
+++ b/arch/s390/include/asm/kprobes.h
@@ -27,6 +27,11 @@
  * 2005-Dec	Used as a template for s390 by Mike Grundy
  *		<grundym@us.ibm.com>
  */
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0x0002
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -37,7 +42,6 @@ struct pt_regs;
 struct kprobe;
 
 typedef u16 kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0x0002
 
 /* Maximum instruction size is 3 (16bit) halfwords: */
 #define MAX_INSN_SIZE		0x0003
@@ -91,4 +95,5 @@ int probe_is_insn_relative_long(u16 *insn);
 
 #define flush_insn_slot(p)	do { } while (0)
 
+#endif /* CONFIG_KPROBES */
 #endif	/* _ASM_S390_KPROBES_H */
diff --git a/arch/score/include/asm/Kbuild b/arch/score/include/asm/Kbuild
index 16ea15a3e432..6ac8a7f5c768 100644
--- a/arch/score/include/asm/Kbuild
+++ b/arch/score/include/asm/Kbuild
@@ -17,3 +17,4 @@ generic-y += word-at-a-time.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h
index 134f3980e44a..f0986f9b3844 100644
--- a/arch/sh/include/asm/kprobes.h
+++ b/arch/sh/include/asm/kprobes.h
@@ -1,13 +1,16 @@
 #ifndef __ASM_SH_KPROBES_H
 #define __ASM_SH_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xc33a
+
 #ifdef CONFIG_KPROBES
 
 #include <linux/types.h>
 #include <linux/ptrace.h>
 
 typedef insn_size_t kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xc33a
 
 #define MAX_INSN_SIZE 16
 #define MAX_STACK_SIZE 64
diff --git a/arch/sparc/include/asm/kprobes.h b/arch/sparc/include/asm/kprobes.h
index a145d798e112..49f8402035d7 100644
--- a/arch/sparc/include/asm/kprobes.h
+++ b/arch/sparc/include/asm/kprobes.h
@@ -1,13 +1,17 @@
 #ifndef _SPARC64_KPROBES_H
 #define _SPARC64_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION   0x91d02070 /* ta 0x70 */
+#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/percpu.h>
 
 typedef u32 kprobe_opcode_t;
 
-#define BREAKPOINT_INSTRUCTION   0x91d02070 /* ta 0x70 */
-#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
 #define MAX_INSN_SIZE 2
 
 #define kretprobe_blacklist_size 0
@@ -48,4 +52,6 @@ int kprobe_exceptions_notify(struct notifier_block *self,
 int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
 				      struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _SPARC64_KPROBES_H */
diff --git a/arch/tile/include/asm/kprobes.h b/arch/tile/include/asm/kprobes.h
index d8f9a83943b1..4a8b1cadca24 100644
--- a/arch/tile/include/asm/kprobes.h
+++ b/arch/tile/include/asm/kprobes.h
@@ -17,10 +17,13 @@
 #ifndef _ASM_TILE_KPROBES_H
 #define _ASM_TILE_KPROBES_H
 
+#include <asm-generic/kprobes.h>
+
+#ifdef CONFIG_KPROBES
+
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
-
 #include <arch/opcode.h>
 
 #define __ARCH_WANT_KPROBES_INSN_SLOT
@@ -76,4 +79,5 @@ void arch_remove_kprobe(struct kprobe *);
 extern int kprobe_exceptions_notify(struct notifier_block *self,
 			     unsigned long val, void *data);
 
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_TILE_KPROBES_H */
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index d2867aa09e23..ccc5ffeaeef5 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -29,3 +29,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild
index 6671a1f08ead..5aacafb6d385 100644
--- a/arch/unicore32/include/asm/Kbuild
+++ b/arch/unicore32/include/asm/Kbuild
@@ -63,3 +63,4 @@ generic-y += word-at-a-time.h
 generic-y += xor.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h
index d1d1e5094c28..200581691c6e 100644
--- a/arch/x86/include/asm/kprobes.h
+++ b/arch/x86/include/asm/kprobes.h
@@ -21,6 +21,12 @@
  *
  * See arch/x86/kernel/kprobes.c for x86 kprobes history.
  */
+
+#include <asm-generic/kprobes.h>
+
+#define BREAKPOINT_INSTRUCTION	0xcc
+
+#ifdef CONFIG_KPROBES
 #include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
@@ -32,7 +38,6 @@ struct pt_regs;
 struct kprobe;
 
 typedef u8 kprobe_opcode_t;
-#define BREAKPOINT_INSTRUCTION	0xcc
 #define RELATIVEJUMP_OPCODE 0xe9
 #define RELATIVEJUMP_SIZE 5
 #define RELATIVECALL_OPCODE 0xe8
@@ -116,4 +121,6 @@ extern int kprobe_exceptions_notify(struct notifier_block *self,
 				    unsigned long val, void *data);
 extern int kprobe_int3_handler(struct pt_regs *regs);
 extern int kprobe_debug_handler(struct pt_regs *regs);
+
+#endif /* CONFIG_KPROBES */
 #endif /* _ASM_X86_KPROBES_H */
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index 7b41f32a2ba0..20f524ded00e 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -35,3 +35,4 @@ generic-y += xor.h
 generic-y += section-core.h
 generic-y += ranges.h
 generic-y += tables.h
+generic-y += kprobes.h
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
new file mode 100644
index 000000000000..57af9f21d148
--- /dev/null
+++ b/include/asm-generic/kprobes.h
@@ -0,0 +1,25 @@
+#ifndef _ASM_GENERIC_KPROBES_H
+#define _ASM_GENERIC_KPROBES_H
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#ifdef CONFIG_KPROBES
+/*
+ * Blacklist ganerating macro. Specify functions which is not probed
+ * by using this macro.
+ */
+# define __NOKPROBE_SYMBOL(fname)				\
+static unsigned long __used					\
+	__attribute__((__section__("_kprobe_blacklist")))	\
+	_kbl_addr_##fname = (unsigned long)fname;
+# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
+/* Use this to forbid a kprobes attach on very low level functions */
+# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define nokprobe_inline	__always_inline
+#else
+# define NOKPROBE_SYMBOL(fname)
+# define __kprobes
+# define nokprobe_inline	inline
+#endif
+#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
+
+#endif /* _ASM_GENERIC_KPROBES_H */
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index cf0fa5d86059..dca49b4099da 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -566,12 +566,4 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 	(_________p1); \
 })
 
-/* Ignore/forbid kprobes attach on very low level functions marked by this attribute: */
-#ifdef CONFIG_KPROBES
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
-# define nokprobe_inline	__always_inline
-#else
-# define __kprobes
-# define nokprobe_inline	inline
-#endif
 #endif /* __LINUX_COMPILER_H */
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 8f6849084248..985ed79ef431 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -29,7 +29,7 @@
  *		<jkenisto@us.ibm.com>  and Prasanna S Panchamukhi
  *		<prasanna@in.ibm.com> added function-return probes.
  */
-#include <linux/compiler.h>	/* for __kprobes */
+#include <linux/compiler.h>
 #include <linux/linkage.h>
 #include <linux/list.h>
 #include <linux/notifier.h>
@@ -40,9 +40,9 @@
 #include <linux/rcupdate.h>
 #include <linux/mutex.h>
 #include <linux/ftrace.h>
+#include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
-#include <asm/kprobes.h>
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
@@ -51,6 +51,7 @@
 #define KPROBE_HIT_SSDONE	0x00000008
 
 #else /* CONFIG_KPROBES */
+#include <asm-generic/kprobes.h>
 typedef int kprobe_opcode_t;
 struct arch_specific_insn {
 	int dummy;
@@ -481,18 +482,4 @@ static inline int enable_jprobe(struct jprobe *jp)
 	return enable_kprobe(&jp->kp);
 }
 
-#ifdef CONFIG_KPROBES
-/*
- * Blacklist ganerating macro. Specify functions which is not probed
- * by using this macro.
- */
-#define __NOKPROBE_SYMBOL(fname)			\
-static unsigned long __used				\
-	__attribute__((section("_kprobe_blacklist")))	\
-	_kbl_addr_##fname = (unsigned long)fname;
-#define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
-#else
-#define NOKPROBE_SYMBOL(fname)
-#endif
-
 #endif /* _LINUX_KPROBES_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 12/14] kprobes: port .kprobes.text to section range
  2017-01-15 21:10         ` Luis R. Rodriguez
  (?)
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

kprobe makes use of two custom sections, each custom section
is folded into one of the standard Linux sections types as follows,
it currently relies on the linker script to fold the custom section
onto the respective Linux section:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist
range .text         .kprobes.text        __kprobes_text_start     __kprobes_text_end

This ports the .kprobes.text custom section to the standard
Linux ranges API allowing us remove all the custom kprobe section
declarations from the linker script.

Tested with CONFIG_KPROBES_SANITY_TEST, it passes with:

Kprobe smoke test: started
Kprobe smoke test: passed successfully

Then tested CONFIG_SAMPLE_KPROBES on do_fork, and the kprobe bites
and kicks as expected.

Also ran ./ftracetest with no issues:

sudo ./ftracetest
== Ftrace unit tests =[1] Basic trace file check	[PASS]
[2] Basic test for tracers	[PASS]
[3] Basic trace clock test	[PASS]
[4] Basic event tracing check	[PASS]
[5] event tracing - enable/disable with event level files	[PASS]
[6] event tracing - restricts events based on pid	[PASS]
[7] event tracing - enable/disable with subsystem level files	[PASS]
[8] event tracing - enable/disable with top level files	[PASS]
[9] ftrace - function graph filters with stack tracer	[PASS]
[10] ftrace - function graph filters	[PASS]
[11] ftrace - function glob filters	[PASS]
[12] ftrace - function profiler with function tracing	[PASS]
[13] Test creation and deletion of trace instances while setting an event	[PASS]
[14] Test creation and deletion of trace instances	[PASS]
[15] Kprobe dynamic event - adding and removing	[PASS]
[16] Kprobe dynamic event - busy event check	[PASS]
[17] Kprobe dynamic event with arguments	[PASS]
[18] Kprobes event arguments with types	[PASS]
[19] Kprobe dynamic event with function tracer	[PASS]
[20] Kretprobe dynamic event with arguments	[PASS]
[21] event trigger - test event enable/disable trigger	[PASS]
[22] event trigger - test trigger filter	[PASS]
[23] event trigger - test histogram modifiers	[PASS]
[24] event trigger - test histogram trigger	[PASS]
[25] event trigger - test multiple histogram triggers	[PASS]
[26] event trigger - test snapshot-trigger	[PASS]
[27] event trigger - test stacktrace-trigger	[PASS]
[28] event trigger - test traceon/off trigger	[PASS]

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

v4:

o arm64 build fixes with allmodconfig

o build fix suggested for avr32 with allnoconfig, otherwise we end up with:

arch/avr32/kernel/built-in.o: In function `save_full_context_ex':
(.ex.text+0x1c4): relocation truncated to fit: R_AVR32_16N_PCREL against
symbol `debug_trampoline' defined in .text.rng.kprobes.any section in
arch/avr32/kernel/built-in.o
arch/avr32/kernel/built-in.o: In function `debug_exit_work':
(.text.rng.kprobes.any+0xa8): relocation truncated to fit:
R_AVR32_16N_PCREL against `.ex.text'+3aa
make: *** [Makefile:953: vmlinux] Error 1

o open-code section use on scripts/ code -- folks to prefer the
  simplicity over dealing with having more tool code access kernel
  headers.

o NOPE: include #include <asm-generic/ranges.h> on compiler.h -- solves
  a few 0-day compilation issues

v3:

o after v2 arch/arm/kernel/vmlinux-xip.lds.S got kprobe support,
  this just removes the custom linker script reference to kprobes as
  that is no longer needed with linker tables.

o split kprobe linker table and kprobe section ranges use into
  two separate patches. This should make it easier to review and
  also demos both distinct use types, one a linker table another
  a simple section range.

v2: introduced this patch in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arc/kernel/vmlinux.lds.S        |  1 -
 arch/arm/kernel/entry-armv.S         |  3 ++-
 arch/arm/kernel/vmlinux-xip.lds.S    |  1 -
 arch/arm/kernel/vmlinux.lds.S        |  1 -
 arch/arm64/kernel/armv8_deprecated.c |  1 +
 arch/arm64/kernel/probes/kprobes.c   |  4 ++--
 arch/arm64/kernel/vmlinux.lds.S      |  1 -
 arch/avr32/kernel/entry-avr32b.S     | 13 +++++++++++--
 arch/avr32/kernel/vmlinux.lds.S      |  1 -
 arch/blackfin/kernel/vmlinux.lds.S   |  1 -
 arch/c6x/kernel/vmlinux.lds.S        |  1 -
 arch/hexagon/kernel/vmlinux.lds.S    |  1 -
 arch/ia64/kernel/jprobes.S           |  3 ++-
 arch/ia64/kernel/vmlinux.lds.S       |  1 -
 arch/ia64/lib/flush.S                |  6 +++---
 arch/metag/kernel/vmlinux.lds.S      |  1 -
 arch/microblaze/kernel/vmlinux.lds.S |  1 -
 arch/mips/kernel/vmlinux.lds.S       |  1 -
 arch/mn10300/kernel/vmlinux.lds.S    |  1 -
 arch/nios2/kernel/vmlinux.lds.S      |  1 -
 arch/openrisc/kernel/vmlinux.lds.S   |  1 -
 arch/parisc/kernel/vmlinux.lds.S     |  1 -
 arch/powerpc/include/asm/ppc_asm.h   |  1 +
 arch/powerpc/kernel/vmlinux.lds.S    |  1 -
 arch/s390/kernel/entry.S             |  5 +++--
 arch/s390/kernel/kprobes.c           |  6 +++---
 arch/s390/kernel/mcount.S            |  3 ++-
 arch/s390/kernel/vmlinux.lds.S       |  1 -
 arch/score/kernel/vmlinux.lds.S      |  1 -
 arch/sh/kernel/vmlinux.lds.S         |  1 -
 arch/sparc/kernel/vmlinux.lds.S      |  1 -
 arch/sparc/mm/ultra.S                |  3 ++-
 arch/tile/kernel/vmlinux.lds.S       |  1 -
 arch/x86/kernel/kprobes/core.c       | 11 +++++------
 arch/x86/kernel/vmlinux.lds.S        |  1 -
 include/asm-generic/kprobes.h        |  3 ++-
 include/asm-generic/sections.h       |  2 --
 include/asm-generic/vmlinux.lds.h    |  2 +-
 include/linux/kprobes.h              |  3 +++
 kernel/kprobes.c                     |  6 ++++--
 scripts/mod/modpost.c                |  2 +-
 scripts/recordmcount.c               |  2 +-
 scripts/recordmcount.pl              |  2 +-
 43 files changed, 50 insertions(+), 54 deletions(-)

diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S
index f35ed578e007..dd05c86eb96e 100644
--- a/arch/arc/kernel/vmlinux.lds.S
+++ b/arch/arc/kernel/vmlinux.lds.S
@@ -91,7 +91,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 9f157e7c51e7..c455b491b6d3 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -34,6 +34,7 @@
 #include "entry-header.S"
 #include <asm/entry-macro-multi.S>
 #include <asm/probes.h>
+#include <asm/ranges.h>
 
 /*
  * Interrupt handling.
@@ -83,7 +84,7 @@
 	.endm
 
 #ifdef CONFIG_KPROBES
-	.section	.kprobes.text,"ax",%progbits
+	set_section_rng_type(.text, kprobes, ax, %progbits)
 #else
 	.text
 #endif
diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S
index 37b2a11af345..1a84f84b8165 100644
--- a/arch/arm/kernel/vmlinux-xip.lds.S
+++ b/arch/arm/kernel/vmlinux-xip.lds.S
@@ -103,7 +103,6 @@ SECTIONS
 			SCHED_TEXT
 			CPUIDLE_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index f7f55df0bf7b..1e278e6c3506 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -114,7 +114,6 @@ SECTIONS
 			CPUIDLE_TEXT
 			LOCK_TEXT
 			HYPERVISOR_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index 86032a012388..4043a14c9e36 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -21,6 +21,7 @@
 #include <asm/traps.h>
 #include <linux/uaccess.h>
 #include <asm/cpufeature.h>
+#include <asm/kprobes.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace-events-emulation.h"
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index f0593c92279b..ec288dd165cb 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/stop_machine.h>
 #include <linux/stringify.h>
+#include <linux/ranges.h>
 #include <asm/traps.h>
 #include <asm/ptrace.h>
 #include <asm/cacheflush.h>
@@ -540,8 +541,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
-	if ((addr >= (unsigned long)__kprobes_text_start &&
-	    addr < (unsigned long)__kprobes_text_end) ||
+	if (SECTION_RANGE_ADDR_WITHIN(kprobes, addr) ||
 	    (addr >= (unsigned long)__entry_text_start &&
 	    addr < (unsigned long)__entry_text_end) ||
 	    (addr >= (unsigned long)__idmap_text_start &&
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index b8deffa9e1bf..c68e5d528706 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -124,7 +124,6 @@ SECTIONS
 			SCHED_TEXT
 			CPUIDLE_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			HYPERVISOR_TEXT
 			IDMAP_TEXT
 			HIBERNATE_TEXT
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index 7301f4806bbe..7b2a5c5ef047 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -23,6 +23,7 @@
 #include <asm/sysreg.h>
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
+#include <asm/ranges.h>
 
 #ifdef CONFIG_PREEMPT
 # define preempt_stop		mask_interrupts
@@ -605,7 +606,11 @@ fault_exit_work:
 	brcc	fault_resume_user
 	rjmp	enter_monitor_mode
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(.text, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	handle_debug, @function
 handle_debug:
 	sub	sp, 4		/* r12_orig */
@@ -826,7 +831,11 @@ irq_level\level:
 	IRQ_LEVEL 2
 	IRQ_LEVEL 3
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(.text, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	enter_monitor_mode, @function
 enter_monitor_mode:
 	/*
diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S
index 17f2730eb497..04627a9c178e 100644
--- a/arch/avr32/kernel/vmlinux.lds.S
+++ b/arch/avr32/kernel/vmlinux.lds.S
@@ -49,7 +49,6 @@ SECTIONS
 		_stext = .;
 		*(.ex.text)
 		*(.irq.text)
-		KPROBES_TEXT
 		TEXT_TEXT
 		SCHED_TEXT
 		CPUIDLE_TEXT
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 68069a120055..93220ff65014 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -37,7 +37,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 #ifdef CONFIG_ROMKERNEL
 		__sinittext = .;
 		INIT_TEXT
diff --git a/arch/c6x/kernel/vmlinux.lds.S b/arch/c6x/kernel/vmlinux.lds.S
index a1a5c166bc9b..a41d43b8254b 100644
--- a/arch/c6x/kernel/vmlinux.lds.S
+++ b/arch/c6x/kernel/vmlinux.lds.S
@@ -74,7 +74,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S
index ec87e67feb19..7e6f68584b55 100644
--- a/arch/hexagon/kernel/vmlinux.lds.S
+++ b/arch/hexagon/kernel/vmlinux.lds.S
@@ -52,7 +52,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 	}
 	_etext = .;
diff --git a/arch/ia64/kernel/jprobes.S b/arch/ia64/kernel/jprobes.S
index f69389c7be1d..71adc7132e22 100644
--- a/arch/ia64/kernel/jprobes.S
+++ b/arch/ia64/kernel/jprobes.S
@@ -46,11 +46,12 @@
  */
 #include <asm/asmmacro.h>
 #include <asm/break.h>
+#include <asm/ranges.h>
 
 	/*
 	 * void jprobe_break(void)
 	 */
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 ENTRY(jprobe_break)
 	break.m __IA64_BREAK_JPROBE
 END(jprobe_break)
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index f89d20c97412..3ff6edf913d2 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -48,7 +48,6 @@ SECTIONS {
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.gnu.linkonce.t*)
 	}
 
diff --git a/arch/ia64/lib/flush.S b/arch/ia64/lib/flush.S
index 9a5a2f9fad13..dec1b180d618 100644
--- a/arch/ia64/lib/flush.S
+++ b/arch/ia64/lib/flush.S
@@ -9,7 +9,7 @@
 
 #include <asm/asmmacro.h>
 #include <asm/export.h>
-
+#include <asm/ranges.h>
 
 	/*
 	 * flush_icache_range(start,end)
@@ -21,7 +21,7 @@
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(.text, kprobes, ax)
 GLOBAL_ENTRY(flush_icache_range)
 
 	.prologue
@@ -74,7 +74,7 @@ EXPORT_SYMBOL_GPL(flush_icache_range)
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(.text, kprobes, ax)
 GLOBAL_ENTRY(clflush_cache_range)
 
 	.prologue
diff --git a/arch/metag/kernel/vmlinux.lds.S b/arch/metag/kernel/vmlinux.lds.S
index e6c700eaf207..b18386d2250f 100644
--- a/arch/metag/kernel/vmlinux.lds.S
+++ b/arch/metag/kernel/vmlinux.lds.S
@@ -23,7 +23,6 @@ SECTIONS
 	SCHED_TEXT
 	CPUIDLE_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	IRQENTRY_TEXT
 	SOFTIRQENTRY_TEXT
 	*(.text.*)
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
index 289d0e7f3e3a..aadee2229ac6 100644
--- a/arch/microblaze/kernel/vmlinux.lds.S
+++ b/arch/microblaze/kernel/vmlinux.lds.S
@@ -35,7 +35,6 @@ SECTIONS {
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		. = ALIGN (4) ;
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index f0a0e6d62be3..44e21812c544 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -57,7 +57,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.*)
diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S
index 2d5f1c3f1afb..552ef00a3da5 100644
--- a/arch/mn10300/kernel/vmlinux.lds.S
+++ b/arch/mn10300/kernel/vmlinux.lds.S
@@ -32,7 +32,6 @@ SECTIONS
 	SCHED_TEXT
 	CPUIDLE_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0xcb
diff --git a/arch/nios2/kernel/vmlinux.lds.S b/arch/nios2/kernel/vmlinux.lds.S
index 6a8045bb1a77..aae4a00c4056 100644
--- a/arch/nios2/kernel/vmlinux.lds.S
+++ b/arch/nios2/kernel/vmlinux.lds.S
@@ -41,7 +41,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 	} =0
 	_etext = .;
 
diff --git a/arch/openrisc/kernel/vmlinux.lds.S b/arch/openrisc/kernel/vmlinux.lds.S
index 00ddb7804be4..8ade6ccca6ac 100644
--- a/arch/openrisc/kernel/vmlinux.lds.S
+++ b/arch/openrisc/kernel/vmlinux.lds.S
@@ -57,7 +57,6 @@ SECTIONS
 	  SCHED_TEXT
 	  CPUIDLE_TEXT
 	  LOCK_TEXT
-	  KPROBES_TEXT
 	  IRQENTRY_TEXT
 	  SOFTIRQENTRY_TEXT
 	  *(.fixup)
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 3d6ef1b29c6a..edbd6d9487dc 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -71,7 +71,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.do_softirq)
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 025833b8df9f..0846413b3a2e 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,6 +9,7 @@
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
 #include <asm/firmware.h>
+#include <asm/ranges.h>
 
 #ifdef __ASSEMBLY__
 
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 8cd940c72895..2285664abb52 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -112,7 +112,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		MEM_KEEP(init.text)
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 97298c58b2be..847e2e1df89c 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -24,6 +24,7 @@
 #include <asm/setup.h>
 #include <asm/nmi.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
 __PT_R0      =	__PT_GPRS
 __PT_R1      =	__PT_GPRS + 8
@@ -169,7 +170,7 @@ _PIF_WORK	= (_PIF_PER_TRAP)
 		tm	off+\addr, \mask
 	.endm
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 .Ldummy:
 	/*
 	 * This nop exists only in order to avoid that __switch_to starts at
@@ -986,7 +987,7 @@ ENTRY(restart_int_handler)
 	brc	2,2b
 3:	j	3b
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 
 #ifdef CONFIG_CHECK_STACK
 /*
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 84e0557b16fe..94a4918b5968 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -289,9 +289,9 @@ static void kprobe_reenter_check(struct kprobe_ctlblk *kcb, struct kprobe *p)
 	case KPROBE_REENTER:
 	default:
 		/*
-		 * A kprobe on the code path to single step an instruction
-		 * is a BUG. The code path resides in the .kprobes.text
-		 * section and is executed with interrupts disabled.
+		 * A kprobe on the code path to single step an instruction is a
+		 * BUG. The code path resides in the kprobes section range and
+		 * is executed with interrupts disabled.
 		 */
 		printk(KERN_EMERG "Invalid kprobe detected at %p.\n", p->addr);
 		dump_kprobe(p);
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S
index 9a17e4475d27..9d76056609f7 100644
--- a/arch/s390/kernel/mcount.S
+++ b/arch/s390/kernel/mcount.S
@@ -10,8 +10,9 @@
 #include <asm/ftrace.h>
 #include <asm/ptrace.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 
 ENTRY(ftrace_stub)
 	br	%r14
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 3667d20e997f..b2df6d9bab09 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -37,7 +37,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/score/kernel/vmlinux.lds.S b/arch/score/kernel/vmlinux.lds.S
index 4117890b1db1..a8b14f3ed474 100644
--- a/arch/score/kernel/vmlinux.lds.S
+++ b/arch/score/kernel/vmlinux.lds.S
@@ -42,7 +42,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.text.*)
 		*(.fixup)
 		. = ALIGN (4) ;
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 5b9a3cc90c58..58d9ba796f7a 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -38,7 +38,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 572db686f845..0ee41b0071e5 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -51,7 +51,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.gnu.warning)
diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S
index 5d2fd6cd3189..ee9f648549c0 100644
--- a/arch/sparc/mm/ultra.S
+++ b/arch/sparc/mm/ultra.S
@@ -16,6 +16,7 @@
 #include <asm/cacheflush.h>
 #include <asm/hypervisor.h>
 #include <asm/cpudata.h>
+#include <asm/ranges.h>
 
 	/* Basically, most of the Spitfire vs. Cheetah madness
 	 * has to do with the fact that Cheetah does not support
@@ -185,7 +186,7 @@ __spitfire_flush_tlb_mm_slow:
 /*
  * The following code flushes one page_size worth.
  */
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 	.align		32
 	.globl		__flush_icache_page
 __flush_icache_page:	/* %o0 = phys_page */
diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S
index e1baf094fba4..85d03ce6c0a0 100644
--- a/arch/tile/kernel/vmlinux.lds.S
+++ b/arch/tile/kernel/vmlinux.lds.S
@@ -44,7 +44,6 @@ SECTIONS
     SCHED_TEXT
     CPUIDLE_TEXT
     LOCK_TEXT
-    KPROBES_TEXT
     IRQENTRY_TEXT
     SOFTIRQENTRY_TEXT
     __fix_text_end = .;   /* tile-cpack won't rearrange before this */
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index eb3509338ae0..95e4b172e923 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -580,9 +580,9 @@ static int reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
 	case KPROBE_REENTER:
 		/* A probe has been hit in the codepath leading up to, or just
 		 * after, single-stepping of a probed instruction. This entire
-		 * codepath should strictly reside in .kprobes.text section.
-		 * Raise a BUG or we'll continue in an endless reentering loop
-		 * and eventually a stack overflow.
+		 * codepath should strictly reside in the kprobes section
+		 * range. Raise a BUG or we'll continue in an endless
+		 * reentering loop and eventually a stack overflow.
 		 */
 		printk(KERN_WARNING "Unrecoverable kprobe detected at %p.\n",
 		       p->addr);
@@ -1133,10 +1133,9 @@ NOKPROBE_SYMBOL(longjmp_break_handler);
 
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
-	return  (addr >= (unsigned long)__kprobes_text_start &&
-		 addr < (unsigned long)__kprobes_text_end) ||
+	return  (SECTION_RANGE_ADDR_WITHIN(kprobes, addr) ||
 		(addr >= (unsigned long)__entry_text_start &&
-		 addr < (unsigned long)__entry_text_end);
+		 addr < (unsigned long)__entry_text_end));
 }
 
 int __init arch_init_kprobes(void)
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index e79f15f108a8..4c16fadb9ac6 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -99,7 +99,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		ENTRY_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 57af9f21d148..02a26b975187 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,6 +3,7 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
@@ -13,7 +14,7 @@ static unsigned long __used					\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define __kprobes	__LINUX_RANGE(.text, kprobes)
 # define nokprobe_inline	__always_inline
 #else
 # define NOKPROBE_SYMBOL(fname)
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index b145ae8d9cbe..f3340f2772bb 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -26,7 +26,6 @@
  * Following global variables are optional and may be unavailable on some
  * architectures and/or kernel configurations.
  *	_text, _data
- *	__kprobes_text_start, __kprobes_text_end
  *	__entry_text_start, __entry_text_end
  *	__ctors_start, __ctors_end
  */
@@ -38,7 +37,6 @@ extern char _sinittext[], _einittext[];
 extern char __start_data_ro_after_init[], __end_data_ro_after_init[];
 extern char _end[];
 extern char __per_cpu_load[], __per_cpu_start[], __per_cpu_end[];
-extern char __kprobes_text_start[], __kprobes_text_end[];
 extern char __entry_text_start[], __entry_text_end[];
 extern char __start_rodata[], __end_rodata[];
 
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 37b99537d5a9..499caf5b4361 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -471,7 +471,7 @@
 #define KPROBES_TEXT							\
 		ALIGN_FUNCTION();					\
 		VMLINUX_SYMBOL(__kprobes_text_start) = .;		\
-		*(.kprobes.text)					\
+		*(.text..rng.kprobes.any)				\
 		VMLINUX_SYMBOL(__kprobes_text_end) = .;
 
 #define ENTRY_TEXT							\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 985ed79ef431..445cc6fe7afa 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -43,6 +43,9 @@
 #include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
+#include <linux/ranges.h>
+
+DECLARE_SECTION_RANGE(kprobes);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 43460104f119..82191f328e21 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1328,8 +1328,7 @@ static int register_aggr_kprobe(struct kprobe *orig_p, struct kprobe *p)
 bool __weak arch_within_kprobe_blacklist(unsigned long addr)
 {
 	/* The __kprobes marked functions and entry code must not be probed */
-	return addr >= (unsigned long)__kprobes_text_start &&
-	       addr < (unsigned long)__kprobes_text_end;
+	return SECTION_RANGE_ADDR_WITHIN(kprobes, addr);
 }
 
 bool within_kprobe_blacklist(unsigned long addr)
@@ -2129,6 +2128,9 @@ static struct notifier_block kprobe_module_nb = {
 extern unsigned long __start_kprobe_blacklist[];
 extern unsigned long __stop_kprobe_blacklist[];
 
+/* Actual kprobes section range */
+DEFINE_SECTION_RANGE(kprobes, .text);
+
 static int __init init_kprobes(void)
 {
 	int i, err = 0;
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 29c89a6bad3d..2b442234c69b 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -894,7 +894,7 @@ static void check_section(const char *modname, struct elf_info *elf,
 
 #define DATA_SECTIONS ".data", ".data.rel"
 #define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \
-		".kprobes.text", ".cpuidle.text"
+		".text..rng.kprobes.any", ".cpuidle.text"
 #define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
 		".fixup", ".entry.text", ".exception.text", ".text.*", \
 		".coldtext"
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index aeb34223167c..6e95f3f87db1 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -417,7 +417,7 @@ is_mcounted_section_name(char const *const txtname)
 		strcmp(".spinlock.text", txtname) = 0 ||
 		strcmp(".irqentry.text", txtname) = 0 ||
 		strcmp(".softirqentry.text", txtname) = 0 ||
-		strcmp(".kprobes.text", txtname) = 0 ||
+		strcmp(".text..rng.kprobes.any", txtname) = 0 ||
 		strcmp(".cpuidle.text", txtname) = 0 ||
 		strcmp(".text.unlikely", txtname) = 0;
 }
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 0b6002b36f20..15e2fa37c489 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -135,7 +135,7 @@ my %text_sections = (
      ".spinlock.text" => 1,
      ".irqentry.text" => 1,
      ".softirqentry.text" => 1,
-     ".kprobes.text" => 1,
+     ".text..rng.kprobes.any" => 1,
      ".cpuidle.text" => 1,
      ".text.unlikely" => 1,
 );
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 12/14] kprobes: port .kprobes.text to section range
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

kprobe makes use of two custom sections, each custom section
is folded into one of the standard Linux sections types as follows,
it currently relies on the linker script to fold the custom section
onto the respective Linux section:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist
range .text         .kprobes.text        __kprobes_text_start     __kprobes_text_end

This ports the .kprobes.text custom section to the standard
Linux ranges API allowing us remove all the custom kprobe section
declarations from the linker script.

Tested with CONFIG_KPROBES_SANITY_TEST, it passes with:

Kprobe smoke test: started
Kprobe smoke test: passed successfully

Then tested CONFIG_SAMPLE_KPROBES on do_fork, and the kprobe bites
and kicks as expected.

Also ran ./ftracetest with no issues:

sudo ./ftracetest
=== Ftrace unit tests ===
[1] Basic trace file check	[PASS]
[2] Basic test for tracers	[PASS]
[3] Basic trace clock test	[PASS]
[4] Basic event tracing check	[PASS]
[5] event tracing - enable/disable with event level files	[PASS]
[6] event tracing - restricts events based on pid	[PASS]
[7] event tracing - enable/disable with subsystem level files	[PASS]
[8] event tracing - enable/disable with top level files	[PASS]
[9] ftrace - function graph filters with stack tracer	[PASS]
[10] ftrace - function graph filters	[PASS]
[11] ftrace - function glob filters	[PASS]
[12] ftrace - function profiler with function tracing	[PASS]
[13] Test creation and deletion of trace instances while setting an event	[PASS]
[14] Test creation and deletion of trace instances	[PASS]
[15] Kprobe dynamic event - adding and removing	[PASS]
[16] Kprobe dynamic event - busy event check	[PASS]
[17] Kprobe dynamic event with arguments	[PASS]
[18] Kprobes event arguments with types	[PASS]
[19] Kprobe dynamic event with function tracer	[PASS]
[20] Kretprobe dynamic event with arguments	[PASS]
[21] event trigger - test event enable/disable trigger	[PASS]
[22] event trigger - test trigger filter	[PASS]
[23] event trigger - test histogram modifiers	[PASS]
[24] event trigger - test histogram trigger	[PASS]
[25] event trigger - test multiple histogram triggers	[PASS]
[26] event trigger - test snapshot-trigger	[PASS]
[27] event trigger - test stacktrace-trigger	[PASS]
[28] event trigger - test traceon/off trigger	[PASS]

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

v4:

o arm64 build fixes with allmodconfig

o build fix suggested for avr32 with allnoconfig, otherwise we end up with:

arch/avr32/kernel/built-in.o: In function `save_full_context_ex':
(.ex.text+0x1c4): relocation truncated to fit: R_AVR32_16N_PCREL against
symbol `debug_trampoline' defined in .text.rng.kprobes.any section in
arch/avr32/kernel/built-in.o
arch/avr32/kernel/built-in.o: In function `debug_exit_work':
(.text.rng.kprobes.any+0xa8): relocation truncated to fit:
R_AVR32_16N_PCREL against `.ex.text'+3aa
make: *** [Makefile:953: vmlinux] Error 1

o open-code section use on scripts/ code -- folks to prefer the
  simplicity over dealing with having more tool code access kernel
  headers.

o NOPE: include #include <asm-generic/ranges.h> on compiler.h -- solves
  a few 0-day compilation issues

v3:

o after v2 arch/arm/kernel/vmlinux-xip.lds.S got kprobe support,
  this just removes the custom linker script reference to kprobes as
  that is no longer needed with linker tables.

o split kprobe linker table and kprobe section ranges use into
  two separate patches. This should make it easier to review and
  also demos both distinct use types, one a linker table another
  a simple section range.

v2: introduced this patch in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arc/kernel/vmlinux.lds.S        |  1 -
 arch/arm/kernel/entry-armv.S         |  3 ++-
 arch/arm/kernel/vmlinux-xip.lds.S    |  1 -
 arch/arm/kernel/vmlinux.lds.S        |  1 -
 arch/arm64/kernel/armv8_deprecated.c |  1 +
 arch/arm64/kernel/probes/kprobes.c   |  4 ++--
 arch/arm64/kernel/vmlinux.lds.S      |  1 -
 arch/avr32/kernel/entry-avr32b.S     | 13 +++++++++++--
 arch/avr32/kernel/vmlinux.lds.S      |  1 -
 arch/blackfin/kernel/vmlinux.lds.S   |  1 -
 arch/c6x/kernel/vmlinux.lds.S        |  1 -
 arch/hexagon/kernel/vmlinux.lds.S    |  1 -
 arch/ia64/kernel/jprobes.S           |  3 ++-
 arch/ia64/kernel/vmlinux.lds.S       |  1 -
 arch/ia64/lib/flush.S                |  6 +++---
 arch/metag/kernel/vmlinux.lds.S      |  1 -
 arch/microblaze/kernel/vmlinux.lds.S |  1 -
 arch/mips/kernel/vmlinux.lds.S       |  1 -
 arch/mn10300/kernel/vmlinux.lds.S    |  1 -
 arch/nios2/kernel/vmlinux.lds.S      |  1 -
 arch/openrisc/kernel/vmlinux.lds.S   |  1 -
 arch/parisc/kernel/vmlinux.lds.S     |  1 -
 arch/powerpc/include/asm/ppc_asm.h   |  1 +
 arch/powerpc/kernel/vmlinux.lds.S    |  1 -
 arch/s390/kernel/entry.S             |  5 +++--
 arch/s390/kernel/kprobes.c           |  6 +++---
 arch/s390/kernel/mcount.S            |  3 ++-
 arch/s390/kernel/vmlinux.lds.S       |  1 -
 arch/score/kernel/vmlinux.lds.S      |  1 -
 arch/sh/kernel/vmlinux.lds.S         |  1 -
 arch/sparc/kernel/vmlinux.lds.S      |  1 -
 arch/sparc/mm/ultra.S                |  3 ++-
 arch/tile/kernel/vmlinux.lds.S       |  1 -
 arch/x86/kernel/kprobes/core.c       | 11 +++++------
 arch/x86/kernel/vmlinux.lds.S        |  1 -
 include/asm-generic/kprobes.h        |  3 ++-
 include/asm-generic/sections.h       |  2 --
 include/asm-generic/vmlinux.lds.h    |  2 +-
 include/linux/kprobes.h              |  3 +++
 kernel/kprobes.c                     |  6 ++++--
 scripts/mod/modpost.c                |  2 +-
 scripts/recordmcount.c               |  2 +-
 scripts/recordmcount.pl              |  2 +-
 43 files changed, 50 insertions(+), 54 deletions(-)

diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S
index f35ed578e007..dd05c86eb96e 100644
--- a/arch/arc/kernel/vmlinux.lds.S
+++ b/arch/arc/kernel/vmlinux.lds.S
@@ -91,7 +91,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 9f157e7c51e7..c455b491b6d3 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -34,6 +34,7 @@
 #include "entry-header.S"
 #include <asm/entry-macro-multi.S>
 #include <asm/probes.h>
+#include <asm/ranges.h>
 
 /*
  * Interrupt handling.
@@ -83,7 +84,7 @@
 	.endm
 
 #ifdef CONFIG_KPROBES
-	.section	.kprobes.text,"ax",%progbits
+	set_section_rng_type(.text, kprobes, ax, %progbits)
 #else
 	.text
 #endif
diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S
index 37b2a11af345..1a84f84b8165 100644
--- a/arch/arm/kernel/vmlinux-xip.lds.S
+++ b/arch/arm/kernel/vmlinux-xip.lds.S
@@ -103,7 +103,6 @@ SECTIONS
 			SCHED_TEXT
 			CPUIDLE_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index f7f55df0bf7b..1e278e6c3506 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -114,7 +114,6 @@ SECTIONS
 			CPUIDLE_TEXT
 			LOCK_TEXT
 			HYPERVISOR_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index 86032a012388..4043a14c9e36 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -21,6 +21,7 @@
 #include <asm/traps.h>
 #include <linux/uaccess.h>
 #include <asm/cpufeature.h>
+#include <asm/kprobes.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace-events-emulation.h"
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index f0593c92279b..ec288dd165cb 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/stop_machine.h>
 #include <linux/stringify.h>
+#include <linux/ranges.h>
 #include <asm/traps.h>
 #include <asm/ptrace.h>
 #include <asm/cacheflush.h>
@@ -540,8 +541,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
-	if ((addr >= (unsigned long)__kprobes_text_start &&
-	    addr < (unsigned long)__kprobes_text_end) ||
+	if (SECTION_RANGE_ADDR_WITHIN(kprobes, addr) ||
 	    (addr >= (unsigned long)__entry_text_start &&
 	    addr < (unsigned long)__entry_text_end) ||
 	    (addr >= (unsigned long)__idmap_text_start &&
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index b8deffa9e1bf..c68e5d528706 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -124,7 +124,6 @@ SECTIONS
 			SCHED_TEXT
 			CPUIDLE_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			HYPERVISOR_TEXT
 			IDMAP_TEXT
 			HIBERNATE_TEXT
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index 7301f4806bbe..7b2a5c5ef047 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -23,6 +23,7 @@
 #include <asm/sysreg.h>
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
+#include <asm/ranges.h>
 
 #ifdef CONFIG_PREEMPT
 # define preempt_stop		mask_interrupts
@@ -605,7 +606,11 @@ fault_exit_work:
 	brcc	fault_resume_user
 	rjmp	enter_monitor_mode
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(.text, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	handle_debug, @function
 handle_debug:
 	sub	sp, 4		/* r12_orig */
@@ -826,7 +831,11 @@ irq_level\level:
 	IRQ_LEVEL 2
 	IRQ_LEVEL 3
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(.text, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	enter_monitor_mode, @function
 enter_monitor_mode:
 	/*
diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S
index 17f2730eb497..04627a9c178e 100644
--- a/arch/avr32/kernel/vmlinux.lds.S
+++ b/arch/avr32/kernel/vmlinux.lds.S
@@ -49,7 +49,6 @@ SECTIONS
 		_stext = .;
 		*(.ex.text)
 		*(.irq.text)
-		KPROBES_TEXT
 		TEXT_TEXT
 		SCHED_TEXT
 		CPUIDLE_TEXT
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 68069a120055..93220ff65014 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -37,7 +37,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 #ifdef CONFIG_ROMKERNEL
 		__sinittext = .;
 		INIT_TEXT
diff --git a/arch/c6x/kernel/vmlinux.lds.S b/arch/c6x/kernel/vmlinux.lds.S
index a1a5c166bc9b..a41d43b8254b 100644
--- a/arch/c6x/kernel/vmlinux.lds.S
+++ b/arch/c6x/kernel/vmlinux.lds.S
@@ -74,7 +74,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S
index ec87e67feb19..7e6f68584b55 100644
--- a/arch/hexagon/kernel/vmlinux.lds.S
+++ b/arch/hexagon/kernel/vmlinux.lds.S
@@ -52,7 +52,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 	}
 	_etext = .;
diff --git a/arch/ia64/kernel/jprobes.S b/arch/ia64/kernel/jprobes.S
index f69389c7be1d..71adc7132e22 100644
--- a/arch/ia64/kernel/jprobes.S
+++ b/arch/ia64/kernel/jprobes.S
@@ -46,11 +46,12 @@
  */
 #include <asm/asmmacro.h>
 #include <asm/break.h>
+#include <asm/ranges.h>
 
 	/*
 	 * void jprobe_break(void)
 	 */
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 ENTRY(jprobe_break)
 	break.m __IA64_BREAK_JPROBE
 END(jprobe_break)
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index f89d20c97412..3ff6edf913d2 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -48,7 +48,6 @@ SECTIONS {
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.gnu.linkonce.t*)
 	}
 
diff --git a/arch/ia64/lib/flush.S b/arch/ia64/lib/flush.S
index 9a5a2f9fad13..dec1b180d618 100644
--- a/arch/ia64/lib/flush.S
+++ b/arch/ia64/lib/flush.S
@@ -9,7 +9,7 @@
 
 #include <asm/asmmacro.h>
 #include <asm/export.h>
-
+#include <asm/ranges.h>
 
 	/*
 	 * flush_icache_range(start,end)
@@ -21,7 +21,7 @@
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(.text, kprobes, ax)
 GLOBAL_ENTRY(flush_icache_range)
 
 	.prologue
@@ -74,7 +74,7 @@ EXPORT_SYMBOL_GPL(flush_icache_range)
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(.text, kprobes, ax)
 GLOBAL_ENTRY(clflush_cache_range)
 
 	.prologue
diff --git a/arch/metag/kernel/vmlinux.lds.S b/arch/metag/kernel/vmlinux.lds.S
index e6c700eaf207..b18386d2250f 100644
--- a/arch/metag/kernel/vmlinux.lds.S
+++ b/arch/metag/kernel/vmlinux.lds.S
@@ -23,7 +23,6 @@ SECTIONS
 	SCHED_TEXT
 	CPUIDLE_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	IRQENTRY_TEXT
 	SOFTIRQENTRY_TEXT
 	*(.text.*)
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
index 289d0e7f3e3a..aadee2229ac6 100644
--- a/arch/microblaze/kernel/vmlinux.lds.S
+++ b/arch/microblaze/kernel/vmlinux.lds.S
@@ -35,7 +35,6 @@ SECTIONS {
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		. = ALIGN (4) ;
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index f0a0e6d62be3..44e21812c544 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -57,7 +57,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.*)
diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S
index 2d5f1c3f1afb..552ef00a3da5 100644
--- a/arch/mn10300/kernel/vmlinux.lds.S
+++ b/arch/mn10300/kernel/vmlinux.lds.S
@@ -32,7 +32,6 @@ SECTIONS
 	SCHED_TEXT
 	CPUIDLE_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0xcb
diff --git a/arch/nios2/kernel/vmlinux.lds.S b/arch/nios2/kernel/vmlinux.lds.S
index 6a8045bb1a77..aae4a00c4056 100644
--- a/arch/nios2/kernel/vmlinux.lds.S
+++ b/arch/nios2/kernel/vmlinux.lds.S
@@ -41,7 +41,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 	} =0
 	_etext = .;
 
diff --git a/arch/openrisc/kernel/vmlinux.lds.S b/arch/openrisc/kernel/vmlinux.lds.S
index 00ddb7804be4..8ade6ccca6ac 100644
--- a/arch/openrisc/kernel/vmlinux.lds.S
+++ b/arch/openrisc/kernel/vmlinux.lds.S
@@ -57,7 +57,6 @@ SECTIONS
 	  SCHED_TEXT
 	  CPUIDLE_TEXT
 	  LOCK_TEXT
-	  KPROBES_TEXT
 	  IRQENTRY_TEXT
 	  SOFTIRQENTRY_TEXT
 	  *(.fixup)
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 3d6ef1b29c6a..edbd6d9487dc 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -71,7 +71,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.do_softirq)
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 025833b8df9f..0846413b3a2e 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,6 +9,7 @@
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
 #include <asm/firmware.h>
+#include <asm/ranges.h>
 
 #ifdef __ASSEMBLY__
 
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 8cd940c72895..2285664abb52 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -112,7 +112,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		MEM_KEEP(init.text)
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 97298c58b2be..847e2e1df89c 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -24,6 +24,7 @@
 #include <asm/setup.h>
 #include <asm/nmi.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
 __PT_R0      =	__PT_GPRS
 __PT_R1      =	__PT_GPRS + 8
@@ -169,7 +170,7 @@ _PIF_WORK	= (_PIF_PER_TRAP)
 		tm	off+\addr, \mask
 	.endm
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 .Ldummy:
 	/*
 	 * This nop exists only in order to avoid that __switch_to starts at
@@ -986,7 +987,7 @@ ENTRY(restart_int_handler)
 	brc	2,2b
 3:	j	3b
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 
 #ifdef CONFIG_CHECK_STACK
 /*
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 84e0557b16fe..94a4918b5968 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -289,9 +289,9 @@ static void kprobe_reenter_check(struct kprobe_ctlblk *kcb, struct kprobe *p)
 	case KPROBE_REENTER:
 	default:
 		/*
-		 * A kprobe on the code path to single step an instruction
-		 * is a BUG. The code path resides in the .kprobes.text
-		 * section and is executed with interrupts disabled.
+		 * A kprobe on the code path to single step an instruction is a
+		 * BUG. The code path resides in the kprobes section range and
+		 * is executed with interrupts disabled.
 		 */
 		printk(KERN_EMERG "Invalid kprobe detected at %p.\n", p->addr);
 		dump_kprobe(p);
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S
index 9a17e4475d27..9d76056609f7 100644
--- a/arch/s390/kernel/mcount.S
+++ b/arch/s390/kernel/mcount.S
@@ -10,8 +10,9 @@
 #include <asm/ftrace.h>
 #include <asm/ptrace.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 
 ENTRY(ftrace_stub)
 	br	%r14
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 3667d20e997f..b2df6d9bab09 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -37,7 +37,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/score/kernel/vmlinux.lds.S b/arch/score/kernel/vmlinux.lds.S
index 4117890b1db1..a8b14f3ed474 100644
--- a/arch/score/kernel/vmlinux.lds.S
+++ b/arch/score/kernel/vmlinux.lds.S
@@ -42,7 +42,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.text.*)
 		*(.fixup)
 		. = ALIGN (4) ;
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 5b9a3cc90c58..58d9ba796f7a 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -38,7 +38,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 572db686f845..0ee41b0071e5 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -51,7 +51,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.gnu.warning)
diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S
index 5d2fd6cd3189..ee9f648549c0 100644
--- a/arch/sparc/mm/ultra.S
+++ b/arch/sparc/mm/ultra.S
@@ -16,6 +16,7 @@
 #include <asm/cacheflush.h>
 #include <asm/hypervisor.h>
 #include <asm/cpudata.h>
+#include <asm/ranges.h>
 
 	/* Basically, most of the Spitfire vs. Cheetah madness
 	 * has to do with the fact that Cheetah does not support
@@ -185,7 +186,7 @@ __spitfire_flush_tlb_mm_slow:
 /*
  * The following code flushes one page_size worth.
  */
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 	.align		32
 	.globl		__flush_icache_page
 __flush_icache_page:	/* %o0 = phys_page */
diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S
index e1baf094fba4..85d03ce6c0a0 100644
--- a/arch/tile/kernel/vmlinux.lds.S
+++ b/arch/tile/kernel/vmlinux.lds.S
@@ -44,7 +44,6 @@ SECTIONS
     SCHED_TEXT
     CPUIDLE_TEXT
     LOCK_TEXT
-    KPROBES_TEXT
     IRQENTRY_TEXT
     SOFTIRQENTRY_TEXT
     __fix_text_end = .;   /* tile-cpack won't rearrange before this */
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index eb3509338ae0..95e4b172e923 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -580,9 +580,9 @@ static int reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
 	case KPROBE_REENTER:
 		/* A probe has been hit in the codepath leading up to, or just
 		 * after, single-stepping of a probed instruction. This entire
-		 * codepath should strictly reside in .kprobes.text section.
-		 * Raise a BUG or we'll continue in an endless reentering loop
-		 * and eventually a stack overflow.
+		 * codepath should strictly reside in the kprobes section
+		 * range. Raise a BUG or we'll continue in an endless
+		 * reentering loop and eventually a stack overflow.
 		 */
 		printk(KERN_WARNING "Unrecoverable kprobe detected at %p.\n",
 		       p->addr);
@@ -1133,10 +1133,9 @@ NOKPROBE_SYMBOL(longjmp_break_handler);
 
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
-	return  (addr >= (unsigned long)__kprobes_text_start &&
-		 addr < (unsigned long)__kprobes_text_end) ||
+	return  (SECTION_RANGE_ADDR_WITHIN(kprobes, addr) ||
 		(addr >= (unsigned long)__entry_text_start &&
-		 addr < (unsigned long)__entry_text_end);
+		 addr < (unsigned long)__entry_text_end));
 }
 
 int __init arch_init_kprobes(void)
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index e79f15f108a8..4c16fadb9ac6 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -99,7 +99,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		ENTRY_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 57af9f21d148..02a26b975187 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,6 +3,7 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
@@ -13,7 +14,7 @@ static unsigned long __used					\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define __kprobes	__LINUX_RANGE(.text, kprobes)
 # define nokprobe_inline	__always_inline
 #else
 # define NOKPROBE_SYMBOL(fname)
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index b145ae8d9cbe..f3340f2772bb 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -26,7 +26,6 @@
  * Following global variables are optional and may be unavailable on some
  * architectures and/or kernel configurations.
  *	_text, _data
- *	__kprobes_text_start, __kprobes_text_end
  *	__entry_text_start, __entry_text_end
  *	__ctors_start, __ctors_end
  */
@@ -38,7 +37,6 @@ extern char _sinittext[], _einittext[];
 extern char __start_data_ro_after_init[], __end_data_ro_after_init[];
 extern char _end[];
 extern char __per_cpu_load[], __per_cpu_start[], __per_cpu_end[];
-extern char __kprobes_text_start[], __kprobes_text_end[];
 extern char __entry_text_start[], __entry_text_end[];
 extern char __start_rodata[], __end_rodata[];
 
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 37b99537d5a9..499caf5b4361 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -471,7 +471,7 @@
 #define KPROBES_TEXT							\
 		ALIGN_FUNCTION();					\
 		VMLINUX_SYMBOL(__kprobes_text_start) = .;		\
-		*(.kprobes.text)					\
+		*(.text..rng.kprobes.any)				\
 		VMLINUX_SYMBOL(__kprobes_text_end) = .;
 
 #define ENTRY_TEXT							\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 985ed79ef431..445cc6fe7afa 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -43,6 +43,9 @@
 #include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
+#include <linux/ranges.h>
+
+DECLARE_SECTION_RANGE(kprobes);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 43460104f119..82191f328e21 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1328,8 +1328,7 @@ static int register_aggr_kprobe(struct kprobe *orig_p, struct kprobe *p)
 bool __weak arch_within_kprobe_blacklist(unsigned long addr)
 {
 	/* The __kprobes marked functions and entry code must not be probed */
-	return addr >= (unsigned long)__kprobes_text_start &&
-	       addr < (unsigned long)__kprobes_text_end;
+	return SECTION_RANGE_ADDR_WITHIN(kprobes, addr);
 }
 
 bool within_kprobe_blacklist(unsigned long addr)
@@ -2129,6 +2128,9 @@ static struct notifier_block kprobe_module_nb = {
 extern unsigned long __start_kprobe_blacklist[];
 extern unsigned long __stop_kprobe_blacklist[];
 
+/* Actual kprobes section range */
+DEFINE_SECTION_RANGE(kprobes, .text);
+
 static int __init init_kprobes(void)
 {
 	int i, err = 0;
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 29c89a6bad3d..2b442234c69b 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -894,7 +894,7 @@ static void check_section(const char *modname, struct elf_info *elf,
 
 #define DATA_SECTIONS ".data", ".data.rel"
 #define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \
-		".kprobes.text", ".cpuidle.text"
+		".text..rng.kprobes.any", ".cpuidle.text"
 #define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
 		".fixup", ".entry.text", ".exception.text", ".text.*", \
 		".coldtext"
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index aeb34223167c..6e95f3f87db1 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -417,7 +417,7 @@ is_mcounted_section_name(char const *const txtname)
 		strcmp(".spinlock.text", txtname) == 0 ||
 		strcmp(".irqentry.text", txtname) == 0 ||
 		strcmp(".softirqentry.text", txtname) == 0 ||
-		strcmp(".kprobes.text", txtname) == 0 ||
+		strcmp(".text..rng.kprobes.any", txtname) == 0 ||
 		strcmp(".cpuidle.text", txtname) == 0 ||
 		strcmp(".text.unlikely", txtname) == 0;
 }
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 0b6002b36f20..15e2fa37c489 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -135,7 +135,7 @@ my %text_sections = (
      ".spinlock.text" => 1,
      ".irqentry.text" => 1,
      ".softirqentry.text" => 1,
-     ".kprobes.text" => 1,
+     ".text..rng.kprobes.any" => 1,
      ".cpuidle.text" => 1,
      ".text.unlikely" => 1,
 );
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 12/14] kprobes: port .kprobes.text to section range
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

kprobe makes use of two custom sections, each custom section
is folded into one of the standard Linux sections types as follows,
it currently relies on the linker script to fold the custom section
onto the respective Linux section:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist
range .text         .kprobes.text        __kprobes_text_start     __kprobes_text_end

This ports the .kprobes.text custom section to the standard
Linux ranges API allowing us remove all the custom kprobe section
declarations from the linker script.

Tested with CONFIG_KPROBES_SANITY_TEST, it passes with:

Kprobe smoke test: started
Kprobe smoke test: passed successfully

Then tested CONFIG_SAMPLE_KPROBES on do_fork, and the kprobe bites
and kicks as expected.

Also ran ./ftracetest with no issues:

sudo ./ftracetest
=== Ftrace unit tests ===
[1] Basic trace file check	[PASS]
[2] Basic test for tracers	[PASS]
[3] Basic trace clock test	[PASS]
[4] Basic event tracing check	[PASS]
[5] event tracing - enable/disable with event level files	[PASS]
[6] event tracing - restricts events based on pid	[PASS]
[7] event tracing - enable/disable with subsystem level files	[PASS]
[8] event tracing - enable/disable with top level files	[PASS]
[9] ftrace - function graph filters with stack tracer	[PASS]
[10] ftrace - function graph filters	[PASS]
[11] ftrace - function glob filters	[PASS]
[12] ftrace - function profiler with function tracing	[PASS]
[13] Test creation and deletion of trace instances while setting an event	[PASS]
[14] Test creation and deletion of trace instances	[PASS]
[15] Kprobe dynamic event - adding and removing	[PASS]
[16] Kprobe dynamic event - busy event check	[PASS]
[17] Kprobe dynamic event with arguments	[PASS]
[18] Kprobes event arguments with types	[PASS]
[19] Kprobe dynamic event with function tracer	[PASS]
[20] Kretprobe dynamic event with arguments	[PASS]
[21] event trigger - test event enable/disable trigger	[PASS]
[22] event trigger - test trigger filter	[PASS]
[23] event trigger - test histogram modifiers	[PASS]
[24] event trigger - test histogram trigger	[PASS]
[25] event trigger - test multiple histogram triggers	[PASS]
[26] event trigger - test snapshot-trigger	[PASS]
[27] event trigger - test stacktrace-trigger	[PASS]
[28] event trigger - test traceon/off trigger	[PASS]

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clash with compiler generated
  section.

o Replace section macros with section names

v4:

o arm64 build fixes with allmodconfig

o build fix suggested for avr32 with allnoconfig, otherwise we end up with:

arch/avr32/kernel/built-in.o: In function `save_full_context_ex':
(.ex.text+0x1c4): relocation truncated to fit: R_AVR32_16N_PCREL against
symbol `debug_trampoline' defined in .text.rng.kprobes.any section in
arch/avr32/kernel/built-in.o
arch/avr32/kernel/built-in.o: In function `debug_exit_work':
(.text.rng.kprobes.any+0xa8): relocation truncated to fit:
R_AVR32_16N_PCREL against `.ex.text'+3aa
make: *** [Makefile:953: vmlinux] Error 1

o open-code section use on scripts/ code -- folks to prefer the
  simplicity over dealing with having more tool code access kernel
  headers.

o NOPE: include #include <asm-generic/ranges.h> on compiler.h -- solves
  a few 0-day compilation issues

v3:

o after v2 arch/arm/kernel/vmlinux-xip.lds.S got kprobe support,
  this just removes the custom linker script reference to kprobes as
  that is no longer needed with linker tables.

o split kprobe linker table and kprobe section ranges use into
  two separate patches. This should make it easier to review and
  also demos both distinct use types, one a linker table another
  a simple section range.

v2: introduced this patch in this series

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/arc/kernel/vmlinux.lds.S        |  1 -
 arch/arm/kernel/entry-armv.S         |  3 ++-
 arch/arm/kernel/vmlinux-xip.lds.S    |  1 -
 arch/arm/kernel/vmlinux.lds.S        |  1 -
 arch/arm64/kernel/armv8_deprecated.c |  1 +
 arch/arm64/kernel/probes/kprobes.c   |  4 ++--
 arch/arm64/kernel/vmlinux.lds.S      |  1 -
 arch/avr32/kernel/entry-avr32b.S     | 13 +++++++++++--
 arch/avr32/kernel/vmlinux.lds.S      |  1 -
 arch/blackfin/kernel/vmlinux.lds.S   |  1 -
 arch/c6x/kernel/vmlinux.lds.S        |  1 -
 arch/hexagon/kernel/vmlinux.lds.S    |  1 -
 arch/ia64/kernel/jprobes.S           |  3 ++-
 arch/ia64/kernel/vmlinux.lds.S       |  1 -
 arch/ia64/lib/flush.S                |  6 +++---
 arch/metag/kernel/vmlinux.lds.S      |  1 -
 arch/microblaze/kernel/vmlinux.lds.S |  1 -
 arch/mips/kernel/vmlinux.lds.S       |  1 -
 arch/mn10300/kernel/vmlinux.lds.S    |  1 -
 arch/nios2/kernel/vmlinux.lds.S      |  1 -
 arch/openrisc/kernel/vmlinux.lds.S   |  1 -
 arch/parisc/kernel/vmlinux.lds.S     |  1 -
 arch/powerpc/include/asm/ppc_asm.h   |  1 +
 arch/powerpc/kernel/vmlinux.lds.S    |  1 -
 arch/s390/kernel/entry.S             |  5 +++--
 arch/s390/kernel/kprobes.c           |  6 +++---
 arch/s390/kernel/mcount.S            |  3 ++-
 arch/s390/kernel/vmlinux.lds.S       |  1 -
 arch/score/kernel/vmlinux.lds.S      |  1 -
 arch/sh/kernel/vmlinux.lds.S         |  1 -
 arch/sparc/kernel/vmlinux.lds.S      |  1 -
 arch/sparc/mm/ultra.S                |  3 ++-
 arch/tile/kernel/vmlinux.lds.S       |  1 -
 arch/x86/kernel/kprobes/core.c       | 11 +++++------
 arch/x86/kernel/vmlinux.lds.S        |  1 -
 include/asm-generic/kprobes.h        |  3 ++-
 include/asm-generic/sections.h       |  2 --
 include/asm-generic/vmlinux.lds.h    |  2 +-
 include/linux/kprobes.h              |  3 +++
 kernel/kprobes.c                     |  6 ++++--
 scripts/mod/modpost.c                |  2 +-
 scripts/recordmcount.c               |  2 +-
 scripts/recordmcount.pl              |  2 +-
 43 files changed, 50 insertions(+), 54 deletions(-)

diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S
index f35ed578e007..dd05c86eb96e 100644
--- a/arch/arc/kernel/vmlinux.lds.S
+++ b/arch/arc/kernel/vmlinux.lds.S
@@ -91,7 +91,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 9f157e7c51e7..c455b491b6d3 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -34,6 +34,7 @@
 #include "entry-header.S"
 #include <asm/entry-macro-multi.S>
 #include <asm/probes.h>
+#include <asm/ranges.h>
 
 /*
  * Interrupt handling.
@@ -83,7 +84,7 @@
 	.endm
 
 #ifdef CONFIG_KPROBES
-	.section	.kprobes.text,"ax",%progbits
+	set_section_rng_type(.text, kprobes, ax, %progbits)
 #else
 	.text
 #endif
diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S
index 37b2a11af345..1a84f84b8165 100644
--- a/arch/arm/kernel/vmlinux-xip.lds.S
+++ b/arch/arm/kernel/vmlinux-xip.lds.S
@@ -103,7 +103,6 @@ SECTIONS
 			SCHED_TEXT
 			CPUIDLE_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index f7f55df0bf7b..1e278e6c3506 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -114,7 +114,6 @@ SECTIONS
 			CPUIDLE_TEXT
 			LOCK_TEXT
 			HYPERVISOR_TEXT
-			KPROBES_TEXT
 			*(.gnu.warning)
 			*(.glue_7)
 			*(.glue_7t)
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index 86032a012388..4043a14c9e36 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -21,6 +21,7 @@
 #include <asm/traps.h>
 #include <linux/uaccess.h>
 #include <asm/cpufeature.h>
+#include <asm/kprobes.h>
 
 #define CREATE_TRACE_POINTS
 #include "trace-events-emulation.h"
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index f0593c92279b..ec288dd165cb 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/stop_machine.h>
 #include <linux/stringify.h>
+#include <linux/ranges.h>
 #include <asm/traps.h>
 #include <asm/ptrace.h>
 #include <asm/cacheflush.h>
@@ -540,8 +541,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
-	if ((addr >= (unsigned long)__kprobes_text_start &&
-	    addr < (unsigned long)__kprobes_text_end) ||
+	if (SECTION_RANGE_ADDR_WITHIN(kprobes, addr) ||
 	    (addr >= (unsigned long)__entry_text_start &&
 	    addr < (unsigned long)__entry_text_end) ||
 	    (addr >= (unsigned long)__idmap_text_start &&
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index b8deffa9e1bf..c68e5d528706 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -124,7 +124,6 @@ SECTIONS
 			SCHED_TEXT
 			CPUIDLE_TEXT
 			LOCK_TEXT
-			KPROBES_TEXT
 			HYPERVISOR_TEXT
 			IDMAP_TEXT
 			HIBERNATE_TEXT
diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S
index 7301f4806bbe..7b2a5c5ef047 100644
--- a/arch/avr32/kernel/entry-avr32b.S
+++ b/arch/avr32/kernel/entry-avr32b.S
@@ -23,6 +23,7 @@
 #include <asm/sysreg.h>
 #include <asm/thread_info.h>
 #include <asm/unistd.h>
+#include <asm/ranges.h>
 
 #ifdef CONFIG_PREEMPT
 # define preempt_stop		mask_interrupts
@@ -605,7 +606,11 @@ fault_exit_work:
 	brcc	fault_resume_user
 	rjmp	enter_monitor_mode
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(.text, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	handle_debug, @function
 handle_debug:
 	sub	sp, 4		/* r12_orig */
@@ -826,7 +831,11 @@ irq_level\level:
 	IRQ_LEVEL 2
 	IRQ_LEVEL 3
 
-	.section .kprobes.text, "ax", @progbits
+#ifdef CONFIG_KPROBES
+	set_section_rng_type(.text, kprobes, ax, @progbits)
+#else
+	.text
+#endif
 	.type	enter_monitor_mode, @function
 enter_monitor_mode:
 	/*
diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S
index 17f2730eb497..04627a9c178e 100644
--- a/arch/avr32/kernel/vmlinux.lds.S
+++ b/arch/avr32/kernel/vmlinux.lds.S
@@ -49,7 +49,6 @@ SECTIONS
 		_stext = .;
 		*(.ex.text)
 		*(.irq.text)
-		KPROBES_TEXT
 		TEXT_TEXT
 		SCHED_TEXT
 		CPUIDLE_TEXT
diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S
index 68069a120055..93220ff65014 100644
--- a/arch/blackfin/kernel/vmlinux.lds.S
+++ b/arch/blackfin/kernel/vmlinux.lds.S
@@ -37,7 +37,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 #ifdef CONFIG_ROMKERNEL
 		__sinittext = .;
 		INIT_TEXT
diff --git a/arch/c6x/kernel/vmlinux.lds.S b/arch/c6x/kernel/vmlinux.lds.S
index a1a5c166bc9b..a41d43b8254b 100644
--- a/arch/c6x/kernel/vmlinux.lds.S
+++ b/arch/c6x/kernel/vmlinux.lds.S
@@ -74,7 +74,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 		*(.gnu.warning)
 	}
diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S
index ec87e67feb19..7e6f68584b55 100644
--- a/arch/hexagon/kernel/vmlinux.lds.S
+++ b/arch/hexagon/kernel/vmlinux.lds.S
@@ -52,7 +52,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.fixup)
 	}
 	_etext = .;
diff --git a/arch/ia64/kernel/jprobes.S b/arch/ia64/kernel/jprobes.S
index f69389c7be1d..71adc7132e22 100644
--- a/arch/ia64/kernel/jprobes.S
+++ b/arch/ia64/kernel/jprobes.S
@@ -46,11 +46,12 @@
  */
 #include <asm/asmmacro.h>
 #include <asm/break.h>
+#include <asm/ranges.h>
 
 	/*
 	 * void jprobe_break(void)
 	 */
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 ENTRY(jprobe_break)
 	break.m __IA64_BREAK_JPROBE
 END(jprobe_break)
diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
index f89d20c97412..3ff6edf913d2 100644
--- a/arch/ia64/kernel/vmlinux.lds.S
+++ b/arch/ia64/kernel/vmlinux.lds.S
@@ -48,7 +48,6 @@ SECTIONS {
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.gnu.linkonce.t*)
 	}
 
diff --git a/arch/ia64/lib/flush.S b/arch/ia64/lib/flush.S
index 9a5a2f9fad13..dec1b180d618 100644
--- a/arch/ia64/lib/flush.S
+++ b/arch/ia64/lib/flush.S
@@ -9,7 +9,7 @@
 
 #include <asm/asmmacro.h>
 #include <asm/export.h>
-
+#include <asm/ranges.h>
 
 	/*
 	 * flush_icache_range(start,end)
@@ -21,7 +21,7 @@
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(.text, kprobes, ax)
 GLOBAL_ENTRY(flush_icache_range)
 
 	.prologue
@@ -74,7 +74,7 @@ EXPORT_SYMBOL_GPL(flush_icache_range)
 	 *
 	 *	Note: "in0" and "in1" are preserved for debugging purposes.
 	 */
-	.section .kprobes.text,"ax"
+	set_section_rng(.text, kprobes, ax)
 GLOBAL_ENTRY(clflush_cache_range)
 
 	.prologue
diff --git a/arch/metag/kernel/vmlinux.lds.S b/arch/metag/kernel/vmlinux.lds.S
index e6c700eaf207..b18386d2250f 100644
--- a/arch/metag/kernel/vmlinux.lds.S
+++ b/arch/metag/kernel/vmlinux.lds.S
@@ -23,7 +23,6 @@ SECTIONS
 	SCHED_TEXT
 	CPUIDLE_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	IRQENTRY_TEXT
 	SOFTIRQENTRY_TEXT
 	*(.text.*)
diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S
index 289d0e7f3e3a..aadee2229ac6 100644
--- a/arch/microblaze/kernel/vmlinux.lds.S
+++ b/arch/microblaze/kernel/vmlinux.lds.S
@@ -35,7 +35,6 @@ SECTIONS {
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		. = ALIGN (4) ;
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index f0a0e6d62be3..44e21812c544 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -57,7 +57,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.*)
diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S
index 2d5f1c3f1afb..552ef00a3da5 100644
--- a/arch/mn10300/kernel/vmlinux.lds.S
+++ b/arch/mn10300/kernel/vmlinux.lds.S
@@ -32,7 +32,6 @@ SECTIONS
 	SCHED_TEXT
 	CPUIDLE_TEXT
 	LOCK_TEXT
-	KPROBES_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0xcb
diff --git a/arch/nios2/kernel/vmlinux.lds.S b/arch/nios2/kernel/vmlinux.lds.S
index 6a8045bb1a77..aae4a00c4056 100644
--- a/arch/nios2/kernel/vmlinux.lds.S
+++ b/arch/nios2/kernel/vmlinux.lds.S
@@ -41,7 +41,6 @@ SECTIONS
 		LOCK_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
-		KPROBES_TEXT
 	} =0
 	_etext = .;
 
diff --git a/arch/openrisc/kernel/vmlinux.lds.S b/arch/openrisc/kernel/vmlinux.lds.S
index 00ddb7804be4..8ade6ccca6ac 100644
--- a/arch/openrisc/kernel/vmlinux.lds.S
+++ b/arch/openrisc/kernel/vmlinux.lds.S
@@ -57,7 +57,6 @@ SECTIONS
 	  SCHED_TEXT
 	  CPUIDLE_TEXT
 	  LOCK_TEXT
-	  KPROBES_TEXT
 	  IRQENTRY_TEXT
 	  SOFTIRQENTRY_TEXT
 	  *(.fixup)
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index 3d6ef1b29c6a..edbd6d9487dc 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -71,7 +71,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.text.do_softirq)
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 025833b8df9f..0846413b3a2e 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,6 +9,7 @@
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
 #include <asm/firmware.h>
+#include <asm/ranges.h>
 
 #ifdef __ASSEMBLY__
 
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 8cd940c72895..2285664abb52 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -112,7 +112,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		MEM_KEEP(init.text)
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 97298c58b2be..847e2e1df89c 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -24,6 +24,7 @@
 #include <asm/setup.h>
 #include <asm/nmi.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
 __PT_R0      =	__PT_GPRS
 __PT_R1      =	__PT_GPRS + 8
@@ -169,7 +170,7 @@ _PIF_WORK	= (_PIF_PER_TRAP)
 		tm	off+\addr, \mask
 	.endm
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 .Ldummy:
 	/*
 	 * This nop exists only in order to avoid that __switch_to starts at
@@ -986,7 +987,7 @@ ENTRY(restart_int_handler)
 	brc	2,2b
 3:	j	3b
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 
 #ifdef CONFIG_CHECK_STACK
 /*
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 84e0557b16fe..94a4918b5968 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -289,9 +289,9 @@ static void kprobe_reenter_check(struct kprobe_ctlblk *kcb, struct kprobe *p)
 	case KPROBE_REENTER:
 	default:
 		/*
-		 * A kprobe on the code path to single step an instruction
-		 * is a BUG. The code path resides in the .kprobes.text
-		 * section and is executed with interrupts disabled.
+		 * A kprobe on the code path to single step an instruction is a
+		 * BUG. The code path resides in the kprobes section range and
+		 * is executed with interrupts disabled.
 		 */
 		printk(KERN_EMERG "Invalid kprobe detected at %p.\n", p->addr);
 		dump_kprobe(p);
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S
index 9a17e4475d27..9d76056609f7 100644
--- a/arch/s390/kernel/mcount.S
+++ b/arch/s390/kernel/mcount.S
@@ -10,8 +10,9 @@
 #include <asm/ftrace.h>
 #include <asm/ptrace.h>
 #include <asm/export.h>
+#include <asm/ranges.h>
 
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 
 ENTRY(ftrace_stub)
 	br	%r14
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 3667d20e997f..b2df6d9bab09 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -37,7 +37,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/score/kernel/vmlinux.lds.S b/arch/score/kernel/vmlinux.lds.S
index 4117890b1db1..a8b14f3ed474 100644
--- a/arch/score/kernel/vmlinux.lds.S
+++ b/arch/score/kernel/vmlinux.lds.S
@@ -42,7 +42,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		*(.text.*)
 		*(.fixup)
 		. = ALIGN (4) ;
diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S
index 5b9a3cc90c58..58d9ba796f7a 100644
--- a/arch/sh/kernel/vmlinux.lds.S
+++ b/arch/sh/kernel/vmlinux.lds.S
@@ -38,7 +38,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.fixup)
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 572db686f845..0ee41b0071e5 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -51,7 +51,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
 		*(.gnu.warning)
diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S
index 5d2fd6cd3189..ee9f648549c0 100644
--- a/arch/sparc/mm/ultra.S
+++ b/arch/sparc/mm/ultra.S
@@ -16,6 +16,7 @@
 #include <asm/cacheflush.h>
 #include <asm/hypervisor.h>
 #include <asm/cpudata.h>
+#include <asm/ranges.h>
 
 	/* Basically, most of the Spitfire vs. Cheetah madness
 	 * has to do with the fact that Cheetah does not support
@@ -185,7 +186,7 @@ __spitfire_flush_tlb_mm_slow:
 /*
  * The following code flushes one page_size worth.
  */
-	.section .kprobes.text, "ax"
+	set_section_rng(.text, kprobes, ax)
 	.align		32
 	.globl		__flush_icache_page
 __flush_icache_page:	/* %o0 = phys_page */
diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S
index e1baf094fba4..85d03ce6c0a0 100644
--- a/arch/tile/kernel/vmlinux.lds.S
+++ b/arch/tile/kernel/vmlinux.lds.S
@@ -44,7 +44,6 @@ SECTIONS
     SCHED_TEXT
     CPUIDLE_TEXT
     LOCK_TEXT
-    KPROBES_TEXT
     IRQENTRY_TEXT
     SOFTIRQENTRY_TEXT
     __fix_text_end = .;   /* tile-cpack won't rearrange before this */
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index eb3509338ae0..95e4b172e923 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -580,9 +580,9 @@ static int reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
 	case KPROBE_REENTER:
 		/* A probe has been hit in the codepath leading up to, or just
 		 * after, single-stepping of a probed instruction. This entire
-		 * codepath should strictly reside in .kprobes.text section.
-		 * Raise a BUG or we'll continue in an endless reentering loop
-		 * and eventually a stack overflow.
+		 * codepath should strictly reside in the kprobes section
+		 * range. Raise a BUG or we'll continue in an endless
+		 * reentering loop and eventually a stack overflow.
 		 */
 		printk(KERN_WARNING "Unrecoverable kprobe detected at %p.\n",
 		       p->addr);
@@ -1133,10 +1133,9 @@ NOKPROBE_SYMBOL(longjmp_break_handler);
 
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
-	return  (addr >= (unsigned long)__kprobes_text_start &&
-		 addr < (unsigned long)__kprobes_text_end) ||
+	return  (SECTION_RANGE_ADDR_WITHIN(kprobes, addr) ||
 		(addr >= (unsigned long)__entry_text_start &&
-		 addr < (unsigned long)__entry_text_end);
+		 addr < (unsigned long)__entry_text_end));
 }
 
 int __init arch_init_kprobes(void)
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index e79f15f108a8..4c16fadb9ac6 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -99,7 +99,6 @@ SECTIONS
 		SCHED_TEXT
 		CPUIDLE_TEXT
 		LOCK_TEXT
-		KPROBES_TEXT
 		ENTRY_TEXT
 		IRQENTRY_TEXT
 		SOFTIRQENTRY_TEXT
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 57af9f21d148..02a26b975187 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,6 +3,7 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
@@ -13,7 +14,7 @@ static unsigned long __used					\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
-# define __kprobes	__attribute__((__section__(".kprobes.text")))
+# define __kprobes	__LINUX_RANGE(.text, kprobes)
 # define nokprobe_inline	__always_inline
 #else
 # define NOKPROBE_SYMBOL(fname)
diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
index b145ae8d9cbe..f3340f2772bb 100644
--- a/include/asm-generic/sections.h
+++ b/include/asm-generic/sections.h
@@ -26,7 +26,6 @@
  * Following global variables are optional and may be unavailable on some
  * architectures and/or kernel configurations.
  *	_text, _data
- *	__kprobes_text_start, __kprobes_text_end
  *	__entry_text_start, __entry_text_end
  *	__ctors_start, __ctors_end
  */
@@ -38,7 +37,6 @@ extern char _sinittext[], _einittext[];
 extern char __start_data_ro_after_init[], __end_data_ro_after_init[];
 extern char _end[];
 extern char __per_cpu_load[], __per_cpu_start[], __per_cpu_end[];
-extern char __kprobes_text_start[], __kprobes_text_end[];
 extern char __entry_text_start[], __entry_text_end[];
 extern char __start_rodata[], __end_rodata[];
 
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 37b99537d5a9..499caf5b4361 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -471,7 +471,7 @@
 #define KPROBES_TEXT							\
 		ALIGN_FUNCTION();					\
 		VMLINUX_SYMBOL(__kprobes_text_start) = .;		\
-		*(.kprobes.text)					\
+		*(.text..rng.kprobes.any)				\
 		VMLINUX_SYMBOL(__kprobes_text_end) = .;
 
 #define ENTRY_TEXT							\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 985ed79ef431..445cc6fe7afa 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -43,6 +43,9 @@
 #include <asm/kprobes.h>
 
 #ifdef CONFIG_KPROBES
+#include <linux/ranges.h>
+
+DECLARE_SECTION_RANGE(kprobes);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 43460104f119..82191f328e21 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1328,8 +1328,7 @@ static int register_aggr_kprobe(struct kprobe *orig_p, struct kprobe *p)
 bool __weak arch_within_kprobe_blacklist(unsigned long addr)
 {
 	/* The __kprobes marked functions and entry code must not be probed */
-	return addr >= (unsigned long)__kprobes_text_start &&
-	       addr < (unsigned long)__kprobes_text_end;
+	return SECTION_RANGE_ADDR_WITHIN(kprobes, addr);
 }
 
 bool within_kprobe_blacklist(unsigned long addr)
@@ -2129,6 +2128,9 @@ static struct notifier_block kprobe_module_nb = {
 extern unsigned long __start_kprobe_blacklist[];
 extern unsigned long __stop_kprobe_blacklist[];
 
+/* Actual kprobes section range */
+DEFINE_SECTION_RANGE(kprobes, .text);
+
 static int __init init_kprobes(void)
 {
 	int i, err = 0;
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 29c89a6bad3d..2b442234c69b 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -894,7 +894,7 @@ static void check_section(const char *modname, struct elf_info *elf,
 
 #define DATA_SECTIONS ".data", ".data.rel"
 #define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \
-		".kprobes.text", ".cpuidle.text"
+		".text..rng.kprobes.any", ".cpuidle.text"
 #define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
 		".fixup", ".entry.text", ".exception.text", ".text.*", \
 		".coldtext"
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index aeb34223167c..6e95f3f87db1 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -417,7 +417,7 @@ is_mcounted_section_name(char const *const txtname)
 		strcmp(".spinlock.text", txtname) == 0 ||
 		strcmp(".irqentry.text", txtname) == 0 ||
 		strcmp(".softirqentry.text", txtname) == 0 ||
-		strcmp(".kprobes.text", txtname) == 0 ||
+		strcmp(".text..rng.kprobes.any", txtname) == 0 ||
 		strcmp(".cpuidle.text", txtname) == 0 ||
 		strcmp(".text.unlikely", txtname) == 0;
 }
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 0b6002b36f20..15e2fa37c489 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -135,7 +135,7 @@ my %text_sections = (
      ".spinlock.text" => 1,
      ".irqentry.text" => 1,
      ".softirqentry.text" => 1,
-     ".kprobes.text" => 1,
+     ".text..rng.kprobes.any" => 1,
      ".cpuidle.text" => 1,
      ".text.unlikely" => 1,
 );
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 13/14] kprobes: port blacklist kprobes to linker table
  2017-01-15 21:10         ` Luis R. Rodriguez
  (?)
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, konrad.wilk,
	jani.nikula, will.deacon, rusty

kprobe makes use of two sections, the one dealing with the actual
kprobes was recently ported using the standard section range API.
The blacklist functionality of kprobes is still using a custom
section and declaring its custom section using the linker script
as follows:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist

This ports the _kprobe_blacklist custom section to the standard
Linux linker table API allowing us remove all the custom blacklist
kprobe section declarations from the linker script.

This has been tested by trying to register a kprobe on a blacklisted
symbol (these are declared with NOKPROBE_SYMBOL()), and confirms that
this fails to work as expected. This was tested with:

 # insmod samples/kprobes/kprobe_example.ko symbol="get_kprobe"

This fails to load as expected with:

insmod: ERROR: could not insert module samples/kprobes/kprobe_example.ko: Invalid parameters

v5: Use push_section_tbl() for _ASM_NOKPROBE() for x86, and
    _ASM_NOKPROBE_SYMBOL() on powerpc
v4: ported over _ASM_NOKPROBE_SYMBOL() on powerpc and
    ASM_NOKPROBE() on x86
v3: this patch was introduced in this series

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/powerpc/include/asm/ppc_asm.h |  4 ++--
 arch/x86/include/asm/asm.h         |  4 +++-
 include/asm-generic/kprobes.h      |  4 ++--
 include/asm-generic/vmlinux.lds.h  | 10 ----------
 include/linux/kprobes.h            |  2 ++
 kernel/kprobes.c                   | 11 ++++-------
 6 files changed, 13 insertions(+), 22 deletions(-)

diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 0846413b3a2e..20cd9c00eef5 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,7 +9,7 @@
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
 #include <asm/firmware.h>
-#include <asm/ranges.h>
+#include <asm/tables.h>
 
 #ifdef __ASSEMBLY__
 
@@ -266,7 +266,7 @@ GLUE(.,name):
  */
 #ifdef CONFIG_KPROBES
 #define _ASM_NOKPROBE_SYMBOL(entry)			\
-	.pushsection "_kprobe_blacklist","aw";		\
+	push_section_tbl(.init.data, _kprobe_blacklist, any, aw); \
 	PPC_LONG (entry) ;				\
 	.popsection
 #else
diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
index 7acb51c49fec..48b1bc85c0e6 100644
--- a/arch/x86/include/asm/asm.h
+++ b/arch/x86/include/asm/asm.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_ASM_H
 #define _ASM_X86_ASM_H
 
+#include <asm/tables.h>
+
 #ifdef __ASSEMBLY__
 # define __ASM_FORM(x)	x
 # define __ASM_FORM_RAW(x)     x
@@ -74,7 +76,7 @@
 	_ASM_EXTABLE_HANDLE(from, to, ex_handler_ext)
 
 # define _ASM_NOKPROBE(entry)					\
-	.pushsection "_kprobe_blacklist","aw" ;			\
+	push_section_tbl_any(.init.data, _kprobe_blacklist, aw);\
 	_ASM_ALIGN ;						\
 	_ASM_PTR (entry);					\
 	.popsection
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 02a26b975187..7d29a208390e 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,14 +3,14 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <linux/tables.h>
 #include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
  */
 # define __NOKPROBE_SYMBOL(fname)				\
-static unsigned long __used					\
-	__attribute__((__section__("_kprobe_blacklist")))	\
+static LINKTABLE_INIT_DATA(_kprobe_blacklist, all)		\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 499caf5b4361..9f062af1f728 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -114,15 +114,6 @@
 #define BRANCH_PROFILE()
 #endif
 
-#ifdef CONFIG_KPROBES
-#define KPROBE_BLACKLIST()	. = ALIGN(8);				      \
-				VMLINUX_SYMBOL(__start_kprobe_blacklist) = .; \
-				KEEP(*(_kprobe_blacklist))		      \
-				VMLINUX_SYMBOL(__stop_kprobe_blacklist) = .;
-#else
-#define KPROBE_BLACKLIST()
-#endif
-
 #ifdef CONFIG_EVENT_TRACING
 #define FTRACE_EVENTS()	. = ALIGN(8);					\
 			VMLINUX_SYMBOL(__start_ftrace_events) = .;	\
@@ -551,7 +542,6 @@
 	*(.init.rodata)							\
 	FTRACE_EVENTS()							\
 	TRACE_SYSCALLS()						\
-	KPROBE_BLACKLIST()						\
 	MEM_DISCARD(init.rodata)					\
 	CLK_OF_TABLES()							\
 	RESERVEDMEM_OF_TABLES()						\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 445cc6fe7afa..2707820cbb56 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -44,8 +44,10 @@
 
 #ifdef CONFIG_KPROBES
 #include <linux/ranges.h>
+#include <linux/tables.h>
 
 DECLARE_SECTION_RANGE(kprobes);
+DECLARE_LINKTABLE(unsigned long, _kprobe_blacklist);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 82191f328e21..9d102ac95256 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -2053,14 +2053,13 @@ NOKPROBE_SYMBOL(dump_kprobe);
  * since a kprobe need not necessarily be at the beginning
  * of a function.
  */
-static int __init populate_kprobe_blacklist(unsigned long *start,
-					     unsigned long *end)
+static int __init populate_kprobe_blacklist(void)
 {
 	unsigned long *iter;
 	struct kprobe_blacklist_entry *ent;
 	unsigned long entry, offset = 0, size = 0;
 
-	for (iter = start; iter < end; iter++) {
+	linktable_for_each(iter, _kprobe_blacklist) {
 		entry = arch_deref_entry_point((void *)*iter);
 
 		if (!kernel_text_address(entry) ||
@@ -2125,8 +2124,7 @@ static struct notifier_block kprobe_module_nb = {
 };
 
 /* Markers of _kprobe_blacklist section */
-extern unsigned long __start_kprobe_blacklist[];
-extern unsigned long __stop_kprobe_blacklist[];
+DEFINE_LINKTABLE_INIT_DATA(unsigned long, _kprobe_blacklist);
 
 /* Actual kprobes section range */
 DEFINE_SECTION_RANGE(kprobes, .text);
@@ -2143,8 +2141,7 @@ static int __init init_kprobes(void)
 		raw_spin_lock_init(&(kretprobe_table_locks[i].lock));
 	}
 
-	err = populate_kprobe_blacklist(__start_kprobe_blacklist,
-					__stop_kprobe_blacklist);
+	err = populate_kprobe_blacklist();
 	if (err) {
 		pr_err("kprobes: failed to populate blacklist: %d\n", err);
 		pr_err("Please take care of using kprobes.\n");
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 13/14] kprobes: port blacklist kprobes to linker table
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: gnomes, linux-ia64, jkosina, benh, ming.lei, linux,
	platform-driver-x86, James.Bottomley, paul.gortmaker, paulus,
	sparclinux, wangnan0, mchehab, linux-arch, markus.heiser,
	xen-devel, msalter, linux-sh, mpe, joro, x86, fontana, dsahern,
	linux-arm-kernel, catalin.marinas, dvhart, dwmw2, linux,
	linux-xtensa, pali.rohar, keescook, arnd, konrad.wilk,
	jani.nikula, will.deacon, rusty

kprobe makes use of two sections, the one dealing with the actual
kprobes was recently ported using the standard section range API.
The blacklist functionality of kprobes is still using a custom
section and declaring its custom section using the linker script
as follows:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist

This ports the _kprobe_blacklist custom section to the standard
Linux linker table API allowing us remove all the custom blacklist
kprobe section declarations from the linker script.

This has been tested by trying to register a kprobe on a blacklisted
symbol (these are declared with NOKPROBE_SYMBOL()), and confirms that
this fails to work as expected. This was tested with:

 # insmod samples/kprobes/kprobe_example.ko symbol="get_kprobe"

This fails to load as expected with:

insmod: ERROR: could not insert module samples/kprobes/kprobe_example.ko: Invalid parameters

v5: Use push_section_tbl() for _ASM_NOKPROBE() for x86, and
    _ASM_NOKPROBE_SYMBOL() on powerpc
v4: ported over _ASM_NOKPROBE_SYMBOL() on powerpc and
    ASM_NOKPROBE() on x86
v3: this patch was introduced in this series

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/powerpc/include/asm/ppc_asm.h |  4 ++--
 arch/x86/include/asm/asm.h         |  4 +++-
 include/asm-generic/kprobes.h      |  4 ++--
 include/asm-generic/vmlinux.lds.h  | 10 ----------
 include/linux/kprobes.h            |  2 ++
 kernel/kprobes.c                   | 11 ++++-------
 6 files changed, 13 insertions(+), 22 deletions(-)

diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 0846413b3a2e..20cd9c00eef5 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,7 +9,7 @@
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
 #include <asm/firmware.h>
-#include <asm/ranges.h>
+#include <asm/tables.h>
 
 #ifdef __ASSEMBLY__
 
@@ -266,7 +266,7 @@ GLUE(.,name):
  */
 #ifdef CONFIG_KPROBES
 #define _ASM_NOKPROBE_SYMBOL(entry)			\
-	.pushsection "_kprobe_blacklist","aw";		\
+	push_section_tbl(.init.data, _kprobe_blacklist, any, aw); \
 	PPC_LONG (entry) ;				\
 	.popsection
 #else
diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
index 7acb51c49fec..48b1bc85c0e6 100644
--- a/arch/x86/include/asm/asm.h
+++ b/arch/x86/include/asm/asm.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_ASM_H
 #define _ASM_X86_ASM_H
 
+#include <asm/tables.h>
+
 #ifdef __ASSEMBLY__
 # define __ASM_FORM(x)	x
 # define __ASM_FORM_RAW(x)     x
@@ -74,7 +76,7 @@
 	_ASM_EXTABLE_HANDLE(from, to, ex_handler_ext)
 
 # define _ASM_NOKPROBE(entry)					\
-	.pushsection "_kprobe_blacklist","aw" ;			\
+	push_section_tbl_any(.init.data, _kprobe_blacklist, aw);\
 	_ASM_ALIGN ;						\
 	_ASM_PTR (entry);					\
 	.popsection
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 02a26b975187..7d29a208390e 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,14 +3,14 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <linux/tables.h>
 #include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
  */
 # define __NOKPROBE_SYMBOL(fname)				\
-static unsigned long __used					\
-	__attribute__((__section__("_kprobe_blacklist")))	\
+static LINKTABLE_INIT_DATA(_kprobe_blacklist, all)		\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 499caf5b4361..9f062af1f728 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -114,15 +114,6 @@
 #define BRANCH_PROFILE()
 #endif
 
-#ifdef CONFIG_KPROBES
-#define KPROBE_BLACKLIST()	. = ALIGN(8);				      \
-				VMLINUX_SYMBOL(__start_kprobe_blacklist) = .; \
-				KEEP(*(_kprobe_blacklist))		      \
-				VMLINUX_SYMBOL(__stop_kprobe_blacklist) = .;
-#else
-#define KPROBE_BLACKLIST()
-#endif
-
 #ifdef CONFIG_EVENT_TRACING
 #define FTRACE_EVENTS()	. = ALIGN(8);					\
 			VMLINUX_SYMBOL(__start_ftrace_events) = .;	\
@@ -551,7 +542,6 @@
 	*(.init.rodata)							\
 	FTRACE_EVENTS()							\
 	TRACE_SYSCALLS()						\
-	KPROBE_BLACKLIST()						\
 	MEM_DISCARD(init.rodata)					\
 	CLK_OF_TABLES()							\
 	RESERVEDMEM_OF_TABLES()						\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 445cc6fe7afa..2707820cbb56 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -44,8 +44,10 @@
 
 #ifdef CONFIG_KPROBES
 #include <linux/ranges.h>
+#include <linux/tables.h>
 
 DECLARE_SECTION_RANGE(kprobes);
+DECLARE_LINKTABLE(unsigned long, _kprobe_blacklist);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 82191f328e21..9d102ac95256 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -2053,14 +2053,13 @@ NOKPROBE_SYMBOL(dump_kprobe);
  * since a kprobe need not necessarily be at the beginning
  * of a function.
  */
-static int __init populate_kprobe_blacklist(unsigned long *start,
-					     unsigned long *end)
+static int __init populate_kprobe_blacklist(void)
 {
 	unsigned long *iter;
 	struct kprobe_blacklist_entry *ent;
 	unsigned long entry, offset = 0, size = 0;
 
-	for (iter = start; iter < end; iter++) {
+	linktable_for_each(iter, _kprobe_blacklist) {
 		entry = arch_deref_entry_point((void *)*iter);
 
 		if (!kernel_text_address(entry) ||
@@ -2125,8 +2124,7 @@ static struct notifier_block kprobe_module_nb = {
 };
 
 /* Markers of _kprobe_blacklist section */
-extern unsigned long __start_kprobe_blacklist[];
-extern unsigned long __stop_kprobe_blacklist[];
+DEFINE_LINKTABLE_INIT_DATA(unsigned long, _kprobe_blacklist);
 
 /* Actual kprobes section range */
 DEFINE_SECTION_RANGE(kprobes, .text);
@@ -2143,8 +2141,7 @@ static int __init init_kprobes(void)
 		raw_spin_lock_init(&(kretprobe_table_locks[i].lock));
 	}
 
-	err = populate_kprobe_blacklist(__start_kprobe_blacklist,
-					__stop_kprobe_blacklist);
+	err = populate_kprobe_blacklist();
 	if (err) {
 		pr_err("kprobes: failed to populate blacklist: %d\n", err);
 		pr_err("Please take care of using kprobes.\n");
-- 
2.11.0


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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 13/14] kprobes: port blacklist kprobes to linker table
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

kprobe makes use of two sections, the one dealing with the actual
kprobes was recently ported using the standard section range API.
The blacklist functionality of kprobes is still using a custom
section and declaring its custom section using the linker script
as follows:

type  Linux-section custom section name  begin                    end
table .init.data    _kprobe_blacklist    __start_kprobe_blacklist __stop_kprobe_blacklist

This ports the _kprobe_blacklist custom section to the standard
Linux linker table API allowing us remove all the custom blacklist
kprobe section declarations from the linker script.

This has been tested by trying to register a kprobe on a blacklisted
symbol (these are declared with NOKPROBE_SYMBOL()), and confirms that
this fails to work as expected. This was tested with:

 # insmod samples/kprobes/kprobe_example.ko symbol="get_kprobe"

This fails to load as expected with:

insmod: ERROR: could not insert module samples/kprobes/kprobe_example.ko: Invalid parameters

v5: Use push_section_tbl() for _ASM_NOKPROBE() for x86, and
    _ASM_NOKPROBE_SYMBOL() on powerpc
v4: ported over _ASM_NOKPROBE_SYMBOL() on powerpc and
    ASM_NOKPROBE() on x86
v3: this patch was introduced in this series

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 arch/powerpc/include/asm/ppc_asm.h |  4 ++--
 arch/x86/include/asm/asm.h         |  4 +++-
 include/asm-generic/kprobes.h      |  4 ++--
 include/asm-generic/vmlinux.lds.h  | 10 ----------
 include/linux/kprobes.h            |  2 ++
 kernel/kprobes.c                   | 11 ++++-------
 6 files changed, 13 insertions(+), 22 deletions(-)

diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 0846413b3a2e..20cd9c00eef5 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -9,7 +9,7 @@
 #include <asm/processor.h>
 #include <asm/ppc-opcode.h>
 #include <asm/firmware.h>
-#include <asm/ranges.h>
+#include <asm/tables.h>
 
 #ifdef __ASSEMBLY__
 
@@ -266,7 +266,7 @@ GLUE(.,name):
  */
 #ifdef CONFIG_KPROBES
 #define _ASM_NOKPROBE_SYMBOL(entry)			\
-	.pushsection "_kprobe_blacklist","aw";		\
+	push_section_tbl(.init.data, _kprobe_blacklist, any, aw); \
 	PPC_LONG (entry) ;				\
 	.popsection
 #else
diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
index 7acb51c49fec..48b1bc85c0e6 100644
--- a/arch/x86/include/asm/asm.h
+++ b/arch/x86/include/asm/asm.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_ASM_H
 #define _ASM_X86_ASM_H
 
+#include <asm/tables.h>
+
 #ifdef __ASSEMBLY__
 # define __ASM_FORM(x)	x
 # define __ASM_FORM_RAW(x)     x
@@ -74,7 +76,7 @@
 	_ASM_EXTABLE_HANDLE(from, to, ex_handler_ext)
 
 # define _ASM_NOKPROBE(entry)					\
-	.pushsection "_kprobe_blacklist","aw" ;			\
+	push_section_tbl_any(.init.data, _kprobe_blacklist, aw);\
 	_ASM_ALIGN ;						\
 	_ASM_PTR (entry);					\
 	.popsection
diff --git a/include/asm-generic/kprobes.h b/include/asm-generic/kprobes.h
index 02a26b975187..7d29a208390e 100644
--- a/include/asm-generic/kprobes.h
+++ b/include/asm-generic/kprobes.h
@@ -3,14 +3,14 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 #ifdef CONFIG_KPROBES
+#include <linux/tables.h>
 #include <asm/ranges.h>
 /*
  * Blacklist ganerating macro. Specify functions which is not probed
  * by using this macro.
  */
 # define __NOKPROBE_SYMBOL(fname)				\
-static unsigned long __used					\
-	__attribute__((__section__("_kprobe_blacklist")))	\
+static LINKTABLE_INIT_DATA(_kprobe_blacklist, all)		\
 	_kbl_addr_##fname = (unsigned long)fname;
 # define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
 /* Use this to forbid a kprobes attach on very low level functions */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 499caf5b4361..9f062af1f728 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -114,15 +114,6 @@
 #define BRANCH_PROFILE()
 #endif
 
-#ifdef CONFIG_KPROBES
-#define KPROBE_BLACKLIST()	. = ALIGN(8);				      \
-				VMLINUX_SYMBOL(__start_kprobe_blacklist) = .; \
-				KEEP(*(_kprobe_blacklist))		      \
-				VMLINUX_SYMBOL(__stop_kprobe_blacklist) = .;
-#else
-#define KPROBE_BLACKLIST()
-#endif
-
 #ifdef CONFIG_EVENT_TRACING
 #define FTRACE_EVENTS()	. = ALIGN(8);					\
 			VMLINUX_SYMBOL(__start_ftrace_events) = .;	\
@@ -551,7 +542,6 @@
 	*(.init.rodata)							\
 	FTRACE_EVENTS()							\
 	TRACE_SYSCALLS()						\
-	KPROBE_BLACKLIST()						\
 	MEM_DISCARD(init.rodata)					\
 	CLK_OF_TABLES()							\
 	RESERVEDMEM_OF_TABLES()						\
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 445cc6fe7afa..2707820cbb56 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -44,8 +44,10 @@
 
 #ifdef CONFIG_KPROBES
 #include <linux/ranges.h>
+#include <linux/tables.h>
 
 DECLARE_SECTION_RANGE(kprobes);
+DECLARE_LINKTABLE(unsigned long, _kprobe_blacklist);
 
 /* kprobe_status settings */
 #define KPROBE_HIT_ACTIVE	0x00000001
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 82191f328e21..9d102ac95256 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -2053,14 +2053,13 @@ NOKPROBE_SYMBOL(dump_kprobe);
  * since a kprobe need not necessarily be at the beginning
  * of a function.
  */
-static int __init populate_kprobe_blacklist(unsigned long *start,
-					     unsigned long *end)
+static int __init populate_kprobe_blacklist(void)
 {
 	unsigned long *iter;
 	struct kprobe_blacklist_entry *ent;
 	unsigned long entry, offset = 0, size = 0;
 
-	for (iter = start; iter < end; iter++) {
+	linktable_for_each(iter, _kprobe_blacklist) {
 		entry = arch_deref_entry_point((void *)*iter);
 
 		if (!kernel_text_address(entry) ||
@@ -2125,8 +2124,7 @@ static struct notifier_block kprobe_module_nb = {
 };
 
 /* Markers of _kprobe_blacklist section */
-extern unsigned long __start_kprobe_blacklist[];
-extern unsigned long __stop_kprobe_blacklist[];
+DEFINE_LINKTABLE_INIT_DATA(unsigned long, _kprobe_blacklist);
 
 /* Actual kprobes section range */
 DEFINE_SECTION_RANGE(kprobes, .text);
@@ -2143,8 +2141,7 @@ static int __init init_kprobes(void)
 		raw_spin_lock_init(&(kretprobe_table_locks[i].lock));
 	}
 
-	err = populate_kprobe_blacklist(__start_kprobe_blacklist,
-					__stop_kprobe_blacklist);
+	err = populate_kprobe_blacklist();
 	if (err) {
 		pr_err("kprobes: failed to populate blacklist: %d\n", err);
 		pr_err("Please take care of using kprobes.\n");
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 14/14] lib: add linker tables test driver
  2017-01-15 21:10         ` Luis R. Rodriguez
  (?)
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Add a test drivers for linker tables.

v7: address ./scripts/checkpatch.pl --codespell issues
v6: rename table macro as suggested by Andy Shevchenko
v5: added this commit for the first time in this series.

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

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


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 14/14] lib: add linker tables test driver
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Add a test drivers for linker tables.

v7: address ./scripts/checkpatch.pl --codespell issues
v6: rename table macro as suggested by Andy Shevchenko
v5: added this commit for the first time in this series.

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

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

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v7 14/14] lib: add linker tables test driver
@ 2017-01-15 21:10           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:10 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

Add a test drivers for linker tables.

v7: address ./scripts/checkpatch.pl --codespell issues
v6: rename table macro as suggested by Andy Shevchenko
v5: added this commit for the first time in this series.

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

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


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 0/6] tools: add linker table userspace sandbox
  2017-01-09 15:02         ` Luis R. Rodriguez
  (?)
@ 2017-01-15 21:12           ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:12 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This v4 also addresses some spelling / checkpatch comlplains.
The remaining checkpatch complaints are not valid for the
code in question. This applies after the series:

[PATCH v7 00/14] linux: generalize sections, ranges and linker tables

Luis R. Rodriguez (6):
  tools: add a userspace tools bug.h
  tools: add init.h for tools
  tools: add __used and enable to override
  tools: expand export.h with VMLINUX_SYMBOL()
  tools: add __section() to compiler.h
  tools: add userspace linker table sandbox

 Documentation/sections/linker-tables.rst           |   4 +-
 MAINTAINERS                                        |   1 +
 include/linux/tables.h                             |   5 +-
 tools/Makefile                                     |   3 +-
 .../arch/x86/include/generated/asm/section-core.h  |   1 +
 tools/arch/x86/include/generated/ranges.h          |   1 +
 tools/arch/x86/include/generated/tables.h          |   1 +
 tools/include/asm-generic/bug.h                    |  26 +
 tools/include/asm-generic/ranges.h                 |  93 +++
 tools/include/asm-generic/section-core.h           | 348 +++++++++++
 tools/include/asm-generic/tables.h                 |  48 ++
 tools/include/linux/bug.h                          |   6 +
 tools/include/linux/compiler.h                     |   8 +
 tools/include/linux/export.h                       |  22 +
 tools/include/linux/init.h                         |   9 +
 tools/include/linux/kernel.h                       |   2 +
 tools/include/linux/ranges.h                       | 183 ++++++
 tools/include/linux/sections.h                     |  87 +++
 tools/include/linux/string.h                       |   1 +
 tools/include/linux/tables.h                       | 684 +++++++++++++++++++++
 tools/linker-tables/.gitignore                     |   2 +
 tools/linker-tables/Makefile                       | 184 ++++++
 tools/linker-tables/README                         | 114 ++++
 tools/linker-tables/arch/x86/include/asm/asm.h     |  17 +
 tools/linker-tables/arch/x86/include/asm/boot.h    |   1 +
 .../linker-tables/arch/x86/include/asm/bootparam.h |  32 +
 tools/linker-tables/arch/x86/include/asm/kprobes.h |   7 +
 .../linker-tables/arch/x86/include/asm/ps_const.h  |  23 +
 tools/linker-tables/arch/x86/include/asm/ranges.h  |   6 +
 .../arch/x86/include/asm/section-core.h            |   1 +
 tools/linker-tables/arch/x86/include/asm/setup.h   |   6 +
 tools/linker-tables/arch/x86/include/asm/tables.h  |   6 +
 tools/linker-tables/arch/x86/include/asm/x86.h     |   4 +
 .../arch/x86/include/asm/x86_init_fn.h             | 169 +++++
 tools/linker-tables/arch/x86/kernel/alpha.c        |  10 +
 tools/linker-tables/arch/x86/kernel/alternative.c  |  31 +
 tools/linker-tables/arch/x86/kernel/beta.c         |  10 +
 tools/linker-tables/arch/x86/kernel/head64.c       |  58 ++
 tools/linker-tables/arch/x86/kernel/init.c         |  42 ++
 tools/linker-tables/arch/x86/kernel/kasan.c        |  11 +
 tools/linker-tables/arch/x86/kernel/kprobes.c      |  51 ++
 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S  | 277 +++++++++
 tools/linker-tables/arch/x86/mm/init.c             |  11 +
 tools/linker-tables/arch/x86/xen/init.c            |  13 +
 tools/linker-tables/drivers/acme.c                 |  33 +
 tools/linker-tables/drivers/synth/common.c         |  16 +
 tools/linker-tables/drivers/synth/common.h         |   2 +
 tools/linker-tables/drivers/synth/main.c           |  36 ++
 tools/linker-tables/drivers/synth/or.S             |  39 ++
 tools/linker-tables/drivers/synth/synth.h          |   2 +
 tools/linker-tables/drivers/xen-driver.c           |  12 +
 .../include/asm-generic/arch_init_fn.h             |  50 ++
 tools/linker-tables/include/asm-generic/kprobes.h  |  26 +
 tools/linker-tables/include/linux/bitops.h         |   6 +
 tools/linker-tables/include/linux/init.h           |  40 ++
 tools/linker-tables/include/linux/kasan.h          |   5 +
 tools/linker-tables/include/linux/kernel.h         |   2 +
 tools/linker-tables/include/linux/kprobes.h        |  11 +
 tools/linker-tables/include/linux/module.h         |  14 +
 tools/linker-tables/include/linux/mutex.h          |  17 +
 tools/linker-tables/include/linux/pci.h            |   7 +
 tools/linker-tables/include/linux/printk.h         |  26 +
 tools/linker-tables/include/linux/ps_const.h       |  46 ++
 tools/linker-tables/include/linux/sched.h          |   9 +
 tools/linker-tables/include/linux/spinlock.h       |  13 +
 tools/linker-tables/include/linux/start_kernel.h   |   1 +
 tools/linker-tables/include/linux/types.h          |  13 +
 tools/linker-tables/include/linux/workqueue.h      |  51 ++
 tools/linker-tables/include/xen/xen.h              |   4 +
 tools/linker-tables/kernel/locking/mutex.c         |  28 +
 tools/linker-tables/kernel/locking/spinlock.c      |  26 +
 tools/linker-tables/kernel/main.c                  |  32 +
 tools/linker-tables/kernel/workqueue.c             |  43 ++
 tools/linker-tables/lib/string.c                   |  26 +
 tools/linker-tables/main.c                         |  20 +
 tools/linker-tables/pci-quirks.c                   |  14 +
 tools/linker-tables/pci.c                          |  30 +
 77 files changed, 3314 insertions(+), 5 deletions(-)
 create mode 100644 tools/arch/x86/include/generated/asm/section-core.h
 create mode 100644 tools/arch/x86/include/generated/ranges.h
 create mode 100644 tools/arch/x86/include/generated/tables.h
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/asm-generic/ranges.h
 create mode 100644 tools/include/asm-generic/section-core.h
 create mode 100644 tools/include/asm-generic/tables.h
 create mode 100644 tools/include/linux/bug.h
 create mode 100644 tools/include/linux/init.h
 create mode 100644 tools/include/linux/ranges.h
 create mode 100644 tools/include/linux/sections.h
 create mode 100644 tools/include/linux/tables.h
 create mode 100644 tools/linker-tables/.gitignore
 create mode 100644 tools/linker-tables/Makefile
 create mode 100644 tools/linker-tables/README
 create mode 100644 tools/linker-tables/arch/x86/include/asm/asm.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/boot.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/bootparam.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/kprobes.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ps_const.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ranges.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/section-core.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/setup.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/tables.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
 create mode 100644 tools/linker-tables/arch/x86/kernel/alpha.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/alternative.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/beta.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/head64.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/init.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kasan.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kprobes.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
 create mode 100644 tools/linker-tables/arch/x86/mm/init.c
 create mode 100644 tools/linker-tables/arch/x86/xen/init.c
 create mode 100644 tools/linker-tables/drivers/acme.c
 create mode 100644 tools/linker-tables/drivers/synth/common.c
 create mode 100644 tools/linker-tables/drivers/synth/common.h
 create mode 100644 tools/linker-tables/drivers/synth/main.c
 create mode 100644 tools/linker-tables/drivers/synth/or.S
 create mode 100644 tools/linker-tables/drivers/synth/synth.h
 create mode 100644 tools/linker-tables/drivers/xen-driver.c
 create mode 100644 tools/linker-tables/include/asm-generic/arch_init_fn.h
 create mode 100644 tools/linker-tables/include/asm-generic/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/bitops.h
 create mode 100644 tools/linker-tables/include/linux/init.h
 create mode 100644 tools/linker-tables/include/linux/kasan.h
 create mode 100644 tools/linker-tables/include/linux/kernel.h
 create mode 100644 tools/linker-tables/include/linux/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/module.h
 create mode 100644 tools/linker-tables/include/linux/mutex.h
 create mode 100644 tools/linker-tables/include/linux/pci.h
 create mode 100644 tools/linker-tables/include/linux/printk.h
 create mode 100644 tools/linker-tables/include/linux/ps_const.h
 create mode 100644 tools/linker-tables/include/linux/sched.h
 create mode 100644 tools/linker-tables/include/linux/spinlock.h
 create mode 100644 tools/linker-tables/include/linux/start_kernel.h
 create mode 100644 tools/linker-tables/include/linux/types.h
 create mode 100644 tools/linker-tables/include/linux/workqueue.h
 create mode 100644 tools/linker-tables/include/xen/xen.h
 create mode 100644 tools/linker-tables/kernel/locking/mutex.c
 create mode 100644 tools/linker-tables/kernel/locking/spinlock.c
 create mode 100644 tools/linker-tables/kernel/main.c
 create mode 100644 tools/linker-tables/kernel/workqueue.c
 create mode 100644 tools/linker-tables/lib/string.c
 create mode 100644 tools/linker-tables/main.c
 create mode 100644 tools/linker-tables/pci-quirks.c
 create mode 100644 tools/linker-tables/pci.c

-- 
2.11.0


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v4 0/6] tools: add linker table userspace sandbox
@ 2017-01-15 21:12           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:12 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This v4 also addresses some spelling / checkpatch comlplains.
The remaining checkpatch complaints are not valid for the
code in question. This applies after the series:

[PATCH v7 00/14] linux: generalize sections, ranges and linker tables

Luis R. Rodriguez (6):
  tools: add a userspace tools bug.h
  tools: add init.h for tools
  tools: add __used and enable to override
  tools: expand export.h with VMLINUX_SYMBOL()
  tools: add __section() to compiler.h
  tools: add userspace linker table sandbox

 Documentation/sections/linker-tables.rst           |   4 +-
 MAINTAINERS                                        |   1 +
 include/linux/tables.h                             |   5 +-
 tools/Makefile                                     |   3 +-
 .../arch/x86/include/generated/asm/section-core.h  |   1 +
 tools/arch/x86/include/generated/ranges.h          |   1 +
 tools/arch/x86/include/generated/tables.h          |   1 +
 tools/include/asm-generic/bug.h                    |  26 +
 tools/include/asm-generic/ranges.h                 |  93 +++
 tools/include/asm-generic/section-core.h           | 348 +++++++++++
 tools/include/asm-generic/tables.h                 |  48 ++
 tools/include/linux/bug.h                          |   6 +
 tools/include/linux/compiler.h                     |   8 +
 tools/include/linux/export.h                       |  22 +
 tools/include/linux/init.h                         |   9 +
 tools/include/linux/kernel.h                       |   2 +
 tools/include/linux/ranges.h                       | 183 ++++++
 tools/include/linux/sections.h                     |  87 +++
 tools/include/linux/string.h                       |   1 +
 tools/include/linux/tables.h                       | 684 +++++++++++++++++++++
 tools/linker-tables/.gitignore                     |   2 +
 tools/linker-tables/Makefile                       | 184 ++++++
 tools/linker-tables/README                         | 114 ++++
 tools/linker-tables/arch/x86/include/asm/asm.h     |  17 +
 tools/linker-tables/arch/x86/include/asm/boot.h    |   1 +
 .../linker-tables/arch/x86/include/asm/bootparam.h |  32 +
 tools/linker-tables/arch/x86/include/asm/kprobes.h |   7 +
 .../linker-tables/arch/x86/include/asm/ps_const.h  |  23 +
 tools/linker-tables/arch/x86/include/asm/ranges.h  |   6 +
 .../arch/x86/include/asm/section-core.h            |   1 +
 tools/linker-tables/arch/x86/include/asm/setup.h   |   6 +
 tools/linker-tables/arch/x86/include/asm/tables.h  |   6 +
 tools/linker-tables/arch/x86/include/asm/x86.h     |   4 +
 .../arch/x86/include/asm/x86_init_fn.h             | 169 +++++
 tools/linker-tables/arch/x86/kernel/alpha.c        |  10 +
 tools/linker-tables/arch/x86/kernel/alternative.c  |  31 +
 tools/linker-tables/arch/x86/kernel/beta.c         |  10 +
 tools/linker-tables/arch/x86/kernel/head64.c       |  58 ++
 tools/linker-tables/arch/x86/kernel/init.c         |  42 ++
 tools/linker-tables/arch/x86/kernel/kasan.c        |  11 +
 tools/linker-tables/arch/x86/kernel/kprobes.c      |  51 ++
 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S  | 277 +++++++++
 tools/linker-tables/arch/x86/mm/init.c             |  11 +
 tools/linker-tables/arch/x86/xen/init.c            |  13 +
 tools/linker-tables/drivers/acme.c                 |  33 +
 tools/linker-tables/drivers/synth/common.c         |  16 +
 tools/linker-tables/drivers/synth/common.h         |   2 +
 tools/linker-tables/drivers/synth/main.c           |  36 ++
 tools/linker-tables/drivers/synth/or.S             |  39 ++
 tools/linker-tables/drivers/synth/synth.h          |   2 +
 tools/linker-tables/drivers/xen-driver.c           |  12 +
 .../include/asm-generic/arch_init_fn.h             |  50 ++
 tools/linker-tables/include/asm-generic/kprobes.h  |  26 +
 tools/linker-tables/include/linux/bitops.h         |   6 +
 tools/linker-tables/include/linux/init.h           |  40 ++
 tools/linker-tables/include/linux/kasan.h          |   5 +
 tools/linker-tables/include/linux/kernel.h         |   2 +
 tools/linker-tables/include/linux/kprobes.h        |  11 +
 tools/linker-tables/include/linux/module.h         |  14 +
 tools/linker-tables/include/linux/mutex.h          |  17 +
 tools/linker-tables/include/linux/pci.h            |   7 +
 tools/linker-tables/include/linux/printk.h         |  26 +
 tools/linker-tables/include/linux/ps_const.h       |  46 ++
 tools/linker-tables/include/linux/sched.h          |   9 +
 tools/linker-tables/include/linux/spinlock.h       |  13 +
 tools/linker-tables/include/linux/start_kernel.h   |   1 +
 tools/linker-tables/include/linux/types.h          |  13 +
 tools/linker-tables/include/linux/workqueue.h      |  51 ++
 tools/linker-tables/include/xen/xen.h              |   4 +
 tools/linker-tables/kernel/locking/mutex.c         |  28 +
 tools/linker-tables/kernel/locking/spinlock.c      |  26 +
 tools/linker-tables/kernel/main.c                  |  32 +
 tools/linker-tables/kernel/workqueue.c             |  43 ++
 tools/linker-tables/lib/string.c                   |  26 +
 tools/linker-tables/main.c                         |  20 +
 tools/linker-tables/pci-quirks.c                   |  14 +
 tools/linker-tables/pci.c                          |  30 +
 77 files changed, 3314 insertions(+), 5 deletions(-)
 create mode 100644 tools/arch/x86/include/generated/asm/section-core.h
 create mode 100644 tools/arch/x86/include/generated/ranges.h
 create mode 100644 tools/arch/x86/include/generated/tables.h
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/asm-generic/ranges.h
 create mode 100644 tools/include/asm-generic/section-core.h
 create mode 100644 tools/include/asm-generic/tables.h
 create mode 100644 tools/include/linux/bug.h
 create mode 100644 tools/include/linux/init.h
 create mode 100644 tools/include/linux/ranges.h
 create mode 100644 tools/include/linux/sections.h
 create mode 100644 tools/include/linux/tables.h
 create mode 100644 tools/linker-tables/.gitignore
 create mode 100644 tools/linker-tables/Makefile
 create mode 100644 tools/linker-tables/README
 create mode 100644 tools/linker-tables/arch/x86/include/asm/asm.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/boot.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/bootparam.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/kprobes.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ps_const.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ranges.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/section-core.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/setup.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/tables.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
 create mode 100644 tools/linker-tables/arch/x86/kernel/alpha.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/alternative.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/beta.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/head64.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/init.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kasan.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kprobes.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
 create mode 100644 tools/linker-tables/arch/x86/mm/init.c
 create mode 100644 tools/linker-tables/arch/x86/xen/init.c
 create mode 100644 tools/linker-tables/drivers/acme.c
 create mode 100644 tools/linker-tables/drivers/synth/common.c
 create mode 100644 tools/linker-tables/drivers/synth/common.h
 create mode 100644 tools/linker-tables/drivers/synth/main.c
 create mode 100644 tools/linker-tables/drivers/synth/or.S
 create mode 100644 tools/linker-tables/drivers/synth/synth.h
 create mode 100644 tools/linker-tables/drivers/xen-driver.c
 create mode 100644 tools/linker-tables/include/asm-generic/arch_init_fn.h
 create mode 100644 tools/linker-tables/include/asm-generic/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/bitops.h
 create mode 100644 tools/linker-tables/include/linux/init.h
 create mode 100644 tools/linker-tables/include/linux/kasan.h
 create mode 100644 tools/linker-tables/include/linux/kernel.h
 create mode 100644 tools/linker-tables/include/linux/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/module.h
 create mode 100644 tools/linker-tables/include/linux/mutex.h
 create mode 100644 tools/linker-tables/include/linux/pci.h
 create mode 100644 tools/linker-tables/include/linux/printk.h
 create mode 100644 tools/linker-tables/include/linux/ps_const.h
 create mode 100644 tools/linker-tables/include/linux/sched.h
 create mode 100644 tools/linker-tables/include/linux/spinlock.h
 create mode 100644 tools/linker-tables/include/linux/start_kernel.h
 create mode 100644 tools/linker-tables/include/linux/types.h
 create mode 100644 tools/linker-tables/include/linux/workqueue.h
 create mode 100644 tools/linker-tables/include/xen/xen.h
 create mode 100644 tools/linker-tables/kernel/locking/mutex.c
 create mode 100644 tools/linker-tables/kernel/locking/spinlock.c
 create mode 100644 tools/linker-tables/kernel/main.c
 create mode 100644 tools/linker-tables/kernel/workqueue.c
 create mode 100644 tools/linker-tables/lib/string.c
 create mode 100644 tools/linker-tables/main.c
 create mode 100644 tools/linker-tables/pci-quirks.c
 create mode 100644 tools/linker-tables/pci.c

-- 
2.11.0


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v4 0/6] tools: add linker table userspace sandbox
@ 2017-01-15 21:12           ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:12 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

This v4 also addresses some spelling / checkpatch comlplains.
The remaining checkpatch complaints are not valid for the
code in question. This applies after the series:

[PATCH v7 00/14] linux: generalize sections, ranges and linker tables

Luis R. Rodriguez (6):
  tools: add a userspace tools bug.h
  tools: add init.h for tools
  tools: add __used and enable to override
  tools: expand export.h with VMLINUX_SYMBOL()
  tools: add __section() to compiler.h
  tools: add userspace linker table sandbox

 Documentation/sections/linker-tables.rst           |   4 +-
 MAINTAINERS                                        |   1 +
 include/linux/tables.h                             |   5 +-
 tools/Makefile                                     |   3 +-
 .../arch/x86/include/generated/asm/section-core.h  |   1 +
 tools/arch/x86/include/generated/ranges.h          |   1 +
 tools/arch/x86/include/generated/tables.h          |   1 +
 tools/include/asm-generic/bug.h                    |  26 +
 tools/include/asm-generic/ranges.h                 |  93 +++
 tools/include/asm-generic/section-core.h           | 348 +++++++++++
 tools/include/asm-generic/tables.h                 |  48 ++
 tools/include/linux/bug.h                          |   6 +
 tools/include/linux/compiler.h                     |   8 +
 tools/include/linux/export.h                       |  22 +
 tools/include/linux/init.h                         |   9 +
 tools/include/linux/kernel.h                       |   2 +
 tools/include/linux/ranges.h                       | 183 ++++++
 tools/include/linux/sections.h                     |  87 +++
 tools/include/linux/string.h                       |   1 +
 tools/include/linux/tables.h                       | 684 +++++++++++++++++++++
 tools/linker-tables/.gitignore                     |   2 +
 tools/linker-tables/Makefile                       | 184 ++++++
 tools/linker-tables/README                         | 114 ++++
 tools/linker-tables/arch/x86/include/asm/asm.h     |  17 +
 tools/linker-tables/arch/x86/include/asm/boot.h    |   1 +
 .../linker-tables/arch/x86/include/asm/bootparam.h |  32 +
 tools/linker-tables/arch/x86/include/asm/kprobes.h |   7 +
 .../linker-tables/arch/x86/include/asm/ps_const.h  |  23 +
 tools/linker-tables/arch/x86/include/asm/ranges.h  |   6 +
 .../arch/x86/include/asm/section-core.h            |   1 +
 tools/linker-tables/arch/x86/include/asm/setup.h   |   6 +
 tools/linker-tables/arch/x86/include/asm/tables.h  |   6 +
 tools/linker-tables/arch/x86/include/asm/x86.h     |   4 +
 .../arch/x86/include/asm/x86_init_fn.h             | 169 +++++
 tools/linker-tables/arch/x86/kernel/alpha.c        |  10 +
 tools/linker-tables/arch/x86/kernel/alternative.c  |  31 +
 tools/linker-tables/arch/x86/kernel/beta.c         |  10 +
 tools/linker-tables/arch/x86/kernel/head64.c       |  58 ++
 tools/linker-tables/arch/x86/kernel/init.c         |  42 ++
 tools/linker-tables/arch/x86/kernel/kasan.c        |  11 +
 tools/linker-tables/arch/x86/kernel/kprobes.c      |  51 ++
 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S  | 277 +++++++++
 tools/linker-tables/arch/x86/mm/init.c             |  11 +
 tools/linker-tables/arch/x86/xen/init.c            |  13 +
 tools/linker-tables/drivers/acme.c                 |  33 +
 tools/linker-tables/drivers/synth/common.c         |  16 +
 tools/linker-tables/drivers/synth/common.h         |   2 +
 tools/linker-tables/drivers/synth/main.c           |  36 ++
 tools/linker-tables/drivers/synth/or.S             |  39 ++
 tools/linker-tables/drivers/synth/synth.h          |   2 +
 tools/linker-tables/drivers/xen-driver.c           |  12 +
 .../include/asm-generic/arch_init_fn.h             |  50 ++
 tools/linker-tables/include/asm-generic/kprobes.h  |  26 +
 tools/linker-tables/include/linux/bitops.h         |   6 +
 tools/linker-tables/include/linux/init.h           |  40 ++
 tools/linker-tables/include/linux/kasan.h          |   5 +
 tools/linker-tables/include/linux/kernel.h         |   2 +
 tools/linker-tables/include/linux/kprobes.h        |  11 +
 tools/linker-tables/include/linux/module.h         |  14 +
 tools/linker-tables/include/linux/mutex.h          |  17 +
 tools/linker-tables/include/linux/pci.h            |   7 +
 tools/linker-tables/include/linux/printk.h         |  26 +
 tools/linker-tables/include/linux/ps_const.h       |  46 ++
 tools/linker-tables/include/linux/sched.h          |   9 +
 tools/linker-tables/include/linux/spinlock.h       |  13 +
 tools/linker-tables/include/linux/start_kernel.h   |   1 +
 tools/linker-tables/include/linux/types.h          |  13 +
 tools/linker-tables/include/linux/workqueue.h      |  51 ++
 tools/linker-tables/include/xen/xen.h              |   4 +
 tools/linker-tables/kernel/locking/mutex.c         |  28 +
 tools/linker-tables/kernel/locking/spinlock.c      |  26 +
 tools/linker-tables/kernel/main.c                  |  32 +
 tools/linker-tables/kernel/workqueue.c             |  43 ++
 tools/linker-tables/lib/string.c                   |  26 +
 tools/linker-tables/main.c                         |  20 +
 tools/linker-tables/pci-quirks.c                   |  14 +
 tools/linker-tables/pci.c                          |  30 +
 77 files changed, 3314 insertions(+), 5 deletions(-)
 create mode 100644 tools/arch/x86/include/generated/asm/section-core.h
 create mode 100644 tools/arch/x86/include/generated/ranges.h
 create mode 100644 tools/arch/x86/include/generated/tables.h
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/asm-generic/ranges.h
 create mode 100644 tools/include/asm-generic/section-core.h
 create mode 100644 tools/include/asm-generic/tables.h
 create mode 100644 tools/include/linux/bug.h
 create mode 100644 tools/include/linux/init.h
 create mode 100644 tools/include/linux/ranges.h
 create mode 100644 tools/include/linux/sections.h
 create mode 100644 tools/include/linux/tables.h
 create mode 100644 tools/linker-tables/.gitignore
 create mode 100644 tools/linker-tables/Makefile
 create mode 100644 tools/linker-tables/README
 create mode 100644 tools/linker-tables/arch/x86/include/asm/asm.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/boot.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/bootparam.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/kprobes.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ps_const.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ranges.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/section-core.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/setup.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/tables.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
 create mode 100644 tools/linker-tables/arch/x86/kernel/alpha.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/alternative.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/beta.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/head64.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/init.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kasan.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kprobes.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
 create mode 100644 tools/linker-tables/arch/x86/mm/init.c
 create mode 100644 tools/linker-tables/arch/x86/xen/init.c
 create mode 100644 tools/linker-tables/drivers/acme.c
 create mode 100644 tools/linker-tables/drivers/synth/common.c
 create mode 100644 tools/linker-tables/drivers/synth/common.h
 create mode 100644 tools/linker-tables/drivers/synth/main.c
 create mode 100644 tools/linker-tables/drivers/synth/or.S
 create mode 100644 tools/linker-tables/drivers/synth/synth.h
 create mode 100644 tools/linker-tables/drivers/xen-driver.c
 create mode 100644 tools/linker-tables/include/asm-generic/arch_init_fn.h
 create mode 100644 tools/linker-tables/include/asm-generic/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/bitops.h
 create mode 100644 tools/linker-tables/include/linux/init.h
 create mode 100644 tools/linker-tables/include/linux/kasan.h
 create mode 100644 tools/linker-tables/include/linux/kernel.h
 create mode 100644 tools/linker-tables/include/linux/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/module.h
 create mode 100644 tools/linker-tables/include/linux/mutex.h
 create mode 100644 tools/linker-tables/include/linux/pci.h
 create mode 100644 tools/linker-tables/include/linux/printk.h
 create mode 100644 tools/linker-tables/include/linux/ps_const.h
 create mode 100644 tools/linker-tables/include/linux/sched.h
 create mode 100644 tools/linker-tables/include/linux/spinlock.h
 create mode 100644 tools/linker-tables/include/linux/start_kernel.h
 create mode 100644 tools/linker-tables/include/linux/types.h
 create mode 100644 tools/linker-tables/include/linux/workqueue.h
 create mode 100644 tools/linker-tables/include/xen/xen.h
 create mode 100644 tools/linker-tables/kernel/locking/mutex.c
 create mode 100644 tools/linker-tables/kernel/locking/spinlock.c
 create mode 100644 tools/linker-tables/kernel/main.c
 create mode 100644 tools/linker-tables/kernel/workqueue.c
 create mode 100644 tools/linker-tables/lib/string.c
 create mode 100644 tools/linker-tables/main.c
 create mode 100644 tools/linker-tables/pci-quirks.c
 create mode 100644 tools/linker-tables/pci.c

-- 
2.11.0


^ permalink raw reply	[flat|nested] 480+ messages in thread

* [PATCH v4 1/6] tools: add a userspace tools bug.h
  2017-01-15 21:12           ` Luis R. Rodriguez
  (?)
@ 2017-01-15 21:12             ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:12 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This will be used later by the userspace linker-tables sandbox.
As a convenience, include bug.h on kernel.h -- this is not done
on upstream kernel.h, however most header files do include bug.h
eventually, if we were to only add the ones that need it we'd
need to copy a lot of headers to tools for the only purpose of
includeing bug.h. This simplifies that.

v4: address ./scripts/checkpatch.pl --codespell complaints

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/asm-generic/bug.h | 26 ++++++++++++++++++++++++++
 tools/include/linux/bug.h       |  6 ++++++
 tools/include/linux/kernel.h    |  2 ++
 3 files changed, 34 insertions(+)
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/linux/bug.h

diff --git a/tools/include/asm-generic/bug.h b/tools/include/asm-generic/bug.h
new file mode 100644
index 000000000000..6c9889e2b764
--- /dev/null
+++ b/tools/include/asm-generic/bug.h
@@ -0,0 +1,26 @@
+#ifndef __TOOLS_ASM_GENERIC_BUG
+#define __TOOLS_ASM_GENERIC_BUG
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define BUG() do {							\
+	fprintf(stderr, "------------------------------------------n");	\
+	fprintf(stderr, "BUG on %s at %s: %i\n",			\
+		__func__, __FILE__, __LINE__);				\
+	abort();							\
+}									\
+while (0)
+
+#define BUG_ON(cond) do { if (cond) BUG(); } while (0)
+
+#define WARN_ON(__test) do {						\
+	if (__test) {							\
+		fprintf(stderr, "----------------------------------n");	\
+		fprintf(stderr, "WARN_ON on %s at %s: %i\n",		\
+			 __func__, __FILE__, __LINE__);			\
+	}								\
+}									\
+while (0)
+
+#endif /* __TOOLS_ASM_GENERIC_BUG */
diff --git a/tools/include/linux/bug.h b/tools/include/linux/bug.h
new file mode 100644
index 000000000000..9be515b40b5c
--- /dev/null
+++ b/tools/include/linux/bug.h
@@ -0,0 +1,6 @@
+#ifndef _TOOLS_LINUX_BUG_H
+#define _TOOLS_LINUX_BUG_H
+
+#include <asm-generic/bug.h>
+
+#endif /* _TOOLS_LINUX_BUG_H */
diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
index 28607db02bd3..3d385a6d4fc1 100644
--- a/tools/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -5,6 +5,8 @@
 #include <stddef.h>
 #include <assert.h>
 
+#include <linux/bug.h>
+
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 
 #define PERF_ALIGN(x, a)	__PERF_ALIGN_MASK(x, (typeof(x))(a)-1)
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 1/6] tools: add a userspace tools bug.h
@ 2017-01-15 21:12             ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:12 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This will be used later by the userspace linker-tables sandbox.
As a convenience, include bug.h on kernel.h -- this is not done
on upstream kernel.h, however most header files do include bug.h
eventually, if we were to only add the ones that need it we'd
need to copy a lot of headers to tools for the only purpose of
includeing bug.h. This simplifies that.

v4: address ./scripts/checkpatch.pl --codespell complaints

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/asm-generic/bug.h | 26 ++++++++++++++++++++++++++
 tools/include/linux/bug.h       |  6 ++++++
 tools/include/linux/kernel.h    |  2 ++
 3 files changed, 34 insertions(+)
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/linux/bug.h

diff --git a/tools/include/asm-generic/bug.h b/tools/include/asm-generic/bug.h
new file mode 100644
index 000000000000..6c9889e2b764
--- /dev/null
+++ b/tools/include/asm-generic/bug.h
@@ -0,0 +1,26 @@
+#ifndef __TOOLS_ASM_GENERIC_BUG
+#define __TOOLS_ASM_GENERIC_BUG
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define BUG() do {							\
+	fprintf(stderr, "------------------------------------------n");	\
+	fprintf(stderr, "BUG on %s at %s: %i\n",			\
+		__func__, __FILE__, __LINE__);				\
+	abort();							\
+}									\
+while (0)
+
+#define BUG_ON(cond) do { if (cond) BUG(); } while (0)
+
+#define WARN_ON(__test) do {						\
+	if (__test) {							\
+		fprintf(stderr, "----------------------------------n");	\
+		fprintf(stderr, "WARN_ON on %s at %s: %i\n",		\
+			 __func__, __FILE__, __LINE__);			\
+	}								\
+}									\
+while (0)
+
+#endif /* __TOOLS_ASM_GENERIC_BUG */
diff --git a/tools/include/linux/bug.h b/tools/include/linux/bug.h
new file mode 100644
index 000000000000..9be515b40b5c
--- /dev/null
+++ b/tools/include/linux/bug.h
@@ -0,0 +1,6 @@
+#ifndef _TOOLS_LINUX_BUG_H
+#define _TOOLS_LINUX_BUG_H
+
+#include <asm-generic/bug.h>
+
+#endif /* _TOOLS_LINUX_BUG_H */
diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
index 28607db02bd3..3d385a6d4fc1 100644
--- a/tools/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -5,6 +5,8 @@
 #include <stddef.h>
 #include <assert.h>
 
+#include <linux/bug.h>
+
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 
 #define PERF_ALIGN(x, a)	__PERF_ALIGN_MASK(x, (typeof(x))(a)-1)
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 1/6] tools: add a userspace tools bug.h
@ 2017-01-15 21:12             ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:12 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

This will be used later by the userspace linker-tables sandbox.
As a convenience, include bug.h on kernel.h -- this is not done
on upstream kernel.h, however most header files do include bug.h
eventually, if we were to only add the ones that need it we'd
need to copy a lot of headers to tools for the only purpose of
includeing bug.h. This simplifies that.

v4: address ./scripts/checkpatch.pl --codespell complaints

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/asm-generic/bug.h | 26 ++++++++++++++++++++++++++
 tools/include/linux/bug.h       |  6 ++++++
 tools/include/linux/kernel.h    |  2 ++
 3 files changed, 34 insertions(+)
 create mode 100644 tools/include/asm-generic/bug.h
 create mode 100644 tools/include/linux/bug.h

diff --git a/tools/include/asm-generic/bug.h b/tools/include/asm-generic/bug.h
new file mode 100644
index 000000000000..6c9889e2b764
--- /dev/null
+++ b/tools/include/asm-generic/bug.h
@@ -0,0 +1,26 @@
+#ifndef __TOOLS_ASM_GENERIC_BUG
+#define __TOOLS_ASM_GENERIC_BUG
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define BUG() do {							\
+	fprintf(stderr, "------------------------------------------n");	\
+	fprintf(stderr, "BUG on %s at %s: %i\n",			\
+		__func__, __FILE__, __LINE__);				\
+	abort();							\
+}									\
+while (0)
+
+#define BUG_ON(cond) do { if (cond) BUG(); } while (0)
+
+#define WARN_ON(__test) do {						\
+	if (__test) {							\
+		fprintf(stderr, "----------------------------------n");	\
+		fprintf(stderr, "WARN_ON on %s at %s: %i\n",		\
+			 __func__, __FILE__, __LINE__);			\
+	}								\
+}									\
+while (0)
+
+#endif /* __TOOLS_ASM_GENERIC_BUG */
diff --git a/tools/include/linux/bug.h b/tools/include/linux/bug.h
new file mode 100644
index 000000000000..9be515b40b5c
--- /dev/null
+++ b/tools/include/linux/bug.h
@@ -0,0 +1,6 @@
+#ifndef _TOOLS_LINUX_BUG_H
+#define _TOOLS_LINUX_BUG_H
+
+#include <asm-generic/bug.h>
+
+#endif /* _TOOLS_LINUX_BUG_H */
diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
index 28607db02bd3..3d385a6d4fc1 100644
--- a/tools/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -5,6 +5,8 @@
 #include <stddef.h>
 #include <assert.h>
 
+#include <linux/bug.h>
+
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 
 #define PERF_ALIGN(x, a)	__PERF_ALIGN_MASK(x, (typeof(x))(a)-1)
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 2/6] tools: add init.h for tools
  2017-01-15 21:12           ` Luis R. Rodriguez
  (?)
@ 2017-01-15 21:12             ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:12 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Start off with just __ref -- we enalbe you to override, if you do
that then you can define your own. The way you'd use this, if you
do override, is define your own __ref and then use include_next.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/init.h | 9 +++++++++
 1 file changed, 9 insertions(+)
 create mode 100644 tools/include/linux/init.h

diff --git a/tools/include/linux/init.h b/tools/include/linux/init.h
new file mode 100644
index 000000000000..6d970a360a05
--- /dev/null
+++ b/tools/include/linux/init.h
@@ -0,0 +1,9 @@
+#ifndef _TOOLS_LINUX_INIT_H
+#define _TOOLS_LINUX_INIT_H
+
+/* this means you can add your own to fit you own userspace needs */
+#ifndef __ref
+#define __ref
+#endif
+
+#endif /* _TOOLS_LINUX_INIT_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 2/6] tools: add init.h for tools
@ 2017-01-15 21:12             ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:12 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Start off with just __ref -- we enalbe you to override, if you do
that then you can define your own. The way you'd use this, if you
do override, is define your own __ref and then use include_next.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/init.h | 9 +++++++++
 1 file changed, 9 insertions(+)
 create mode 100644 tools/include/linux/init.h

diff --git a/tools/include/linux/init.h b/tools/include/linux/init.h
new file mode 100644
index 000000000000..6d970a360a05
--- /dev/null
+++ b/tools/include/linux/init.h
@@ -0,0 +1,9 @@
+#ifndef _TOOLS_LINUX_INIT_H
+#define _TOOLS_LINUX_INIT_H
+
+/* this means you can add your own to fit you own userspace needs */
+#ifndef __ref
+#define __ref
+#endif
+
+#endif /* _TOOLS_LINUX_INIT_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 2/6] tools: add init.h for tools
@ 2017-01-15 21:12             ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:12 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

Start off with just __ref -- we enalbe you to override, if you do
that then you can define your own. The way you'd use this, if you
do override, is define your own __ref and then use include_next.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/init.h | 9 +++++++++
 1 file changed, 9 insertions(+)
 create mode 100644 tools/include/linux/init.h

diff --git a/tools/include/linux/init.h b/tools/include/linux/init.h
new file mode 100644
index 000000000000..6d970a360a05
--- /dev/null
+++ b/tools/include/linux/init.h
@@ -0,0 +1,9 @@
+#ifndef _TOOLS_LINUX_INIT_H
+#define _TOOLS_LINUX_INIT_H
+
+/* this means you can add your own to fit you own userspace needs */
+#ifndef __ref
+#define __ref
+#endif
+
+#endif /* _TOOLS_LINUX_INIT_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 3/6] tools: add __used and enable to override
  2017-01-15 21:12           ` Luis R. Rodriguez
  (?)
@ 2017-01-15 21:12             ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:12 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This adds __used, to be used later in the userspace linker-tables
sandbox. If any userspace applicaiton wants to override they can
add their own definition and then use include_next.

This definition should probably suffice for most uses cases though.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index e33fc1df3935..556c991de212 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -5,6 +5,12 @@
 /* The "volatile" is due to gcc bugs */
 #define barrier() __asm__ __volatile__("": : :"memory")
 
+
+/* You can override as you see fit on your userspace tool */
+#ifndef __used
+#define __used          __attribute__((__used__))
+#endif
+
 #ifndef __always_inline
 # define __always_inline	inline __attribute__((always_inline))
 #endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 3/6] tools: add __used and enable to override
@ 2017-01-15 21:12             ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:12 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This adds __used, to be used later in the userspace linker-tables
sandbox. If any userspace applicaiton wants to override they can
add their own definition and then use include_next.

This definition should probably suffice for most uses cases though.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index e33fc1df3935..556c991de212 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -5,6 +5,12 @@
 /* The "volatile" is due to gcc bugs */
 #define barrier() __asm__ __volatile__("": : :"memory")
 
+
+/* You can override as you see fit on your userspace tool */
+#ifndef __used
+#define __used          __attribute__((__used__))
+#endif
+
 #ifndef __always_inline
 # define __always_inline	inline __attribute__((always_inline))
 #endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 3/6] tools: add __used and enable to override
@ 2017-01-15 21:12             ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:12 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

This adds __used, to be used later in the userspace linker-tables
sandbox. If any userspace applicaiton wants to override they can
add their own definition and then use include_next.

This definition should probably suffice for most uses cases though.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index e33fc1df3935..556c991de212 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -5,6 +5,12 @@
 /* The "volatile" is due to gcc bugs */
 #define barrier() __asm__ __volatile__("": : :"memory")
 
+
+/* You can override as you see fit on your userspace tool */
+#ifndef __used
+#define __used          __attribute__((__used__))
+#endif
+
 #ifndef __always_inline
 # define __always_inline	inline __attribute__((always_inline))
 #endif
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 4/6] tools: expand export.h with VMLINUX_SYMBOL()
  2017-01-15 21:12           ` Luis R. Rodriguez
  (?)
@ 2017-01-15 21:12             ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:12 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This will be used later by the linker-table userspace sandbox.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/export.h | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/tools/include/linux/export.h b/tools/include/linux/export.h
index d07e586b9ba0..cb7d6b490e08 100644
--- a/tools/include/linux/export.h
+++ b/tools/include/linux/export.h
@@ -1,6 +1,28 @@
 #ifndef _TOOLS_LINUX_EXPORT_H_
 #define _TOOLS_LINUX_EXPORT_H_
 
+/*
+ * Export symbols from the kernel to modules.  Forked from module.h
+ * to reduce the amount of pointless cruft we feed to gcc when only
+ * exporting a simple symbol or two.
+ *
+ * Try not to add #includes here.  It slows compilation and makes kernel
+ * hackers place grumpy comments in header files.
+ */
+
+/* Some toolchains use a `_' prefix for all user symbols. */
+#ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX
+#define __VMLINUX_SYMBOL(x) _##x
+#define __VMLINUX_SYMBOL_STR(x) "_" #x
+#else
+#define __VMLINUX_SYMBOL(x) x
+#define __VMLINUX_SYMBOL_STR(x) #x
+#endif
+
+/* Indirect, so macros are expanded before pasting. */
+#define VMLINUX_SYMBOL(x) __VMLINUX_SYMBOL(x)
+#define VMLINUX_SYMBOL_STR(x) __VMLINUX_SYMBOL_STR(x)
+
 #define EXPORT_SYMBOL(sym)
 #define EXPORT_SYMBOL_GPL(sym)
 #define EXPORT_SYMBOL_GPL_FUTURE(sym)
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 4/6] tools: expand export.h with VMLINUX_SYMBOL()
@ 2017-01-15 21:12             ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:12 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This will be used later by the linker-table userspace sandbox.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/export.h | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/tools/include/linux/export.h b/tools/include/linux/export.h
index d07e586b9ba0..cb7d6b490e08 100644
--- a/tools/include/linux/export.h
+++ b/tools/include/linux/export.h
@@ -1,6 +1,28 @@
 #ifndef _TOOLS_LINUX_EXPORT_H_
 #define _TOOLS_LINUX_EXPORT_H_
 
+/*
+ * Export symbols from the kernel to modules.  Forked from module.h
+ * to reduce the amount of pointless cruft we feed to gcc when only
+ * exporting a simple symbol or two.
+ *
+ * Try not to add #includes here.  It slows compilation and makes kernel
+ * hackers place grumpy comments in header files.
+ */
+
+/* Some toolchains use a `_' prefix for all user symbols. */
+#ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX
+#define __VMLINUX_SYMBOL(x) _##x
+#define __VMLINUX_SYMBOL_STR(x) "_" #x
+#else
+#define __VMLINUX_SYMBOL(x) x
+#define __VMLINUX_SYMBOL_STR(x) #x
+#endif
+
+/* Indirect, so macros are expanded before pasting. */
+#define VMLINUX_SYMBOL(x) __VMLINUX_SYMBOL(x)
+#define VMLINUX_SYMBOL_STR(x) __VMLINUX_SYMBOL_STR(x)
+
 #define EXPORT_SYMBOL(sym)
 #define EXPORT_SYMBOL_GPL(sym)
 #define EXPORT_SYMBOL_GPL_FUTURE(sym)
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 4/6] tools: expand export.h with VMLINUX_SYMBOL()
@ 2017-01-15 21:12             ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:12 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

This will be used later by the linker-table userspace sandbox.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/export.h | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/tools/include/linux/export.h b/tools/include/linux/export.h
index d07e586b9ba0..cb7d6b490e08 100644
--- a/tools/include/linux/export.h
+++ b/tools/include/linux/export.h
@@ -1,6 +1,28 @@
 #ifndef _TOOLS_LINUX_EXPORT_H_
 #define _TOOLS_LINUX_EXPORT_H_
 
+/*
+ * Export symbols from the kernel to modules.  Forked from module.h
+ * to reduce the amount of pointless cruft we feed to gcc when only
+ * exporting a simple symbol or two.
+ *
+ * Try not to add #includes here.  It slows compilation and makes kernel
+ * hackers place grumpy comments in header files.
+ */
+
+/* Some toolchains use a `_' prefix for all user symbols. */
+#ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX
+#define __VMLINUX_SYMBOL(x) _##x
+#define __VMLINUX_SYMBOL_STR(x) "_" #x
+#else
+#define __VMLINUX_SYMBOL(x) x
+#define __VMLINUX_SYMBOL_STR(x) #x
+#endif
+
+/* Indirect, so macros are expanded before pasting. */
+#define VMLINUX_SYMBOL(x) __VMLINUX_SYMBOL(x)
+#define VMLINUX_SYMBOL_STR(x) __VMLINUX_SYMBOL_STR(x)
+
 #define EXPORT_SYMBOL(sym)
 #define EXPORT_SYMBOL_GPL(sym)
 #define EXPORT_SYMBOL_GPL_FUTURE(sym)
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 5/6] tools: add __section() to compiler.h
  2017-01-15 21:12           ` Luis R. Rodriguez
  (?)
@ 2017-01-15 21:12             ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:12 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This will be used later by the userspace linker table.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index 556c991de212..6321265df00a 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -132,4 +132,6 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 #define WRITE_ONCE(x, val) \
 	({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
 
+#define __section(S)	__attribute__ ((__section__(#S)))
+
 #endif /* _TOOLS_LINUX_COMPILER_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 5/6] tools: add __section() to compiler.h
@ 2017-01-15 21:12             ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:12 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

This will be used later by the userspace linker table.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index 556c991de212..6321265df00a 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -132,4 +132,6 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 #define WRITE_ONCE(x, val) \
 	({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
 
+#define __section(S)	__attribute__ ((__section__(#S)))
+
 #endif /* _TOOLS_LINUX_COMPILER_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 5/6] tools: add __section() to compiler.h
@ 2017-01-15 21:12             ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:12 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley,
	Luis R. Rodriguez

This will be used later by the userspace linker table.

Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 tools/include/linux/compiler.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index 556c991de212..6321265df00a 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -132,4 +132,6 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
 #define WRITE_ONCE(x, val) \
 	({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; })
 
+#define __section(S)	__attribute__ ((__section__(#S)))
+
 #endif /* _TOOLS_LINUX_COMPILER_H */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 6/6] tools: add userspace linker table sandbox
  2017-01-15 21:12           ` Luis R. Rodriguez
@ 2017-01-15 21:12             ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:12 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Add a userspace sandbox to allow easy experimentation and
test extensions with linker tables, section ranges and the
new section core definitions.

The userspace sandbox tries to mimic the Linux kernel development
flow as much as possible, it however relies on and uses libc. Support
is currently only provided to x86_64.

Demo run:

cd tools/linker-tables
make clean; make;
./demo
Initializing x86 bare metal world
x86-init: Number of init entries: 8
Initializing memory ...
Completed initializing memory !
Initializing pci ...
PCI fixup size: 1
Demo: Using LINKTABLE_FOR_EACH
foo_fixup
Demo: Using LINKTABLE_RUN_ALL
foo_fixup
Completed initializing pci !
Number of init entries: 1
Initializing kprobes ...
== OK: test_kprobe_0001 within range!
== OK: test_kprobe_0002 not in range as expected!
Completed initializing kprobes !
Initializing kasan ...
Early init for Kasan...
Completed initializing kasan !
Initializing beta ...
Completed initializing beta !
Initializing alpha ...
Completed initializing alpha !
Booting bare metal
Calling start_kernel()...
ACME: Initializing ...
ACME: Finished init ... !
Synthetics: synth_init_or(2) returns: 0xDEADBEEF
Synthetics: ps_shr(0xDEADBEEF, get_demo_shr) returns: 0x0000DEAD

v7: address ./scripts/checkpatch.pl --codespell complaints

v6: rename table macros as suggested by Andy Shevchenko

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clashes with compiler generated
  sections.

o moves tools/include/linux/printk.h to tools
  linker-table/include/linux/printk.h -- we cannot generalize this
  just yet, more work is needed in terms of providing a namespace for
  headers for types of ports of kernel functionality to userspace.

o Adjust code according to the latest discussions for the linker
  tables API (section name macros are now gone).

o Give CONFIG_HAVE_ARCH_PS_CONST for x86 another good 'ol college try,
  still fails, but this is just a demo anyway. We can amend and fix
  make this more optimized for x86 later. Thanks Boris!

v4: this patch is new in this series -- added to the kenrel as
    suggested by Boris, as otherwise it'd be really hard to keep
    an external userspace repository in sync.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/linker-tables.rst           |   4 +-
 MAINTAINERS                                        |   1 +
 include/linux/tables.h                             |   5 +-
 tools/Makefile                                     |   3 +-
 .../arch/x86/include/generated/asm/section-core.h  |   1 +
 tools/arch/x86/include/generated/ranges.h          |   1 +
 tools/arch/x86/include/generated/tables.h          |   1 +
 tools/include/asm-generic/ranges.h                 |  93 +++
 tools/include/asm-generic/section-core.h           | 348 +++++++++++
 tools/include/asm-generic/tables.h                 |  48 ++
 tools/include/linux/ranges.h                       | 183 ++++++
 tools/include/linux/sections.h                     |  87 +++
 tools/include/linux/string.h                       |   1 +
 tools/include/linux/tables.h                       | 684 +++++++++++++++++++++
 tools/linker-tables/.gitignore                     |   2 +
 tools/linker-tables/Makefile                       | 184 ++++++
 tools/linker-tables/README                         | 114 ++++
 tools/linker-tables/arch/x86/include/asm/asm.h     |  17 +
 tools/linker-tables/arch/x86/include/asm/boot.h    |   1 +
 .../linker-tables/arch/x86/include/asm/bootparam.h |  32 +
 tools/linker-tables/arch/x86/include/asm/kprobes.h |   7 +
 .../linker-tables/arch/x86/include/asm/ps_const.h  |  23 +
 tools/linker-tables/arch/x86/include/asm/ranges.h  |   6 +
 .../arch/x86/include/asm/section-core.h            |   1 +
 tools/linker-tables/arch/x86/include/asm/setup.h   |   6 +
 tools/linker-tables/arch/x86/include/asm/tables.h  |   6 +
 tools/linker-tables/arch/x86/include/asm/x86.h     |   4 +
 .../arch/x86/include/asm/x86_init_fn.h             | 169 +++++
 tools/linker-tables/arch/x86/kernel/alpha.c        |  10 +
 tools/linker-tables/arch/x86/kernel/alternative.c  |  31 +
 tools/linker-tables/arch/x86/kernel/beta.c         |  10 +
 tools/linker-tables/arch/x86/kernel/head64.c       |  58 ++
 tools/linker-tables/arch/x86/kernel/init.c         |  42 ++
 tools/linker-tables/arch/x86/kernel/kasan.c        |  11 +
 tools/linker-tables/arch/x86/kernel/kprobes.c      |  51 ++
 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S  | 277 +++++++++
 tools/linker-tables/arch/x86/mm/init.c             |  11 +
 tools/linker-tables/arch/x86/xen/init.c            |  13 +
 tools/linker-tables/drivers/acme.c                 |  33 +
 tools/linker-tables/drivers/synth/common.c         |  16 +
 tools/linker-tables/drivers/synth/common.h         |   2 +
 tools/linker-tables/drivers/synth/main.c           |  36 ++
 tools/linker-tables/drivers/synth/or.S             |  39 ++
 tools/linker-tables/drivers/synth/synth.h          |   2 +
 tools/linker-tables/drivers/xen-driver.c           |  12 +
 .../include/asm-generic/arch_init_fn.h             |  50 ++
 tools/linker-tables/include/asm-generic/kprobes.h  |  26 +
 tools/linker-tables/include/linux/bitops.h         |   6 +
 tools/linker-tables/include/linux/init.h           |  40 ++
 tools/linker-tables/include/linux/kasan.h          |   5 +
 tools/linker-tables/include/linux/kernel.h         |   2 +
 tools/linker-tables/include/linux/kprobes.h        |  11 +
 tools/linker-tables/include/linux/module.h         |  14 +
 tools/linker-tables/include/linux/mutex.h          |  17 +
 tools/linker-tables/include/linux/pci.h            |   7 +
 tools/linker-tables/include/linux/printk.h         |  26 +
 tools/linker-tables/include/linux/ps_const.h       |  46 ++
 tools/linker-tables/include/linux/sched.h          |   9 +
 tools/linker-tables/include/linux/spinlock.h       |  13 +
 tools/linker-tables/include/linux/start_kernel.h   |   1 +
 tools/linker-tables/include/linux/types.h          |  13 +
 tools/linker-tables/include/linux/workqueue.h      |  51 ++
 tools/linker-tables/include/xen/xen.h              |   4 +
 tools/linker-tables/kernel/locking/mutex.c         |  28 +
 tools/linker-tables/kernel/locking/spinlock.c      |  26 +
 tools/linker-tables/kernel/main.c                  |  32 +
 tools/linker-tables/kernel/workqueue.c             |  43 ++
 tools/linker-tables/lib/string.c                   |  26 +
 tools/linker-tables/main.c                         |  20 +
 tools/linker-tables/pci-quirks.c                   |  14 +
 tools/linker-tables/pci.c                          |  30 +
 71 files changed, 3241 insertions(+), 5 deletions(-)
 create mode 100644 tools/arch/x86/include/generated/asm/section-core.h
 create mode 100644 tools/arch/x86/include/generated/ranges.h
 create mode 100644 tools/arch/x86/include/generated/tables.h
 create mode 100644 tools/include/asm-generic/ranges.h
 create mode 100644 tools/include/asm-generic/section-core.h
 create mode 100644 tools/include/asm-generic/tables.h
 create mode 100644 tools/include/linux/ranges.h
 create mode 100644 tools/include/linux/sections.h
 create mode 100644 tools/include/linux/tables.h
 create mode 100644 tools/linker-tables/.gitignore
 create mode 100644 tools/linker-tables/Makefile
 create mode 100644 tools/linker-tables/README
 create mode 100644 tools/linker-tables/arch/x86/include/asm/asm.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/boot.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/bootparam.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/kprobes.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ps_const.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ranges.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/section-core.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/setup.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/tables.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
 create mode 100644 tools/linker-tables/arch/x86/kernel/alpha.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/alternative.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/beta.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/head64.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/init.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kasan.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kprobes.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
 create mode 100644 tools/linker-tables/arch/x86/mm/init.c
 create mode 100644 tools/linker-tables/arch/x86/xen/init.c
 create mode 100644 tools/linker-tables/drivers/acme.c
 create mode 100644 tools/linker-tables/drivers/synth/common.c
 create mode 100644 tools/linker-tables/drivers/synth/common.h
 create mode 100644 tools/linker-tables/drivers/synth/main.c
 create mode 100644 tools/linker-tables/drivers/synth/or.S
 create mode 100644 tools/linker-tables/drivers/synth/synth.h
 create mode 100644 tools/linker-tables/drivers/xen-driver.c
 create mode 100644 tools/linker-tables/include/asm-generic/arch_init_fn.h
 create mode 100644 tools/linker-tables/include/asm-generic/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/bitops.h
 create mode 100644 tools/linker-tables/include/linux/init.h
 create mode 100644 tools/linker-tables/include/linux/kasan.h
 create mode 100644 tools/linker-tables/include/linux/kernel.h
 create mode 100644 tools/linker-tables/include/linux/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/module.h
 create mode 100644 tools/linker-tables/include/linux/mutex.h
 create mode 100644 tools/linker-tables/include/linux/pci.h
 create mode 100644 tools/linker-tables/include/linux/printk.h
 create mode 100644 tools/linker-tables/include/linux/ps_const.h
 create mode 100644 tools/linker-tables/include/linux/sched.h
 create mode 100644 tools/linker-tables/include/linux/spinlock.h
 create mode 100644 tools/linker-tables/include/linux/start_kernel.h
 create mode 100644 tools/linker-tables/include/linux/types.h
 create mode 100644 tools/linker-tables/include/linux/workqueue.h
 create mode 100644 tools/linker-tables/include/xen/xen.h
 create mode 100644 tools/linker-tables/kernel/locking/mutex.c
 create mode 100644 tools/linker-tables/kernel/locking/spinlock.c
 create mode 100644 tools/linker-tables/kernel/main.c
 create mode 100644 tools/linker-tables/kernel/workqueue.c
 create mode 100644 tools/linker-tables/lib/string.c
 create mode 100644 tools/linker-tables/main.c
 create mode 100644 tools/linker-tables/pci-quirks.c
 create mode 100644 tools/linker-tables/pci.c

diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index bc2d9f46cde6..2f2bb1fc0798 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -11,11 +11,11 @@ About Linker tables
 .. kernel-doc:: include/linux/tables.h
    :doc: Introduction
 
-Linker table provenance
+Linker table provenance and userspace testing
 ---------------------------------------------
 
 .. kernel-doc:: include/linux/tables.h
-   :doc: Linker table provenance
+   :doc: Linker table provenance and userspace testing
 
 Benefits of using Linker tables
 ===============================
diff --git a/MAINTAINERS b/MAINTAINERS
index cee1efd50e04..b83bd957011e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5429,6 +5429,7 @@ L:	linux-kernel@vger.kernel.org
 S:	Supported
 F:	include/asm-generic/tables.h
 F:	include/linux/tables.h
+F:	tools/linker-tables/
 F:	Documentation/sections/linker-tables.rst
 
 GENERIC PHY FRAMEWORK
diff --git a/include/linux/tables.h b/include/linux/tables.h
index f295fbe74734..9dd8f947b60b 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -35,12 +35,13 @@
  */
 
 /**
- * DOC: Linker table provenance
+ * DOC: Linker table provenance and userspace testing
  *
  * 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].
+ * userspace linker-table tree [1]. Linux has a similar userspace application
+ * in tools/linker-tables/ to help more easily test adding new extensions.
  *
  * Contrary to iPXE's solution which strives to force compilation of
  * everything using linker tables, Linux's solution allows for developers to be
diff --git a/tools/Makefile b/tools/Makefile
index 00caacd3ed92..ecb2e651c930 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -19,6 +19,7 @@ help:
 	@echo '  kvm_stat               - top-like utility for displaying kvm statistics'
 	@echo '  leds                   - LEDs  tools'
 	@echo '  lguest                 - a minimal 32-bit x86 hypervisor'
+	@echo '  linker-tables		- userspace liker table sandbox and related tools'
 	@echo '  net                    - misc networking tools'
 	@echo '  perf                   - Linux performance measurement and analysis tool'
 	@echo '  selftests              - various kernel selftests'
@@ -86,7 +87,7 @@ tmon: FORCE
 freefall: FORCE
 	$(call descend,laptop/$@)
 
-all: acpi cgroup cpupower gpio hv firewire lguest \
+all: acpi cgroup cpupower gpio hv firewire lguest linker-tables \
 		perf selftests turbostat usb \
 		virtio vm net x86_energy_perf_policy \
 		tmon freefall objtool
diff --git a/tools/arch/x86/include/generated/asm/section-core.h b/tools/arch/x86/include/generated/asm/section-core.h
new file mode 100644
index 000000000000..06be2b1c424f
--- /dev/null
+++ b/tools/arch/x86/include/generated/asm/section-core.h
@@ -0,0 +1 @@
+#include <asm-generic/section-core.h>
diff --git a/tools/arch/x86/include/generated/ranges.h b/tools/arch/x86/include/generated/ranges.h
new file mode 100644
index 000000000000..dac1a9a11367
--- /dev/null
+++ b/tools/arch/x86/include/generated/ranges.h
@@ -0,0 +1 @@
+#include <asm-generic/ranges.h>
diff --git a/tools/arch/x86/include/generated/tables.h b/tools/arch/x86/include/generated/tables.h
new file mode 100644
index 000000000000..d437818275c5
--- /dev/null
+++ b/tools/arch/x86/include/generated/tables.h
@@ -0,0 +1 @@
+#include <asm-generic/tables.h>
diff --git a/tools/include/asm-generic/ranges.h b/tools/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..10e67bcf6dbe
--- /dev/null
+++ b/tools/include/asm-generic/ranges.h
@@ -0,0 +1,93 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  any, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       any, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   any, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(#section "..rng.name.any")))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using binutils
+ *	SORT(), the number is sorted as a string, as such be sure to fill with
+ *	zeroes any empty digits. For instance if you are using 3 levels of
+ *	digits for order levels, use 001 for the first entry, 0002 for the
+ *	second, 999 for the last entry. You can use however many digits you
+ *	need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(#section "..rng.name." #level)))
+
+#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/tools/include/asm-generic/section-core.h b/tools/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..e2db4da87222
--- /dev/null
+++ b/tools/include/asm-generic/section-core.h
@@ -0,0 +1,348 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Linux ELF program specific sections
+ *
+ * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and
+ * definition of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
+ * sections. This chapter is dedicated to documenting Linux program specific
+ * sections and helpers available to make use of these easier to implement and
+ * use.
+ *
+ * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
+ */
+
+/**
+ * DOC: Linux linker script
+ *
+ * Linux uses a custom linker script to build the vmlinux binary, it uses it to
+ * strategically place and define Linux ELF sections.  Each architecture needs
+ * to implement its own linker script, it is expected to reside in
+ * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
+ * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
+ * as well as some helpers documented in this chapter.
+ *
+ * In assembly it is common practice to use dots (``.``) in labels to avoid
+ * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
+ * name but not a C symbol. Historically then, two dots are used (``..``)
+ * have been used in linker scripts when adding program specific sections
+ * when there are concerns to avoid clashes with compiler generated sections.
+ */
+
+/**
+ * DOC: Memory protection
+ *
+ * Linux allows architectures which support memory protection features to
+ * take advantage of them by letting architectures define and enable
+ * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.
+ * mark_rodata_ro() can be used for instance to mark specific sections as
+ * read-only or non-executable.
+ *
+ * Linux typically follows a convention to have the .rodata ELF section follow
+ * after the .text ELF section, it does this to help architectures which
+ * support memory protection to mark both .text and .rodata as read-only in
+ * one shot.
+ *
+ * For more details refer to mark_rodata_ro().
+ */
+
+/**
+ * DOC: .rodata
+ *
+ * ELF section used for data which must be protected from write access.
+ */
+
+/**
+ * DOC: .text
+ *
+ * ELF section name used for code (functions) used during regular
+ * kernel run time.
+ */
+
+/**
+ * DOC: .data
+ *
+ * ELF section used for read-write data.
+ */
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: .init.text
+ *
+ * ELF section for code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+
+/**
+ * DOC: .init.data
+ *
+ * ELF section used for data structures used only during boot or driver
+ * initialization.
+ */
+
+/**
+ * DOC: .init.rodata
+ *
+ * ELF section used for read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+
+/**
+ * DOC: .initcall
+ *
+ * ELF section used for subsystem init calls. There are init levels
+ * representing different functionality in the kernel. For more details
+ * refer to __define_initcall().
+ */
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: .exit.text
+ *
+ * ELF section used to for code (functions) used only during module unload.
+ */
+
+/**
+ * DOC: .exit.data
+ *
+ * ELF section used to for data structures used only during module
+ * unload.
+ */
+
+/**
+ * DOC: .exitcall.exit
+ *
+ * ELF section used for exit routines, order is important and maintained by
+ * link order.
+ */
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: .ref.text
+ *
+ * ELF section used to annotate code (functions) which has been vetted as
+ * valid for its reference or use of other code (functions) or data structures
+ * which are part of the init sections.
+ */
+
+/**
+ * DOC: .ref.data
+ *
+ * ELF section used for data structures which have been vetted for its
+ * reference or use of other code (functions) or data structures part of the
+ * init sections.
+ */
+
+/**
+ * DOC: .ref.rodata
+ *
+ * ELF section used to annotate const code (functions) const data structures
+ * which has been vetted for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections alpha numerically. Linux has historically used 'SORT()' in
+ * ``include/asm-generic/vmlinux.lds.h``, its a well established practice. If
+ * 'SORT()' is used on a section one can provide ordering using a postfix on
+ * each section entry added. For instance if a linker script uses::
+ *
+ *    SORT(.foo.*)
+ *
+ * one can then add entries with explicit ordering using numeric postfixes for
+ * each entry, we refer to these as 'order levels'. Since 'SORT()' sorts alpha
+ * numerically a specific series set of digits must be agreed a-priori which
+ * would give also an idea of the max expected number of entries added to a
+ * section. For instance, if you expect a maximum of 999 entries you can use
+ * 3 digits for a section order level. If you wanted an entry to be ordered
+ * first you could use the postfix '000', if you wanted an entry to follow this
+ * you could use '001', and so on. We could for instance have::
+ *
+ *    .foo.000
+ *    .foo.001
+ *    .foo.002
+ *
+ * Often times one may want the option to specify no order is required for
+ * certain elements added to a section which does use 'SORT()' on the linker
+ * script. You can use any arbitrary string value to to specify no order is
+ * used, so long as its used consistantly. For instance, one possibility is to
+ * use the 'any' postfix.  All entries on the section would then have no
+ * specific ordering::
+ *
+ *    .foo.any
+ *    .foo.any
+ *    .foo.any
+ *
+ * To help establish a convention we reserve the special name 'any' for this
+ * purpose. Developers can use and expect the 'any' postfix string on sections
+ * as a helper to annotate section ordering at link time is not relevant
+ * for entries on a section.
+ */
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section..___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section..__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifndef LINKER_SCRIPT
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align=16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/tools/include/asm-generic/tables.h b/tools/include/asm-generic/tables.h
new file mode 100644
index 000000000000..567775b292c2
--- /dev/null
+++ b/tools/include/asm-generic/tables.h
@@ -0,0 +1,48 @@
+#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..tbl.name.level
+
+/* Some toolchains are buggy, let them override */
+#ifndef SECTION_TBL_RO
+# define SECTION_TBL_RO	.rodata
+#endif
+
+#define SECTION_TBL_RO_STR __stringify(SECTION_TBL_RO)
+
+#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, 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, any, flags)
+#endif
+
+#endif /* _ASM_GENERIC_TABLES_H_ */
diff --git a/tools/include/linux/ranges.h b/tools/include/linux/ranges.h
new file mode 100644
index 000000000000..3368fc475cd8
--- /dev/null
+++ b/tools/include/linux/ranges.h
@@ -0,0 +1,183 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * SECTION_RANGE_START - get address of start of section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the start address of the section range.
+ * This should give you the address of the first entry.
+ *
+ */
+#define SECTION_RANGE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * SECTION_RANGE_END - get address of end of the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define SECTION_RANGE_END(name)		LINUX_SECTION_END(name)
+
+/**
+ * SECTION_RANGE_SIZE - get number of entries in the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the number of entries in the section range.
+ * Example usage:
+ *
+ *   unsigned int num_ents = LINKTABLE_SIZE(some_fns);
+ */
+#define SECTION_RANGE_SIZE(name)					\
+	((SECTION_RANGE_END(name)) - (SECTION_RANGE_START(name)))
+
+/**
+ * SECTION_RANGE_EMPTY - check if section range has no entries
+ *
+ * @name: name of the section range
+ *
+ * Returns true if the section range is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(some_fns);
+ */
+#define SECTION_RANGE_EMPTY(name)	(SECTION_RANGE_SIZE(name) == 0)
+
+/**
+ * SECTION_RANGE_ADDR_WITHIN - returns true if address is in the section range
+ *
+ * @name: name of the section range
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_RANGE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) SECTION_RANGE_START(name) &&		\
+	  addr < (unsigned long) SECTION_RANGE_END(name))
+
+/**
+ * SECTION_RANGE_ALIGNMENT - get the alignment of the section range
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the section range.
+ */
+#define SECTION_RANGE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.")))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.~")))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) SECTION_RANGE_START(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) SECTION_RANGE_END(name)[0] = {}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
diff --git a/tools/include/linux/sections.h b/tools/include/linux/sections.h
new file mode 100644
index 000000000000..6771c727bcd1
--- /dev/null
+++ b/tools/include/linux/sections.h
@@ -0,0 +1,87 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_CORE(section, core, name, level)			\
+	#section ".." #core "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
diff --git a/tools/include/linux/string.h b/tools/include/linux/string.h
index f436d2420a18..a6b12564bbd9 100644
--- a/tools/include/linux/string.h
+++ b/tools/include/linux/string.h
@@ -3,6 +3,7 @@
 
 
 #include <linux/types.h>	/* for size_t */
+#include <string.h>
 
 void *memdup(const void *src, size_t len);
 
diff --git a/tools/include/linux/tables.h b/tools/include/linux/tables.h
new file mode 100644
index 000000000000..9dd8f947b60b
--- /dev/null
+++ b/tools/include/linux/tables.h
@@ -0,0 +1,684 @@
+#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 and userspace testing
+ *
+ * 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]. Linux has a similar userspace application
+ * in tools/linker-tables/ to help more easily test adding new extensions.
+ *
+ * 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(.foo..tbl.*))
+ *
+ * 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: The code bit-rot problem
+ *
+ * Linux provides a rich array of features, enabling each feature
+ * however increases the size of the kernel and there are many
+ * features which users often want disabled. The traditional
+ * solution to this problem is for each feature to have its own
+ * Kconfig symbol, followed by a series of #ifdef statements
+ * in C code and header files, allowing the feature to be compiled
+ * only when desirable. As the variability of Linux increases build
+ * tests can and are often done with random kernel configurations,
+ * allyesconfig, and allmodconfig to help find code issues. This
+ * however doesn't catch all errors and as a consequence code that
+ * is typically not enabled often can suffer from bit-rot over time.
+ */
+
+/**
+ * DOC: The build-all selective-link philosophy
+ *
+ * A code architecture philosophy to help avoid code bit-rot consists
+ * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
+ * by instead having each feature implemented it its own C file, and force
+ * compilation for all features. Only features that are enabled get linked in,
+ * the forced compilation therefore has no size impact on the final result of
+ * the kernel. The practice of having each feature implemented in its own C
+ * file is already prevalent in many subsystems, however #ifdefs are still
+ * typically required during feature initialization. For instance in::
+ *
+ *	#ifdef CONFIG_FOO
+ *	foo_init();
+ *	#endif
+ *
+ * We cannot remove the #ifdef and leave foo_init() as we'd either
+ * need to always enable the feature or add a respective #ifdef in a
+ * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem with linker tables
+ *
+ * Linker tables can be used to further help avoid the code bit-rot problem
+ * when embracing the 'build-all selective-link philosophy' by lifting the
+ * requirement to use of #ifdefs during initialization. With linker tables
+ * initialization sequences can be aggregated into a custom ELF section at
+ * link time, during run time the table can be iterated over and each init
+ * sequence enabled can be called. A feature's init routine is only added to a
+ * table when its respective Kconfig symbols has been enabled and therefore
+ * linked in. Linker tables enable subsystems to completely do away with
+ * #ifdefs if one is comfortable in accepting all subsystem's feature's
+ * structural size implications.
+ *
+ * To further help with this the Linux build system supports two special
+ * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
+ * follow the 'build-all selective-link philosophy' can use these targets for a
+ * feature's kconfig symbol. Using these targets will always require
+ * compilation of the kconfig's objects if the kconfig symbol's dependencies
+ * are met but only link the objects into the kernel, and therefore enable the
+ * feature, if and only if the kconfig symbol has been enabled.
+ *
+ * Not all users or build systems may want to opt-in to compile all objects
+ * following the 'build-all selective-link philosophy', as such the targets
+ * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
+ * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
+ * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
+ * ``obj-y`` and ``lib-y`` respectively.
+ *
+ * Example use::
+ *
+ *	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+ */
+
+/**
+ * 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_START - get address of start of linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the start address of the linker table.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINKTABLE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * LINKTABLE_END - get address of end of the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define LINKTABLE_END(name)	LINUX_SECTION_END(name)
+
+/**
+ * LINKTABLE_SIZE - get number of entries in the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the number of entries in the linker table.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINKTABLE_SIZE(frobnicator_fns);
+ */
+#define LINKTABLE_SIZE(name)					\
+	((LINKTABLE_END(name)) - (LINKTABLE_START(name)))
+
+/**
+ * LINKTABLE_EMPTY - check if linker table has no entries
+ *
+ * @name: name of linker table
+ *
+ * Returns true if the linker table is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(frobnicator_fns);
+ */
+#define LINKTABLE_EMPTY(name)	(LINKTABLE_SIZE(name) == 0)
+
+/**
+ * LINKTABLE_ADDR_WITHIN - returns true if address is in the linker table
+ *
+ * @name: name of the linker table
+ * @addr: address to query for
+ *
+ * Returns true if the address is part of the linker table.
+ */
+#define LINKTABLE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) LINKTABLE_START(name) &&		\
+	  addr < (unsigned long) LINKTABLE_END(name))
+
+/**
+ * LINKTABLE_ALIGNMENT - get the alignment of the linker table
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the linker table.
+ */
+#define LINKTABLE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * 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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_TEXT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE_RO(name, ~) LINKTABLE_END(name)[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_RO(type, name);				\
+	LINKTABLE_INIT_WEAK(name,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT_DATA(name, ~) LINKTABLE_END(name)[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 = LINKTABLE_START(tbl);				\
+	     pointer < LINKTABLE_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 < LINKTABLE_SIZE(tbl); i++)			\
+		(LINKTABLE_START(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 < LINKTABLE_SIZE(tbl); i++)		\
+		err = (LINKTABLE_START(tbl)[i]).func(args);		\
+	err;								\
+})
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_LINKER_TABLES_H */
diff --git a/tools/linker-tables/.gitignore b/tools/linker-tables/.gitignore
new file mode 100644
index 000000000000..8275b0c55385
--- /dev/null
+++ b/tools/linker-tables/.gitignore
@@ -0,0 +1,2 @@
+arch/x86/kernel/vmlinux.lds
+demo
diff --git a/tools/linker-tables/Makefile b/tools/linker-tables/Makefile
new file mode 100644
index 000000000000..9d4e6fb0d176
--- /dev/null
+++ b/tools/linker-tables/Makefile
@@ -0,0 +1,184 @@
+include ../scripts/Makefile.include
+
+all:
+
+include ../scripts/utilities.mak
+
+MAKEFLAGS += --no-print-directory
+
+unexport LC_ALL
+LC_COLLATE=C
+LC_NUMERIC=C
+export LC_COLLATE LC_NUMERIC
+
+ifeq ($(srctree),)
+	srctree := $(patsubst %/,%,$(dir $(shell pwd)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Determined 'srctree' to be $(srctree))
+endif
+
+ifneq ($(objtree),)
+#$(info Determined 'objtree' to be $(objtree))
+endif
+
+ifneq ($(OUTPUT),)
+#$(info Determined 'OUTPUT' to be $(OUTPUT))
+# Adding $(OUTPUT) as a directory to look for source files,
+# because use generated output files as sources dependency
+# for flex/bison parsers.
+VPATH += $(OUTPUT)
+export VPATH
+endif
+
+export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK
+include $(srctree)/tools/build/Makefile.include
+
+ifeq ($(V),1)
+	Q=
+	NQ=@true
+else
+	Q=@
+	NQ=@echo
+endif
+
+MAKEFLAGS += -r
+
+define allow-override
+  $(if $(or $(findstring environment,$(origin $(1))),\
+            $(findstring command line,$(origin $(1)))),,\
+    $(eval $(1) = $(2)))
+endef
+
+# Allow setting CC and AR and LD, or setting CROSS_COMPILE as a prefix.
+$(call allow-override,CC,$(CROSS_COMPILE)gcc)
+$(call allow-override,AR,$(CROSS_COMPILE)ar)
+$(call allow-override,LD,$(CROSS_COMPILE)ld)
+
+LD += $(EXTRA_LDFLAGS)
+
+include $(srctree)/tools/scripts/Makefile.arch
+
+# Refer to README to learn how to support your architecture
+SUPPORTED_ARCHS = x86
+
+ifeq ($(filter $(ARCH),$(SUPPORTED_ARCHS)),)
+$(error Unsupported arch: $(ARCH))
+endif
+
+CFLAGS += -O2 -g
+CFLAGS += -std=gnu99 -Wall -Werror
+CFLAGS += -lpthread
+CFLAGS += -DCONFIG_KPROBES
+
+# We confine the includes used below to those we know are safe
+# for this type of hack.
+CFLAGS += -D__KERNEL__
+
+# CFLAGS += -DCONFIG_HAVE_ARCH_PS_CONST
+INCLUDES = \
+	   -I include/ \
+	   -I arch/$(ARCH)/include/ \
+	   -I ../include/ \
+	   -I ../arch/$(ARCH)/include/ \
+	   -I ../arch/$(ARCH)/include/generated/
+
+CFLAGS += $(INCLUDES)
+CFLAGS +=-Wl,-Tarch/$(ARCH)/kernel/vmlinux.lds
+
+HEADERS = \
+	  ../../include/asm-generic/section-core.h \
+	  ../../include/asm-generic/ranges.h \
+	  ../../include/asm-generic/tables.h \
+	  ../../include/linux/sections.h \
+	  ../../include/linux/ranges.h \
+	  ../../include/linux/tables.h
+
+__check_headers: $(HEADERS)
+	@$(foreach h, $(HEADERS), \
+		(test -f $(h) && ( \
+			(diff -B $(subst ../,../,$(h)) $(h) >/dev/null) \
+			|| echo "Warning: $(subst ../../,tools/,$(h)) differs from kernel" >&2 ) || true);)
+
+$(OUTPUT)arch/$(ARCH)/kernel/vmlinux.lds: arch/$(ARCH)/kernel/vmlinux.lds.S
+	$(NQ) '  LD  ' $@
+	$(Q)$(CC) $(CFLAGS) $(INCLUDES) -E -P \
+		-D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
+
+# Note, we use obj-y as a convenience factor, the cmd build
+# stuff doesn't allow this magic, it resolves our depds but
+# we still need to provide a series of targets for our objects.
+# We stick to the convenient shorthand we're used to in the
+# kernel. The final object resolution build stuff is handled
+# by tool_target_obj and its caller below. This also enables
+# OUTPUT=foo-path support so you can build externally.
+obj-y += \
+	arch/$(ARCH)/kernel/head64.o \
+	arch/$(ARCH)/mm/init.o \
+	kernel/locking/mutex.o \
+	kernel/locking/spinlock.o \
+	kernel/workqueue.o \
+	kernel/main.o \
+	pci.o \
+	lib/string.o \
+	pci-quirks.o \
+	drivers/acme.o \
+	drivers/synth/main.o \
+	drivers/synth/common.o \
+	drivers/synth/or.s \
+	main.o
+
+ifeq ($(ARCH),x86)
+obj-y += \
+	arch/$(ARCH)/kernel/alternative.o \
+	arch/$(ARCH)/kernel/init.o \
+	arch/$(ARCH)/kernel/kprobes.o \
+	arch/$(ARCH)/kernel/kasan.o \
+	arch/$(ARCH)/kernel/beta.o \
+	arch/$(ARCH)/kernel/alpha.o \
+	arch/$(ARCH)/xen/init.o	\
+	drivers/xen-driver.o
+endif
+
+obj-y-out = $(patsubst %,$(OUTPUT)%,$(obj-y))
+
+__build-dir = $(subst $(OUTPUT),,$(dir $1))
+build-dir   = $(if $(__build-dir),$(__build-dir),.)
+
+build := -f $(srctree)/tools/build/Makefile.build dir=$(build-dir)
+
+define tool_target_obj
+$(1): $(subst .s,.S,$(subst .o,.c,$(patsubst $(OUTPUT)%,%,$(1))))
+	$(Q)$(MAKE) $(build) obj=$(1)
+endef
+
+$(foreach tool_obj, $(obj-y-out), \
+	$(eval $(call tool_target_obj, $(tool_obj))))
+
+$(OUTPUT)demo: $(obj-y-out)
+	$(NQ) '  CC  ' $@
+	$(Q)$(CC) $(obj-y-out) -o $@ $(CPPFLAGS) $(CFLAGS)
+
+CHECK_HEADERS := __check_headers
+PHONY += $(CHECK_HEADERS)
+
+CMD_TARGETS = $(OUTPUT)arch/$(ARCH)/kernel/vmlinux.lds $(OUTPUT)demo
+TARGETS = $(CMD_TARGETS)
+
+all: $(CHECK_HEADERS) all_cmd
+
+all_cmd: $(CMD_TARGETS)
+
+ifeq ($(OUTPUT),)
+clean_dir = ./
+else
+clean_dir = $(OUTPUT)
+endif
+
+clean::
+	$(NQ)  '  CLEAN deps'
+	$(Q)find $(clean_dir) -name \*.o \
+		-o -name \*.s \
+		-o -name \*.o.d \
+		-o -name \*.o.cmd | xargs rm -f
+	$(NQ)  '  CLEAN targets'
+	$(Q)$(foreach f, $(CMD_TARGETS), rm -f $(f);)
diff --git a/tools/linker-tables/README b/tools/linker-tables/README
new file mode 100644
index 000000000000..729241f9e4c4
--- /dev/null
+++ b/tools/linker-tables/README
@@ -0,0 +1,114 @@
+Linux linker table userspace sandbox
+====================================
+
+This is a userspace sandbox to allow easy experimentation and
+test extensions with linker tables. It tries to mimic the Linux
+kernel development flow as much as possible, it however relies
+on and uses libc and is nothing but a simple stupid userspace
+application demo.
+
+You can use the sandbox to modify the kernel's linker table
+solution or add use it in creative ways without having to run
+qemu with a real kernel or user mode linux. You can simply try
+to extend this sandbox as you would for a regular userspace
+application.
+
+History
+=======
+
+This was hacked on first in an external repository, that tree has
+the full set of history of how this work came about. Refer to that
+tree for more details if you are interested in the logic used for
+a lot of decisions made for linker tables:
+
+https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linker-tables.git/
+
+This tree is discontinued now in favor of an upstream solution which
+is kept in sync with the kernel.
+
+Compile
+=======
+
+Run:
+	make
+
+Clean:
+	make clean
+
+If you need to get object files outside of the source tree:
+
+	make OUTPUT=/tmp/path/
+	make OUTPUT=/tmp/path/ clean
+
+Supported architectures
+=======================
+
+x86_64
+
+Currently only x86_64 is supported for the demo. It should be
+relatively easy to add more. To add a new architecture you need
+a toolchain available with libc. You then need to generate a
+respective base template custom linker script for userspace
+as is provided on x86 in arch/x86/kernel/vmlinux.lds.S.
+
+A respective architecture tools/arch/$(ARCH)/include/* file for
+each section-core.h, ranges.h, tables.h will need to be provided
+as well. If your architecture's file is generated copy the generated
+file over.
+
+x86 Simulated boots
+===================
+
+This programs simulates boot on both bare metal and with the
+Xen PV entry on x86.
+
+Emulate bare metal boot:
+
+./demo
+
+Emulate Xen boot (x86):
+
+./demo -x
+
+Testing new features
+====================
+
+A copy of each kernel header file is maintained in tools/include/,
+as well as a respective generated asm file for each sandbox supported
+architecture. This sandbox has a built in checker for when these files
+get out of sync.
+
+If testing new extensions on the files:
+
+  o section-core
+  o ranges.h
+  o tables.h
+
+You'll want to copy them into tools as well. If you are working on
+using these files you can work within the current directory's namespace,
+including its own set of header files, so tools/linker-tables/include/ and
+each respective tools/linker-tables/arch/$(ARCH)/include/asm/.
+
+Features evaluation
+===================
+
+This lists features currently being evaluated in the sandbox, not yet
+present upstream. These make use of the existing set of header files
+without modification.
+
+ o Demo use of initialization on for x86, refer to arch/x86/kernel/init.c
+
+ o Demo use of porting the kernel's init call levels to linker tables, refer
+   to the init_calls linker table use on kernel/main.c
+
+ o Demo use of an asm-generic architecture init family, which could potentially
+   be used to help share initialization sequences on simple architectures.
+   Refer to include/asm-generic/arch_init_fn.h
+
+ o Building synthetic routines with the option to provide enhancements
+   per architecture in asm, refer to drivers/synth/or.S and its use on
+   synth_init_or().
+
+ o User of linker tables for alternatives with consts - refer to
+   use of the ps_set_const_table linker table and its use in
+   arch/x86/kernel/alternative.c
diff --git a/tools/linker-tables/arch/x86/include/asm/asm.h b/tools/linker-tables/arch/x86/include/asm/asm.h
new file mode 100644
index 000000000000..155a52920dfb
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/asm.h
@@ -0,0 +1,17 @@
+#ifndef _ASM_X86_ASM_H
+
+#ifdef __ASSEMBLY__
+# define __ASM_FORM(x)	x
+# define __ASM_FORM_RAW(x)     x
+# define __ASM_FORM_COMMA(x) x,
+#else
+# define __ASM_FORM(x)	" " #x " "
+# define __ASM_FORM_RAW(x)     #x
+# define __ASM_FORM_COMMA(x) " " #x ","
+#endif
+
+# define __ASM_SEL(a,b) __ASM_FORM(b)
+# define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(b)
+#define _ASM_PTR	__ASM_SEL(.long, .quad)
+
+#endif /* _ASM_X86_ASM_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/boot.h b/tools/linker-tables/arch/x86/include/asm/boot.h
new file mode 100644
index 000000000000..af91b94ad5a6
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/boot.h
@@ -0,0 +1 @@
+extern struct boot_params boot_params;
diff --git a/tools/linker-tables/arch/x86/include/asm/bootparam.h b/tools/linker-tables/arch/x86/include/asm/bootparam.h
new file mode 100644
index 000000000000..a7ef34216f7f
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/bootparam.h
@@ -0,0 +1,32 @@
+#ifndef __BOOTPARAM_H
+#define __BOOTPARAM_H
+
+#include <linux/types.h>
+
+struct setup_header {
+	__u32 hardware_subarch;
+} __attribute__((packed));
+
+struct boot_params {
+	struct setup_header hdr;
+} __attribute__((packed));
+
+enum {
+	X86_SUBARCH_PC = 0,
+	X86_SUBARCH_LGUEST,
+	X86_SUBARCH_XEN,
+	X86_SUBARCH_INTEL_MID,
+	X86_SUBARCH_CE4100,
+	X86_NR_SUBARCHS,
+};
+
+#define X86_SUBARCH_ALL_SUBARCHS 	\
+	(				\
+	BIT(X86_SUBARCH_PC) |		\
+	BIT(X86_SUBARCH_LGUEST) |	\
+	BIT(X86_SUBARCH_XEN) |		\
+	BIT(X86_SUBARCH_INTEL_MID) |	\
+	BIT(X86_SUBARCH_CE4100)		\
+	)
+
+#endif /* __BOOTPARAM_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/kprobes.h b/tools/linker-tables/arch/x86/include/asm/kprobes.h
new file mode 100644
index 000000000000..f702fc359efe
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/kprobes.h
@@ -0,0 +1,7 @@
+#ifndef _SANDBOX_ASM_X86_KPROBES_H
+#define _SANDBOX_ASM_X86_KPROBES_H
+
+/* This is all we need for the demo */
+#include <asm-generic/kprobes.h>
+
+#endif /* _SANDBOX_ASM_X86_KPROBES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/ps_const.h b/tools/linker-tables/arch/x86/include/asm/ps_const.h
new file mode 100644
index 000000000000..3847f03fca92
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/ps_const.h
@@ -0,0 +1,23 @@
+#ifndef __X86_PS_CONST
+#define __X86_PS_CONST
+
+#include <linux/stringify.h>
+#include <linux/tables.h>
+#include <asm/asm.h>
+
+#define ps_shr(in, _func)						\
+({									\
+	 __typeof__(in) _count;						\
+									\
+	asm volatile(							\
+		"shr %P[_in],%[_count]\n"				\
+		"1:\n"							\
+		push_section_tbl(.init.data, ps_set_const_table, 01,)	\
+		_ASM_PTR "1b-1, %P2, %P3\n"				\
+		".popsection\n"						\
+		: [_count] "=g" (_count)				\
+		: [_in] "i" (in), "i" (SET_CONST_U8), "i" (_func));	\
+	(_count);							\
+})
+
+#endif /* __X86_PS_CONST */
diff --git a/tools/linker-tables/arch/x86/include/asm/ranges.h b/tools/linker-tables/arch/x86/include/asm/ranges.h
new file mode 100644
index 000000000000..823789d2b010
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/ranges.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_RANGES_H
+#define _ASM_X86_RANGES_H
+
+#include <asm-generic/ranges.h>
+
+#endif  /* _ASM_X86_RANGES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/section-core.h b/tools/linker-tables/arch/x86/include/asm/section-core.h
new file mode 100644
index 000000000000..06be2b1c424f
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/section-core.h
@@ -0,0 +1 @@
+#include <asm-generic/section-core.h>
diff --git a/tools/linker-tables/arch/x86/include/asm/setup.h b/tools/linker-tables/arch/x86/include/asm/setup.h
new file mode 100644
index 000000000000..366c36bd2910
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/setup.h
@@ -0,0 +1,6 @@
+#ifndef __LINUX_X86_USER_SETUP_H
+#define __LINUX_X86_USER_SETUP_H
+
+/* I'm lazy */
+
+#endif /* __LINUX_X86_USER_SETUP_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/tables.h b/tools/linker-tables/arch/x86/include/asm/tables.h
new file mode 100644
index 000000000000..797df3407ee1
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/tables.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_TABLES_H
+#define _ASM_X86_TABLES_H
+
+#include <asm-generic/tables.h>
+
+#endif  /* _ASM_X86_RANGES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/x86.h b/tools/linker-tables/arch/x86/include/asm/x86.h
new file mode 100644
index 000000000000..680c1141e0de
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/x86.h
@@ -0,0 +1,4 @@
+int startup_64(void);
+int x86_64_start_reservations(void);
+void setup_arch(void);
+void late_init(void);
diff --git a/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h b/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
new file mode 100644
index 000000000000..afece8ce6dd4
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
@@ -0,0 +1,169 @@
+#ifndef __X86_INIT_TABLES_H
+#define __X86_INIT_TABLES_H
+
+#include <linux/types.h>
+#include <linux/tables.h>
+
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <asm/bootparam.h>
+
+/**
+ * struct x86_init_fn - x86 generic kernel init call
+ *
+ * Linux x86 features vary in complexity, features may require work done at
+ * different levels of the full x86 init sequence. Today there are also two
+ * different possible entry points for Linux on x86, one for bare metal, KVM
+ * and Xen HVM, and another for Xen PV guests / dom0.  Assuming a bootloader
+ * has set up 64-bit mode, roughly the x86 init sequence follows this path:
+ *
+ * Bare metal, KVM, Xen HVM                      Xen PV / dom0
+ *       startup_64()                             startup_xen()
+ *              \                                     /
+ *      x86_64_start_kernel()                 xen_start_kernel()
+ *                           \               /
+ *                      x86_64_start_reservations()
+ *                                   |
+ *                              start_kernel()
+ *                              [   ...        ]
+ *                              [ setup_arch() ]
+ *                              [   ...        ]
+ *                                  init
+ *
+ * x86_64_start_kernel() and xen_start_kernel() are the respective first C code
+ * entry starting points. The different entry points exist to enable Xen to
+ * skip a lot of hardware setup already done and managed on behalf of the
+ * hypervisor, we refer to this as "paravirtualization yielding". The different
+ * levels of init calls on the x86 init sequence exist to account for these
+ * slight differences and requirements. These different entry points also share
+ * a common entry x86 specific path, x86_64_start_reservations().
+ *
+ * A generic x86 feature can have different initialization calls, one on each
+ * of the different main x86 init sequences, but must also address both entry
+ * points in order to work properly across the board on all supported x86
+ * subarchitectures. Since x86 features can also have dependencies on other
+ * setup code or features, x86 features can at times be subordinate to other
+ * x86 features, or conditions. struct x86_init_fn enables feature developers
+ * to annotate dependency relationships to ensure subsequent init calls only
+ * run once a subordinate's dependencies have run. When needed custom
+ * dependency requirements can also be spelled out through a custom dependency
+ * checker. In order to account for the dual entry point nature of x86-64 Linux
+ * for "paravirtualization yielding" and to make annotations for support for
+ * these explicit each struct x86_init_fn must specify supported
+ * subarchitectures. The earliest x86-64 code can read the subarchitecture
+ * though is after load_idt(), as such the earliest we can currently rely on
+ * subarchitecture for semantics and a common init sequences is on the shared
+ * common x86_64_start_reservations().  Each struct x86_init_fn is associated
+ * with a specific special link order number which has been careflly thought
+ * out by x86 maintainers. You should pick a link order level associated with
+ * the specific directory your code lies in, a respective macro is used to
+ * build association to a link oder with a routine, you should use one of the
+ * provided x86_init_*() macros. You should not use __x86_init() directly.
+ *
+ * x86_init_fn enables strong semantics and dependencies to be defined and
+ * implemented on the full x86 initialization sequence.
+ *
+ * @supp_hardware_subarch: must be set, it represents the bitmask of supported
+ *	subarchitectures.  We require each struct x86_init_fn to have this set
+ *	to require developer considerations for each supported x86
+ *	subarchitecture and to build strong annotations of different possible
+ *	run time states particularly in consideration for the two main
+ *	different entry points for x86 Linux, to account for paravirtualization
+ *	yielding.
+ *
+ *	The subarchitecture is read by the kernel at early boot from the
+ *	struct boot_params hardware_subarch. Support for the subarchitecture
+ *	exists as of x86 boot protocol 2.07. The bootloader would have set up
+ *	the respective hardware_subarch on the boot sector as per
+ *	Documentation/x86/boot.txt.
+ *
+ *	What x86 entry point is used is determined at run time by the
+ *	bootloader. Linux pv_ops was designed to help enable to build one Linux
+ *	binary to support bare metal and different hypervisors.  pv_ops setup
+ *	code however is limited in that all pv_ops setup code is run late in
+ *	the x86 init sequence, during setup_arch(). In fact cpu_has_hypervisor
+ *	only works after early_cpu_init() during setup_arch(). If an x86
+ *	feature requires an earlier determination of what hypervisor was used,
+ *	or if it needs to annotate only support for certain hypervisors, the
+ *	x86 hardware_subarch should be set by the bootloader and
+ *	@supp_hardware_subarch set by the x86 feature. Using hardware_subarch
+ *	enables x86 features to fill the semantic gap between the Linux x86
+ *	entry point used and what pv_ops has to offer through a hypervisor
+ *	agnostic mechanism.
+ *
+ *	Each supported subarchitecture is set using the respective
+ *	X86_SUBARCH_* as a bit in the bitmask. For instance if a feature
+ *	is supported on PC and Xen subarchitectures only you would set this
+ *	bitmask to:
+ *
+ *		BIT(X86_SUBARCH_PC) |
+ *		BIT(X86_SUBARCH_XEN);
+ *
+ * @early_init: required, routine which will run in x86_64_start_reservations()
+ *	after we ensure boot_params.hdr.hardware_subarch is accessible and
+ *	properly set. Memory is not yet available. This the earliest we can
+ *	currently define a common shared callback since all callbacks need to
+ *	check for boot_params.hdr.hardware_subarch and this becomes accessible
+ *	on x86-64 until after load_idt().
+ */
+struct x86_init_fn {
+	__u32 supp_hardware_subarch;
+	void (*early_init)(void);
+};
+
+DECLARE_LINKTABLE(struct x86_init_fn, x86_init_fns);
+
+/* Init order levels, we can start at 0000 but reserve 0000-0999 for now */
+
+/*
+ * X86_INIT_ORDER_EARLY - early kernel init code
+ *
+ * This consists of the first parts of the Linux kernel executed.
+ */
+#define X86_INIT_ORDER_EARLY	1000
+
+/* X86_INIT_ORDER_PLATFORM - platform kernel code
+ *
+ * Code the kernel needs to initialize under arch/x86/platform/
+ * early in boot.
+ */
+#define X86_INIT_ORDER_PLATFORM	3000
+
+#define __x86_init(__level,						\
+		   __supp_hardware_subarch,				\
+		   __early_init)					\
+	static LINKTABLE_INIT_DATA(x86_init_fns, __level)		\
+	__x86_init_fn_##__early_init = {				\
+		.supp_hardware_subarch = __supp_hardware_subarch,	\
+		.early_init = __early_init,				\
+	};
+
+#define x86_init_early(__supp_hardware_subarch,				\
+		       __early_init)					\
+	__x86_init(X86_INIT_ORDER_EARLY, __supp_hardware_subarch,	\
+		   __early_init);
+
+#define x86_init_platform(__supp_hardware_subarch,			\
+		       __early_init)					\
+	__x86_init(__name, X86_INIT_ORDER_PLATFORM, __supp_hardware_subarch,\
+		   __early_init);
+
+#define x86_init_early_all(__early_init)				\
+	x86_init_early(X86_SUBARCH_ALL_SUBARCHS,			\
+		       __early_init);
+
+#define x86_init_early_pc(__early_init)					\
+	x86_init_early(BIT(X86_SUBARCH_PC),				\
+		       __early_init);
+
+#define x86_init_early_xen(__early_init)				\
+	x86_init_early(BIT(X86_SUBARCH_XEN),				\
+		       __early_init);
+/**
+ * x86_init_fn_early_init: call all early_init() callbacks
+ *
+ * This calls all early_init() callbacks on the x86_init_fns linker table.
+ */
+void x86_init_fn_early_init(void);
+
+#endif /* __X86_INIT_TABLES_H */
diff --git a/tools/linker-tables/arch/x86/kernel/alpha.c b/tools/linker-tables/arch/x86/kernel/alpha.c
new file mode 100644
index 000000000000..477227d817a3
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/alpha.c
@@ -0,0 +1,10 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_alpha(void)
+{
+	pr_info("Initializing alpha ...\n");
+	pr_info("Completed initializing alpha !\n");
+}
+
+x86_init_early_pc(early_init_alpha);
diff --git a/tools/linker-tables/arch/x86/kernel/alternative.c b/tools/linker-tables/arch/x86/kernel/alternative.c
new file mode 100644
index 000000000000..380c184172b3
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/alternative.c
@@ -0,0 +1,31 @@
+#include <asm/x86_init_fn.h>
+
+#include <linux/kernel.h>
+#include <linux/ps_const.h>
+
+void apply_alternatives_linker_tables(void)
+{
+	unsigned int num_consts = LINKTABLE_SIZE(ps_set_const_table);
+	struct ps_set_const *ps_const;
+
+	if (!num_consts)
+		return;
+
+	pr_debug("Number of init entries: %d\n", num_consts);
+
+	linktable_for_each(ps_const, ps_set_const_table) {
+		switch (ps_const->type) {
+		case SET_CONST_U8:
+			*ps_const->count = (__u8) ps_const->func();
+			break;
+		case SET_CONST_U16:
+			*ps_const->count = (__u16) ps_const->func();
+			break;
+		case SET_CONST_U32:
+			*ps_const->count = (__u16) ps_const->func();
+			break;
+		}
+	}
+}
+
+x86_init_early_pc(apply_alternatives_linker_tables);
diff --git a/tools/linker-tables/arch/x86/kernel/beta.c b/tools/linker-tables/arch/x86/kernel/beta.c
new file mode 100644
index 000000000000..6cbbb3144928
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/beta.c
@@ -0,0 +1,10 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_beta(void)
+{
+	pr_info("Initializing beta ...\n");
+	pr_info("Completed initializing beta !\n");
+}
+
+x86_init_early_pc(early_init_beta);
diff --git a/tools/linker-tables/arch/x86/kernel/head64.c b/tools/linker-tables/arch/x86/kernel/head64.c
new file mode 100644
index 000000000000..d14dcdfd0ea9
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/head64.c
@@ -0,0 +1,58 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+
+#include <asm/x86_init_fn.h>
+#include <asm/boot.h>
+#include <asm/bootparam.h>
+
+#include <linux/start_kernel.h>
+#include <linux/kasan.h>
+
+void x86_64_start_reservations(void)
+{
+	switch (boot_params.hdr.hardware_subarch) {
+	case X86_SUBARCH_PC:
+		pr_info("Booting bare metal\n");
+		break;
+	case X86_SUBARCH_LGUEST:
+		pr_info("Booting lguest not supported\n");
+		BUG();
+	case X86_SUBARCH_XEN:
+		pr_info("Booting a Xen guest\n");
+		break;
+	case X86_SUBARCH_INTEL_MID:
+		pr_info("Booting Intel MID not supported\n");
+		BUG();
+	case X86_SUBARCH_CE4100:
+		pr_info("Booting Intel CE4100 not supported\n");
+		BUG();
+	default:
+		pr_info("Booting sunsupported x86 hardware subarch\n");
+		BUG();
+	}
+
+	start_kernel();
+}
+
+static void x86_64_start_kernel(void)
+{
+	x86_init_fn_early_init();
+
+	x86_64_start_reservations();
+}
+
+void startup_64(void)
+{
+	pr_info("Initializing x86 bare metal world\n");
+	x86_64_start_kernel();
+}
+
+void setup_arch(void)
+{
+	/* TODO: x86_init_fn_setup_arch(); */
+}
+
+void late_init(void)
+{
+	/* TODO: x86_init_fn_late_init(); */
+}
diff --git a/tools/linker-tables/arch/x86/kernel/init.c b/tools/linker-tables/arch/x86/kernel/init.c
new file mode 100644
index 000000000000..1eed92d1acb2
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/init.c
@@ -0,0 +1,42 @@
+#define pr_fmt(fmt) "x86-init: " fmt
+
+#include <linux/bug.h>
+#include <linux/kernel.h>
+
+#include <asm/x86_init_fn.h>
+#include <asm/bootparam.h>
+#include <asm/boot.h>
+#include <asm/setup.h>
+
+DEFINE_LINKTABLE_INIT_DATA(struct x86_init_fn, x86_init_fns);
+
+static bool x86_init_fn_supports_subarch(struct x86_init_fn *fn)
+{
+	if (!fn->supp_hardware_subarch) {
+		//pr_err("Init sequence fails to declares any supported subarchs: %pF\n", fn->early_init);
+		WARN_ON(1);
+	}
+	if (BIT(boot_params.hdr.hardware_subarch) & fn->supp_hardware_subarch)
+		return true;
+	return false;
+}
+
+void __ref x86_init_fn_early_init(void)
+{
+	struct x86_init_fn *init_fn;
+	unsigned int num_inits = LINKTABLE_SIZE(x86_init_fns);
+
+	if (!num_inits)
+		return;
+
+	pr_debug("Number of init entries: %d\n", num_inits);
+
+	linktable_for_each(init_fn, x86_init_fns) {
+		if (!x86_init_fn_supports_subarch(init_fn))
+			continue;
+
+		//pr_debug("Running early init %pF ...\n", init_fn->early_init);
+		init_fn->early_init();
+		//pr_debug("Completed early init %pF\n", init_fn->early_init);
+	}
+}
diff --git a/tools/linker-tables/arch/x86/kernel/kasan.c b/tools/linker-tables/arch/x86/kernel/kasan.c
new file mode 100644
index 000000000000..a1e6a5b72c23
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/kasan.c
@@ -0,0 +1,11 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+void kasan_early_init(void)
+{
+	pr_info("Initializing kasan ...\n");
+	pr_info("Early init for Kasan...\n");
+	pr_info("Completed initializing kasan !\n");
+}
+
+x86_init_early_pc(kasan_early_init);
diff --git a/tools/linker-tables/arch/x86/kernel/kprobes.c b/tools/linker-tables/arch/x86/kernel/kprobes.c
new file mode 100644
index 000000000000..c4e42beae55b
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/kprobes.c
@@ -0,0 +1,51 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <linux/ranges.h>
+#include <linux/kprobes.h>
+
+DEFINE_SECTION_RANGE(kprobes, .text);
+
+void __kprobes test_kprobe_0001(void)
+{
+	pr_info("test_kprobe\n");
+}
+
+void test_kprobe_0002(void)
+{
+	pr_info("test_kprobe\n");
+}
+
+void test_kprobe_addr(const char *test, unsigned long addr, bool should_match)
+{
+	if (SECTION_RANGE_ADDR_WITHIN(kprobes, addr))
+		if (should_match)
+			pr_info("== OK: %s within range!\n", test);
+		else
+			pr_info("== FAIL: %s should not be in range...\n",
+				test);
+	else
+		if (should_match)
+			pr_info("== FAIL: %s should be in range...\n", test);
+		else
+			pr_info("== OK: %s not in range as expected!\n", test);
+}
+
+void early_init_kprobes(void)
+{
+	unsigned long addr;
+
+	pr_info("Initializing kprobes ...\n");
+
+	addr = (unsigned long) &test_kprobe_0001;
+
+	test_kprobe_addr("test_kprobe_0001", addr, true);
+
+	addr = (unsigned long) &test_kprobe_0002;
+
+	test_kprobe_addr("test_kprobe_0002", addr, false);
+
+	pr_info("Completed initializing kprobes !\n");
+}
+
+x86_init_early_all(early_init_kprobes);
diff --git a/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S b/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
new file mode 100644
index 000000000000..783735fb897a
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
@@ -0,0 +1,277 @@
+/* Script for -z combreloc: combine and sort reloc sections */
+/* Copyright (C) 2014 Free Software Foundation, Inc.
+   Copying and distribution of this script, with or without modification,
+   are permitted in any medium without royalty provided the copyright
+   notice and this notice are preserved.  */
+
+#include <asm/section-core.h>
+#include <asm/ranges.h>
+#include <asm/tables.h>
+
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
+	      "elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(_start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
+  .interp         : { *(.interp) }
+  .note.gnu.build-id : { *(.note.gnu.build-id) }
+  .hash           : { *(.hash) }
+  .gnu.hash       : { *(.gnu.hash) }
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+  .rela.dyn       :
+    {
+      *(.rela.init)
+      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+      *(.rela.fini)
+      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+      *(.rela.ctors)
+      *(.rela.dtors)
+      *(.rela.got)
+      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+      *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
+      *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
+      *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
+      *(.rela.ifunc)
+    }
+  .rela.plt       :
+    {
+      *(.rela.plt)
+      PROVIDE_HIDDEN (__rela_iplt_start = .);
+      *(.rela.iplt)
+      PROVIDE_HIDDEN (__rela_iplt_end = .);
+    }
+  .init           :
+  {
+    KEEP (*(SORT_NONE(.init)))
+  }
+  .plt            : { *(.plt) *(.iplt) }
+  .plt.bnd        : { *(.plt.bnd) }
+  .text           :
+  {
+    *(.text.unlikely .text.*_unlikely .text.unlikely.*)
+    *(.text.exit .text.exit.*)
+    *(.text.startup .text.startup.*)
+    *(.text.hot .text.hot.*)
+
+    *(SORT(.text..rng.*))
+    *(SORT(.text..tbl.*))
+
+    *(SORT(.init.text..rng.*))
+    *(SORT(.init.text..tbl.*))
+
+    *(SORT(.initcall..rng.*))
+    *(SORT(.initcall..tbl.*))
+
+    *(SORT(.exit.text..rng.*))
+    *(SORT(.exit.text..tbl.*))
+
+    *(SORT(.exitcall.exit..rng.*))
+    *(SORT(.exitcall.exit..tbl.*))
+
+    *(.text .stub .text.* .gnu.linkonce.t.*)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  }
+  .fini           :
+  {
+    KEEP (*(SORT_NONE(.fini)))
+  }
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+  .rodata         :
+  {
+	*(.rodata)
+
+	*(SORT(.rodata.*))
+
+	*(SORT(.rodata..rng.*))
+	*(SORT(.rodata..tbl.*))
+
+	*(SORT(.init.rodata..rng.*))
+	*(SORT(.init.rodata..tbl.*))
+
+	*(SORT(.ref.rodata..rng.*))
+	*(SORT(.ref.rodata..tbl.*))
+
+	*(.gnu.linkonce.r.*)
+  }
+  .rodata1        : { *(.rodata1) }
+  .eh_frame_hdr : { *(.eh_frame_hdr) }
+  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table
+  .gcc_except_table.*) }
+  /* These sections are generated by the Sun/Oracle C++ compiler.  */
+  .exception_ranges   : ONLY_IF_RO { *(.exception_ranges
+  .exception_ranges*) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  */
+  . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+  /* Exception handling  */
+  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
+  .exception_ranges   : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
+  /* Thread Local Storage sections  */
+  .tdata	  : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+  .preinit_array     :
+  {
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP (*(.preinit_array))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+  }
+  .init_array     :
+  {
+    PROVIDE_HIDDEN (__init_array_start = .);
+    KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
+    KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
+    PROVIDE_HIDDEN (__init_array_end = .);
+  }
+  .fini_array     :
+  {
+    PROVIDE_HIDDEN (__fini_array_start = .);
+    KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
+    KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
+    PROVIDE_HIDDEN (__fini_array_end = .);
+  }
+  .ctors          :
+  {
+    /* gcc uses crtbegin.o to find the start of
+       the constructors, so we make sure it is
+       first.  Because this is a wildcard, it
+       doesn't matter if the user does not
+       actually link against crtbegin.o; the
+       linker won't look for a file to match a
+       wildcard.  The wildcard also means that it
+       doesn't matter which directory crtbegin.o
+       is in.  */
+    KEEP (*crtbegin.o(.ctors))
+    KEEP (*crtbegin?.o(.ctors))
+    /* We don't want to include the .ctor section from
+       the crtend.o file until after the sorted ctors.
+       The .ctor section from the crtend file contains the
+       end of ctors marker and it must be last */
+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+  .dtors          :
+  {
+    KEEP (*crtbegin.o(.dtors))
+    KEEP (*crtbegin?.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  .jcr            : { KEEP (*(.jcr)) }
+  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
+  .dynamic        : { *(.dynamic) }
+  .got            : { *(.got) *(.igot) }
+  . = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
+  .got.plt        : { *(.got.plt)  *(.igot.plt) }
+  .data           :
+  {
+    *(.data .data.* .gnu.linkonce.d.*)
+
+    *(SORT(.data..rng.*))
+    *(SORT(.data..tbl.*))
+
+    *(SORT(.init.data..rng.*))
+    *(SORT(.init.data..tbl.*))
+
+    *(SORT(.ref.rodata..rng.*))
+    *(SORT(.ref.rodata..tbl.*))
+
+    *(SORT(.exit.data..rng.*))
+    *(SORT(.exit.data..tbl.*))
+
+    SORT(CONSTRUCTORS)
+  }
+  .data1          : { *(.data1) }
+  _edata = .; PROVIDE (edata = .);
+  . = .;
+
+  __bss_start = .;
+  .bss            :
+  {
+   *(.dynbss)
+   *(.bss .bss.* .gnu.linkonce.b.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.
+      FIXME: Why do we need it? When there is no .bss section, we don't
+      pad the .data section.  */
+   . = ALIGN(. != 0 ? 64 / 8 : 1);
+  }
+  .lbss   :
+  {
+    *(.dynlbss)
+    *(.lbss .lbss.* .gnu.linkonce.lb.*)
+    *(LARGE_COMMON)
+  }
+  . = ALIGN(64 / 8);
+  . = SEGMENT_START("ldata-segment", .);
+  .lrodata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+  {
+    *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
+  }
+  .ldata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+  {
+    *(.ldata .ldata.* .gnu.linkonce.l.*)
+    . = ALIGN(. != 0 ? 64 / 8 : 1);
+  }
+  . = ALIGN(64 / 8);
+  _end = .; PROVIDE (end = .);
+  . = DATA_SEGMENT_END (.);
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line .debug_line.* .debug_line_end ) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  /* DWARF 3 */
+  .debug_pubtypes 0 : { *(.debug_pubtypes) }
+  .debug_ranges   0 : { *(.debug_ranges) }
+  /* DWARF Extension.  */
+  .debug_macro    0 : { *(.debug_macro) }
+  .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
+}
diff --git a/tools/linker-tables/arch/x86/mm/init.c b/tools/linker-tables/arch/x86/mm/init.c
new file mode 100644
index 000000000000..33e5700e2864
--- /dev/null
+++ b/tools/linker-tables/arch/x86/mm/init.c
@@ -0,0 +1,11 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_memory(void)
+{
+	pr_info("Initializing memory ...\n");
+	sleep(1);
+	pr_info("Completed initializing memory !\n");
+}
+
+x86_init_early_all(early_init_memory);
diff --git a/tools/linker-tables/arch/x86/xen/init.c b/tools/linker-tables/arch/x86/xen/init.c
new file mode 100644
index 000000000000..40ad493daee8
--- /dev/null
+++ b/tools/linker-tables/arch/x86/xen/init.c
@@ -0,0 +1,13 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <asm/x86.h>
+
+void startup_xen(void)
+{
+	pr_info("Initializing Xen guest\n");
+
+	x86_init_fn_early_init();
+
+	x86_64_start_reservations();
+}
diff --git a/tools/linker-tables/drivers/acme.c b/tools/linker-tables/drivers/acme.c
new file mode 100644
index 000000000000..975e4b8bf48d
--- /dev/null
+++ b/tools/linker-tables/drivers/acme.c
@@ -0,0 +1,33 @@
+#define pr_fmt(fmt) "ACME: " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/workqueue.h>
+
+void *acme_todo(void *arg);
+static DECLARE_WORK(acme_work, acme_todo);
+
+void *acme_todo(void *arg)
+{
+	pr_info("Running scheduled work\n");
+	pthread_exit(NULL);
+}
+
+static int acme_init_driver(void)
+{
+	pr_info("Initializing ...\n");
+	sleep(2);
+	pr_info("Finished init ... !\n");
+
+	init_work(&acme_work);
+	schedule_work(&acme_work);
+
+	return 0;
+}
+module_init(acme_init_driver);
+
+static void acme_exit(void)
+{
+	cancel_work_sync(&acme_work);
+};
+module_exit(acme_exit);
diff --git a/tools/linker-tables/drivers/synth/common.c b/tools/linker-tables/drivers/synth/common.c
new file mode 100644
index 000000000000..b44d9fcc7a9b
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/common.c
@@ -0,0 +1,16 @@
+int demo_or_1(int arg)
+{
+	switch (arg) {
+	case 1:
+		return 0xDEA00000;
+	case 2:
+		return 0X000D0000;
+	default:
+		return arg * 2;
+	}
+}
+
+int demo_or_2(void)
+{
+	return 0x0000BEEF;
+}
diff --git a/tools/linker-tables/drivers/synth/common.h b/tools/linker-tables/drivers/synth/common.h
new file mode 100644
index 000000000000..92827004f532
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/common.h
@@ -0,0 +1,2 @@
+int demo_or_1(int arg);
+int demo_or_2(void);
diff --git a/tools/linker-tables/drivers/synth/main.c b/tools/linker-tables/drivers/synth/main.c
new file mode 100644
index 000000000000..b9c2f876afa0
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/main.c
@@ -0,0 +1,36 @@
+#define pr_fmt(fmt) "Synthetics: " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ps_const.h>
+
+#include "common.h"
+#include "synth.h"
+
+DEFINE_LINKTABLE_INIT_DATA(struct ps_set_const, ps_set_const_table);
+
+unsigned int get_demo_shr(void)
+{
+	return 16;
+}
+
+static int synth_init(void)
+{
+	int synth_or;
+	int val = 2;
+	const unsigned int reg =  ps_shr(0xDEADBEEF, get_demo_shr);
+
+	synth_or = synth_init_or(val);
+	pr_info("synth_init_or(%d) returns: 0x%08X\n", val, synth_or);
+
+	pr_info("ps_shr(0x%08X, get_demo_shr) returns: 0x%08X\n",
+		0xDEADBEEF, reg);
+
+	return 0;
+}
+module_init(synth_init);
+
+static void synth_exit(void)
+{
+}
+module_exit(synth_exit);
diff --git a/tools/linker-tables/drivers/synth/or.S b/tools/linker-tables/drivers/synth/or.S
new file mode 100644
index 000000000000..deb963fdae33
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/or.S
@@ -0,0 +1,39 @@
+#include <asm/ranges.h>
+
+	DEFINE_SECTION_RANGE(.text, synth_init_or)
+
+	push_section_rng_level(.text, synth_init_or, "01", )
+	/* err = 0; */
+	pushq %rbp
+	movq %rsp,%rbp
+	pushq %rbx
+	xorq %rbx,%rbx
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "99", )
+	/* return err; */
+	movq %rbx,%rax
+	popq %rbx
+	popq %rbp
+	retq
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "50", )
+	/* err |= demo_or_1(1); */
+	movl $1,%edi
+	call demo_or_1
+	orq %rax,%rbx
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "50", )
+	/* err |= demo_or_1(2); */
+	movl $2,%edi
+	call demo_or_1
+	orq %rax,%rbx
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "50", )
+	/* err |= demo_or_2(); */
+	call demo_or_2
+	orq %rax,%rbx
+	.popsection
diff --git a/tools/linker-tables/drivers/synth/synth.h b/tools/linker-tables/drivers/synth/synth.h
new file mode 100644
index 000000000000..abbb9afac374
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/synth.h
@@ -0,0 +1,2 @@
+/* Synthetic demos go here */
+int synth_init_or(int arg);
diff --git a/tools/linker-tables/drivers/xen-driver.c b/tools/linker-tables/drivers/xen-driver.c
new file mode 100644
index 000000000000..268166efd06c
--- /dev/null
+++ b/tools/linker-tables/drivers/xen-driver.c
@@ -0,0 +1,12 @@
+#include <asm/x86_init_fn.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <xen/xen.h>
+
+static void early_xen_init_driver(void)
+{
+	pr_info("Initializing xen driver\n");
+	sleep(2);
+}
+
+x86_init_early_xen(early_xen_init_driver);
diff --git a/tools/linker-tables/include/asm-generic/arch_init_fn.h b/tools/linker-tables/include/asm-generic/arch_init_fn.h
new file mode 100644
index 000000000000..2318cc22cbe8
--- /dev/null
+++ b/tools/linker-tables/include/asm-generic/arch_init_fn.h
@@ -0,0 +1,50 @@
+#ifndef __ARCH_INIT_TABLES_H
+#define __ARCH_INIT_TABLES_H
+
+#include <linux/types.h>
+#include <linux/tables.h>
+#include <linux/init.h>
+
+/**
+ * struct arch_init_fn - architecture-generic kernel init call
+ *
+ * Architectures must initialize a series of things prior to handing off
+ * control to the kernel. This structure can be used if the architecture is
+ * simple and it just needs a basic set of calls on its way up.
+ *
+ * @early_init: required, routine which will run in startup_64(). Memory is
+ *	not yet available.
+ */
+struct arch_init_fn {
+	void (*early_init)(void);
+};
+
+DECLARE_LINKTABLE(struct arch_init_fn, arch_init_fns);
+
+/* Init order levels, we can start at 0000 but reserve 0000-0999 for now */
+
+/*
+ * ARCH_INIT_ORDER_EARLY - early kernel init code
+ *
+ * This consists of the first parts of the Linux kernel executed.
+ */
+#define ARCH_INIT_ORDER_EARLY	1000
+
+#define __arch_init(__level,						\
+		    __early_init)					\
+	static LINKTABLE_INIT_DATA(arch_init_fns, __level)		\
+	__arch_init_fn_##__early_init = {				\
+		.early_init = __early_init,				\
+	}
+
+#define arch_init_early(__early_init)					\
+	__arch_init(ARCH_INIT_ORDER_EARLY, __early_init)
+
+/**
+ * arch_init_fn_early_init: call all early_init() callbacks
+ *
+ * This calls all early_init() callbacks on the arch_init_fns linker table.
+ */
+void arch_init_fn_early_init(void);
+
+#endif /* __ARCH_INIT_TABLES_H */
diff --git a/tools/linker-tables/include/asm-generic/kprobes.h b/tools/linker-tables/include/asm-generic/kprobes.h
new file mode 100644
index 000000000000..839d2eb464d3
--- /dev/null
+++ b/tools/linker-tables/include/asm-generic/kprobes.h
@@ -0,0 +1,26 @@
+#ifndef _SANDBOX_ASM_GENERIC_KPROBES_H
+#define _SANDBOX_ASM_GENERIC_KPROBES_H
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#ifdef CONFIG_KPROBES
+#include <linux/tables.h>
+#include <asm/ranges.h>
+/*
+ * Blacklist ganerating macro. Specify functions which is not probed
+ * by using this macro.
+ */
+# define __NOKPROBE_SYMBOL(fname)				\
+static LINKTABLE_INIT_DATA(_kprobe_blacklist, all)		\
+	_kbl_addr_##fname = (unsigned long)fname;
+# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
+/* Use this to forbid a kprobes attach on very low level functions */
+# define __kprobes	__LINUX_RANGE(.text, kprobes)
+# define nokprobe_inline	__always_inline
+#else
+# define NOKPROBE_SYMBOL(fname)
+# define __kprobes
+# define nokprobe_inline	inline
+#endif
+#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
+
+#endif /* _SANDBOX_ASM_GENERIC_KPROBES_H */
diff --git a/tools/linker-tables/include/linux/bitops.h b/tools/linker-tables/include/linux/bitops.h
new file mode 100644
index 000000000000..2960e8089ebc
--- /dev/null
+++ b/tools/linker-tables/include/linux/bitops.h
@@ -0,0 +1,6 @@
+#ifndef _LINUX_BITOPS_H
+#define _LINUX_BITOPS_H
+
+#define BIT(nr)		(1UL << (nr))
+
+#endif /* _LINUX_BITOPS_H */
diff --git a/tools/linker-tables/include/linux/init.h b/tools/linker-tables/include/linux/init.h
new file mode 100644
index 000000000000..2691c3697f48
--- /dev/null
+++ b/tools/linker-tables/include/linux/init.h
@@ -0,0 +1,40 @@
+#ifndef _SANDBOX_LINUX_INIT_H
+#define _SANDBOX_LINUX_INIT_H
+
+#include_next <linux/init.h>
+#include <linux/types.h>
+#include <linux/sections.h>
+
+#define __init	__section(.init.text)
+#define __exit	__section(.exit.text)
+
+#ifndef __ASSEMBLY__
+#include <linux/tables.h>
+typedef int (*initcall_t)(void);
+typedef void (*exitcall_t)(void);
+
+DECLARE_LINKTABLE(initcall_t, init_calls);
+DECLARE_LINKTABLE(exitcall_t, exit_calls);
+
+#define __define_initcall(fn, id)					\
+	static LINKTABLE_INIT_DATA(init_calls, id)			\
+	__initcall_##fn##id = fn
+
+#define pure_initcall(fn)			__define_initcall(fn, 0)
+#define core_initcall(fn)			__define_initcall(fn, 1)
+#define postcore_initcall(fn)			__define_initcall(fn, 2)
+#define arch_initcall(fn)			__define_initcall(fn, 3)
+#define subsys_initcall(fn)			__define_initcall(fn, 4)
+#define fs_initcall(fn)				__define_initcall(fn, 5)
+#define device_initcall(fn)			__define_initcall(fn, 6)
+#define late_initcall(fn)			__define_initcall(fn, 7)
+
+#define __initcall(fn)				device_initcall(fn)
+
+#define __exitcall(fn)							\
+	static LINKTABLE_INIT_DATA(exit_calls, any)			\
+	__exitcall_##fn = fn;
+
+#endif
+
+#endif /* _SANDBOX_LINUX_INIT_H */
diff --git a/tools/linker-tables/include/linux/kasan.h b/tools/linker-tables/include/linux/kasan.h
new file mode 100644
index 000000000000..41791187854e
--- /dev/null
+++ b/tools/linker-tables/include/linux/kasan.h
@@ -0,0 +1,5 @@
+#include <linux/types.h>
+
+void kasan_early_init(void);
+int kasan_init(void);
+bool is_kasan_setup(void);
diff --git a/tools/linker-tables/include/linux/kernel.h b/tools/linker-tables/include/linux/kernel.h
new file mode 100644
index 000000000000..e2857c0b5b11
--- /dev/null
+++ b/tools/linker-tables/include/linux/kernel.h
@@ -0,0 +1,2 @@
+#include_next <linux/kernel.h>
+#include <linux/printk.h>
diff --git a/tools/linker-tables/include/linux/kprobes.h b/tools/linker-tables/include/linux/kprobes.h
new file mode 100644
index 000000000000..ecd5a0a69ae6
--- /dev/null
+++ b/tools/linker-tables/include/linux/kprobes.h
@@ -0,0 +1,11 @@
+#ifndef _SANDBOX_LINUX_KPROBES_H
+#define _SANDBOX_LINUX_KPROBES_H
+
+#include <asm/kprobes.h>
+#include <linux/ranges.h>
+
+#ifdef CONFIG_KPROBES
+DECLARE_SECTION_RANGE(kprobes);
+#endif
+
+#endif /* _SANDBOX_LINUX_KPROBES_H */
diff --git a/tools/linker-tables/include/linux/module.h b/tools/linker-tables/include/linux/module.h
new file mode 100644
index 000000000000..b59e55f3f04e
--- /dev/null
+++ b/tools/linker-tables/include/linux/module.h
@@ -0,0 +1,14 @@
+#ifndef _LINUX_MODULE_H
+#define _LINUX_MODULE_H
+
+#include <linux/init.h>
+
+#define module_init(x)  __initcall(x);
+#define module_exit(x)  __exitcall(x);
+
+struct module {
+	int (*init)(void);
+	void (*exit)(void);
+};
+
+#endif /* _LINUX_MODULE_H */
diff --git a/tools/linker-tables/include/linux/mutex.h b/tools/linker-tables/include/linux/mutex.h
new file mode 100644
index 000000000000..a74f951ceb42
--- /dev/null
+++ b/tools/linker-tables/include/linux/mutex.h
@@ -0,0 +1,17 @@
+#ifndef __LINUX_MUTEX_H
+#define __LINUX_MUTEX_H
+
+#include <sys/types.h>
+#include <linux/sched.h>
+#include <pthread.h>
+
+struct mutex {
+	pthread_mutex_t lock;
+};
+
+void mutex_init(struct mutex *lock);
+void mutex_destroy(struct mutex *lock);
+void mutex_lock(struct mutex *lock);
+void mutex_unlock(struct mutex *lock);
+
+#endif /* __LINUX_MUTEX_H */
diff --git a/tools/linker-tables/include/linux/pci.h b/tools/linker-tables/include/linux/pci.h
new file mode 100644
index 000000000000..8518c46631f7
--- /dev/null
+++ b/tools/linker-tables/include/linux/pci.h
@@ -0,0 +1,7 @@
+#include <linux/types.h>
+
+struct pci_fixup {
+	void (*hook)(void);
+};
+
+bool detect_pci(void);
diff --git a/tools/linker-tables/include/linux/printk.h b/tools/linker-tables/include/linux/printk.h
new file mode 100644
index 000000000000..dc137d3421e8
--- /dev/null
+++ b/tools/linker-tables/include/linux/printk.h
@@ -0,0 +1,26 @@
+#ifndef _SANDBOX_KERNEL_PRINTK
+#define _SANDBOX_KERNEL_PRINTK
+
+#ifdef __KERNEL__
+
+#include <stdio.h>
+
+#ifndef pr_fmt
+#define pr_fmt(fmt)	fmt
+#endif
+
+#ifndef pr_info
+#define pr_info(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
+#ifndef pr_err
+#define pr_err(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
+#ifndef pr_debug
+#define pr_debug(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* _SANDBOX_KERNEL_PRINTK */
diff --git a/tools/linker-tables/include/linux/ps_const.h b/tools/linker-tables/include/linux/ps_const.h
new file mode 100644
index 000000000000..5eab3a124e00
--- /dev/null
+++ b/tools/linker-tables/include/linux/ps_const.h
@@ -0,0 +1,46 @@
+#ifndef __PS_CONST
+#define __PS_CONST
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/tables.h>
+
+/* Helpers for partially static settings */
+
+enum ps_static_type {
+	SET_CONST_U8 = 0,
+	SET_CONST_U16,
+	SET_CONST_U32,
+};
+
+struct ps_set_const {
+	unsigned int *count;
+	enum ps_static_type type;
+	unsigned int (*func)(void);
+};
+
+DECLARE_LINKTABLE(struct ps_set_const, ps_set_const_table);
+
+#ifdef CONFIG_HAVE_ARCH_PS_CONST
+#include <asm/ps_const.h>
+#endif
+
+/*
+ * ps_ stands for "partially static", so we "partialloy static shift right"
+ * You can optimize this for your architecture.
+ *
+ * ps_shr(unsigned int in, unsigned char (*func)(void))
+ */
+#ifndef ps_shr
+#define ps_shr(_in, _func)						\
+({									\
+	static unsigned int _count;					\
+	static LINKTABLE_INIT_DATA(ps_set_const_table, 01)		\
+		__ps_shr##__func =					\
+		{ &_count, SET_CONST_U8, (_func) };			\
+									\
+	(_in) >> _count;						\
+})
+#endif /* ps_shr */
+
+#endif /* __PS_CONST */
diff --git a/tools/linker-tables/include/linux/sched.h b/tools/linker-tables/include/linux/sched.h
new file mode 100644
index 000000000000..0fe3526e88bf
--- /dev/null
+++ b/tools/linker-tables/include/linux/sched.h
@@ -0,0 +1,9 @@
+#ifndef _LINUX_SCHED_H
+#define _LINUX_SCHED_H
+
+#include <linux/ranges.h>
+
+DECLARE_SECTION_RANGE(sched_text);
+#define __sched		__LINUX_RANGE(.text, sched_text)
+
+#endif /* _LINUX_SCHED_H */
diff --git a/tools/linker-tables/include/linux/spinlock.h b/tools/linker-tables/include/linux/spinlock.h
new file mode 100644
index 000000000000..e62bc3bc5e6a
--- /dev/null
+++ b/tools/linker-tables/include/linux/spinlock.h
@@ -0,0 +1,13 @@
+#ifndef __LINUX_SPINLOCK_H
+#define __LINUX_SPINLOCK_H
+
+#include <pthread.h>
+
+#define spinlock_t pthread_spinlock_t
+
+void spin_lock_init(spinlock_t *lock);
+void spin_lock_destroy(spinlock_t *lock);
+void spin_lock(spinlock_t *lock);
+void spin_unlock(spinlock_t *lock);
+
+#endif /* __LINUX_SPINLOCK_H */
diff --git a/tools/linker-tables/include/linux/start_kernel.h b/tools/linker-tables/include/linux/start_kernel.h
new file mode 100644
index 000000000000..5c2cb9a5cb0c
--- /dev/null
+++ b/tools/linker-tables/include/linux/start_kernel.h
@@ -0,0 +1 @@
+int start_kernel(void);
diff --git a/tools/linker-tables/include/linux/types.h b/tools/linker-tables/include/linux/types.h
new file mode 100644
index 000000000000..3fc87b2c84e2
--- /dev/null
+++ b/tools/linker-tables/include/linux/types.h
@@ -0,0 +1,13 @@
+#ifndef __LINUX_USER_TYPES_H
+#define __LINUX_USER_TYPES_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+typedef unsigned char __u8;
+typedef unsigned short __u16;
+typedef unsigned int __u32;
+
+#endif /* __LINUX_USER_TYPES_H */
diff --git a/tools/linker-tables/include/linux/workqueue.h b/tools/linker-tables/include/linux/workqueue.h
new file mode 100644
index 000000000000..69e1c6de5051
--- /dev/null
+++ b/tools/linker-tables/include/linux/workqueue.h
@@ -0,0 +1,51 @@
+#ifndef _LINUX_WORKQUEUE_H
+#define _LINUX_WORKQUEUE_H
+
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <pthread.h>
+
+struct work {
+	bool ready;
+
+	pthread_t thread;
+	struct mutex mutex;
+	pthread_cond_t cond;
+
+	void *arg;
+	void *(*work_cb)(void *arg);
+};
+
+#define DECLARE_WORK(_w, _w_cb) \
+struct work _w = { \
+	.work_cb = _w_cb, \
+	.arg = NULL, \
+};
+
+extern void *run_work(void *arg);
+
+static inline void init_work(struct work *w)
+{
+	w->ready = false;
+
+	mutex_init(&w->mutex);
+	pthread_cond_init(&w->cond, NULL);
+
+	pthread_create(&w->thread, NULL, run_work, (void *) w);
+
+	while (1) {
+		mutex_lock(&w->mutex);
+		if (w->ready) {
+			pthread_mutex_unlock(&w->mutex.lock);
+			break;
+		}
+		mutex_unlock(&w->mutex);
+	}
+}
+
+void schedule_work(struct work *w);
+void cancel_work_sync(struct work *w);
+void init_work(struct work *w);
+
+#endif /* _LINUX_WORKQUEUE_H */
diff --git a/tools/linker-tables/include/xen/xen.h b/tools/linker-tables/include/xen/xen.h
new file mode 100644
index 000000000000..782c799a0064
--- /dev/null
+++ b/tools/linker-tables/include/xen/xen.h
@@ -0,0 +1,4 @@
+#include <linux/types.h>
+
+bool booting_xen(void);
+int startup_xen(void);
diff --git a/tools/linker-tables/kernel/locking/mutex.c b/tools/linker-tables/kernel/locking/mutex.c
new file mode 100644
index 000000000000..950e4a18461e
--- /dev/null
+++ b/tools/linker-tables/kernel/locking/mutex.c
@@ -0,0 +1,28 @@
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+
+DEFINE_SECTION_RANGE(sched_text, .text);
+
+void __sched mutex_init(struct mutex *lock)
+{
+	int r;
+
+	r = pthread_mutex_init(&lock->lock, NULL);
+	if (r)
+		BUG_ON(r);
+}
+
+void __sched mutex_destroy(struct mutex *lock)
+{
+	pthread_mutex_destroy(&lock->lock);
+}
+
+void __sched mutex_lock(struct mutex *lock)
+{
+	pthread_mutex_lock(&lock->lock);
+}
+
+void __sched mutex_unlock(struct mutex *lock)
+{
+	pthread_mutex_unlock(&lock->lock);
+}
diff --git a/tools/linker-tables/kernel/locking/spinlock.c b/tools/linker-tables/kernel/locking/spinlock.c
new file mode 100644
index 000000000000..5be2bc7cdece
--- /dev/null
+++ b/tools/linker-tables/kernel/locking/spinlock.c
@@ -0,0 +1,26 @@
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+
+void spin_lock_init(spinlock_t *lock)
+{
+	int r;
+
+	r = pthread_spin_init(lock, PTHREAD_PROCESS_SHARED);
+	if (r)
+		BUG_ON(r);
+}
+
+void spin_lock_destroy(spinlock_t *lock)
+{
+	pthread_spin_destroy(lock);
+}
+
+void spin_lock(spinlock_t *lock)
+{
+	pthread_spin_lock(lock);
+}
+
+void spin_unlock(spinlock_t *lock)
+{
+	pthread_spin_unlock(lock);
+}
diff --git a/tools/linker-tables/kernel/main.c b/tools/linker-tables/kernel/main.c
new file mode 100644
index 000000000000..ad7a19c038bf
--- /dev/null
+++ b/tools/linker-tables/kernel/main.c
@@ -0,0 +1,32 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/x86_init_fn.h>
+#include <asm/x86.h>
+
+DEFINE_LINKTABLE_INIT_DATA(initcall_t, init_calls);
+
+int do_one_initcall(initcall_t fn)
+{
+	int ret;
+
+	ret = fn();
+
+	return ret;
+}
+
+static void do_initcalls(void)
+{
+	initcall_t *fn;
+
+	 linktable_for_each(fn, init_calls)
+		 do_one_initcall(*fn);
+}
+
+void start_kernel(void)
+{
+	pr_info("Calling start_kernel()...\n");
+
+	setup_arch();
+	late_init();
+	do_initcalls();
+}
diff --git a/tools/linker-tables/kernel/workqueue.c b/tools/linker-tables/kernel/workqueue.c
new file mode 100644
index 000000000000..5ba73c7e7c8b
--- /dev/null
+++ b/tools/linker-tables/kernel/workqueue.c
@@ -0,0 +1,43 @@
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <linux/workqueue.h>
+#include <linux/kernel.h>
+
+void schedule_work(struct work *w)
+{
+	mutex_lock(&w->mutex);
+	pthread_cond_signal(&w->cond);
+	mutex_unlock(&w->mutex);
+}
+
+void cancel_work_sync(struct work *w)
+{
+	pthread_exit(NULL);
+}
+
+void *run_work(void *arg)
+{
+	struct work *w;
+	int r;
+
+	w = (struct work *) arg;
+
+	mutex_lock(&w->mutex);
+
+	while (true) {
+		if (!w->ready)
+			w->ready = true;
+		r = pthread_cond_wait(&w->cond, &w->mutex.lock);
+		if (r != 0) {
+			printf("(%s)\n", strerror(r));
+			BUG_ON(r);
+		}
+		w->work_cb(w->arg);
+	}
+
+	mutex_unlock(&w->mutex);
+
+	pthread_exit(NULL);
+}
diff --git a/tools/linker-tables/lib/string.c b/tools/linker-tables/lib/string.c
new file mode 100644
index 000000000000..95631c742f1d
--- /dev/null
+++ b/tools/linker-tables/lib/string.c
@@ -0,0 +1,26 @@
+/*
+ *  linux/lib/string.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  Licensed under GPLv2 - taken from linux-next next-20160803
+ */
+
+#include <linux/kernel.h>
+
+/**
+ * memset - Fill a region of memory with the given value
+ * @s: Pointer to the start of the area.
+ * @c: The byte to fill the area with
+ * @count: The size of the area.
+ *
+ * Do not use memset() to access IO space, use memset_io() instead.
+ */
+void *memset(void *s, int c, size_t count)
+{
+	char *xs = s;
+
+	while (count--)
+		*xs++ = c;
+	return s;
+}
diff --git a/tools/linker-tables/main.c b/tools/linker-tables/main.c
new file mode 100644
index 000000000000..c0b1f4c95112
--- /dev/null
+++ b/tools/linker-tables/main.c
@@ -0,0 +1,20 @@
+#include <linux/string.h>
+#include <xen/xen.h>
+#include <asm/x86.h>
+#include <asm/bootparam.h>
+
+struct boot_params boot_params __attribute__((aligned(16)));
+
+int main(int arg, char *argc[])
+{
+	memset(&boot_params, 0, sizeof(struct boot_params));
+
+	if (arg <= 1)
+		startup_64();
+	else {
+		boot_params.hdr.hardware_subarch = X86_SUBARCH_XEN;
+		startup_xen();
+	}
+
+	return 0;
+}
diff --git a/tools/linker-tables/pci-quirks.c b/tools/linker-tables/pci-quirks.c
new file mode 100644
index 000000000000..8aac79477eab
--- /dev/null
+++ b/tools/linker-tables/pci-quirks.c
@@ -0,0 +1,14 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <linux/pci.h>
+
+DEFINE_LINKTABLE_RO(struct pci_fixup, pci_fixup_early);
+
+static void foo_fixup(void)
+{
+	pr_info("foo_fixup\n");
+};
+
+LINKTABLE_RO(pci_fixup_early, 50) quirk_foo = {
+	.hook = foo_fixup,
+};
diff --git a/tools/linker-tables/pci.c b/tools/linker-tables/pci.c
new file mode 100644
index 000000000000..a452c0766800
--- /dev/null
+++ b/tools/linker-tables/pci.c
@@ -0,0 +1,30 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <asm/bootparam.h>
+#include <linux/pci.h>
+
+DECLARE_LINKTABLE(struct pci_fixup, pci_fixup_early);
+
+void early_init_pci(void)
+{
+
+	const struct pci_fixup *fixup;
+	unsigned int tbl_size = LINKTABLE_SIZE(pci_fixup_early);
+
+	pr_info("Initializing pci ...\n");
+
+	pr_info("PCI fixup size: %d\n", tbl_size);
+
+	sleep(1);
+	pr_info("Demo: Using linktable_for_each\n");
+	linktable_for_each(fixup, pci_fixup_early)
+		fixup->hook();
+
+	pr_info("Demo: Using linktable_run_all\n");
+	linktable_run_all(pci_fixup_early, hook,);
+
+	pr_info("Completed initializing pci !\n");
+}
+
+x86_init_early_all(early_init_pci);
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* [PATCH v4 6/6] tools: add userspace linker table sandbox
@ 2017-01-15 21:12             ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-15 21:12 UTC (permalink / raw)
  To: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux
  Cc: x86, luto, keescook, linux, torvalds, gregkh, rusty, gnomes,
	alan, dwmw2, arnd, ming.lei, linux-arch, benh, pebolle, fontana,
	david.vrabel, konrad.wilk, mcb30, jgross, andrew.cooper3,
	andriy.shevchenko, paul.gortmaker, xen-devel, ak, pali.rohar,
	dvhart, platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild

Add a userspace sandbox to allow easy experimentation and
test extensions with linker tables, section ranges and the
new section core definitions.

The userspace sandbox tries to mimic the Linux kernel development
flow as much as possible, it however relies on and uses libc. Support
is currently only provided to x86_64.

Demo run:

cd tools/linker-tables
make clean; make;
./demo
Initializing x86 bare metal world
x86-init: Number of init entries: 8
Initializing memory ...
Completed initializing memory !
Initializing pci ...
PCI fixup size: 1
Demo: Using LINKTABLE_FOR_EACH
foo_fixup
Demo: Using LINKTABLE_RUN_ALL
foo_fixup
Completed initializing pci !
Number of init entries: 1
Initializing kprobes ...
= OK: test_kprobe_0001 within range!
= OK: test_kprobe_0002 not in range as expected!
Completed initializing kprobes !
Initializing kasan ...
Early init for Kasan...
Completed initializing kasan !
Initializing beta ...
Completed initializing beta !
Initializing alpha ...
Completed initializing alpha !
Booting bare metal
Calling start_kernel()...
ACME: Initializing ...
ACME: Finished init ... !
Synthetics: synth_init_or(2) returns: 0xDEADBEEF
Synthetics: ps_shr(0xDEADBEEF, get_demo_shr) returns: 0x0000DEAD

v7: address ./scripts/checkpatch.pl --codespell complaints

v6: rename table macros as suggested by Andy Shevchenko

v5:

o Use ..rng.* instead of .rng.* as suggested by Nicholas Piggin.
  This is the typical way to avoid clashes with compiler generated
  sections.

o moves tools/include/linux/printk.h to tools
  linker-table/include/linux/printk.h -- we cannot generalize this
  just yet, more work is needed in terms of providing a namespace for
  headers for types of ports of kernel functionality to userspace.

o Adjust code according to the latest discussions for the linker
  tables API (section name macros are now gone).

o Give CONFIG_HAVE_ARCH_PS_CONST for x86 another good 'ol college try,
  still fails, but this is just a demo anyway. We can amend and fix
  make this more optimized for x86 later. Thanks Boris!

v4: this patch is new in this series -- added to the kenrel as
    suggested by Boris, as otherwise it'd be really hard to keep
    an external userspace repository in sync.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
 Documentation/sections/linker-tables.rst           |   4 +-
 MAINTAINERS                                        |   1 +
 include/linux/tables.h                             |   5 +-
 tools/Makefile                                     |   3 +-
 .../arch/x86/include/generated/asm/section-core.h  |   1 +
 tools/arch/x86/include/generated/ranges.h          |   1 +
 tools/arch/x86/include/generated/tables.h          |   1 +
 tools/include/asm-generic/ranges.h                 |  93 +++
 tools/include/asm-generic/section-core.h           | 348 +++++++++++
 tools/include/asm-generic/tables.h                 |  48 ++
 tools/include/linux/ranges.h                       | 183 ++++++
 tools/include/linux/sections.h                     |  87 +++
 tools/include/linux/string.h                       |   1 +
 tools/include/linux/tables.h                       | 684 +++++++++++++++++++++
 tools/linker-tables/.gitignore                     |   2 +
 tools/linker-tables/Makefile                       | 184 ++++++
 tools/linker-tables/README                         | 114 ++++
 tools/linker-tables/arch/x86/include/asm/asm.h     |  17 +
 tools/linker-tables/arch/x86/include/asm/boot.h    |   1 +
 .../linker-tables/arch/x86/include/asm/bootparam.h |  32 +
 tools/linker-tables/arch/x86/include/asm/kprobes.h |   7 +
 .../linker-tables/arch/x86/include/asm/ps_const.h  |  23 +
 tools/linker-tables/arch/x86/include/asm/ranges.h  |   6 +
 .../arch/x86/include/asm/section-core.h            |   1 +
 tools/linker-tables/arch/x86/include/asm/setup.h   |   6 +
 tools/linker-tables/arch/x86/include/asm/tables.h  |   6 +
 tools/linker-tables/arch/x86/include/asm/x86.h     |   4 +
 .../arch/x86/include/asm/x86_init_fn.h             | 169 +++++
 tools/linker-tables/arch/x86/kernel/alpha.c        |  10 +
 tools/linker-tables/arch/x86/kernel/alternative.c  |  31 +
 tools/linker-tables/arch/x86/kernel/beta.c         |  10 +
 tools/linker-tables/arch/x86/kernel/head64.c       |  58 ++
 tools/linker-tables/arch/x86/kernel/init.c         |  42 ++
 tools/linker-tables/arch/x86/kernel/kasan.c        |  11 +
 tools/linker-tables/arch/x86/kernel/kprobes.c      |  51 ++
 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S  | 277 +++++++++
 tools/linker-tables/arch/x86/mm/init.c             |  11 +
 tools/linker-tables/arch/x86/xen/init.c            |  13 +
 tools/linker-tables/drivers/acme.c                 |  33 +
 tools/linker-tables/drivers/synth/common.c         |  16 +
 tools/linker-tables/drivers/synth/common.h         |   2 +
 tools/linker-tables/drivers/synth/main.c           |  36 ++
 tools/linker-tables/drivers/synth/or.S             |  39 ++
 tools/linker-tables/drivers/synth/synth.h          |   2 +
 tools/linker-tables/drivers/xen-driver.c           |  12 +
 .../include/asm-generic/arch_init_fn.h             |  50 ++
 tools/linker-tables/include/asm-generic/kprobes.h  |  26 +
 tools/linker-tables/include/linux/bitops.h         |   6 +
 tools/linker-tables/include/linux/init.h           |  40 ++
 tools/linker-tables/include/linux/kasan.h          |   5 +
 tools/linker-tables/include/linux/kernel.h         |   2 +
 tools/linker-tables/include/linux/kprobes.h        |  11 +
 tools/linker-tables/include/linux/module.h         |  14 +
 tools/linker-tables/include/linux/mutex.h          |  17 +
 tools/linker-tables/include/linux/pci.h            |   7 +
 tools/linker-tables/include/linux/printk.h         |  26 +
 tools/linker-tables/include/linux/ps_const.h       |  46 ++
 tools/linker-tables/include/linux/sched.h          |   9 +
 tools/linker-tables/include/linux/spinlock.h       |  13 +
 tools/linker-tables/include/linux/start_kernel.h   |   1 +
 tools/linker-tables/include/linux/types.h          |  13 +
 tools/linker-tables/include/linux/workqueue.h      |  51 ++
 tools/linker-tables/include/xen/xen.h              |   4 +
 tools/linker-tables/kernel/locking/mutex.c         |  28 +
 tools/linker-tables/kernel/locking/spinlock.c      |  26 +
 tools/linker-tables/kernel/main.c                  |  32 +
 tools/linker-tables/kernel/workqueue.c             |  43 ++
 tools/linker-tables/lib/string.c                   |  26 +
 tools/linker-tables/main.c                         |  20 +
 tools/linker-tables/pci-quirks.c                   |  14 +
 tools/linker-tables/pci.c                          |  30 +
 71 files changed, 3241 insertions(+), 5 deletions(-)
 create mode 100644 tools/arch/x86/include/generated/asm/section-core.h
 create mode 100644 tools/arch/x86/include/generated/ranges.h
 create mode 100644 tools/arch/x86/include/generated/tables.h
 create mode 100644 tools/include/asm-generic/ranges.h
 create mode 100644 tools/include/asm-generic/section-core.h
 create mode 100644 tools/include/asm-generic/tables.h
 create mode 100644 tools/include/linux/ranges.h
 create mode 100644 tools/include/linux/sections.h
 create mode 100644 tools/include/linux/tables.h
 create mode 100644 tools/linker-tables/.gitignore
 create mode 100644 tools/linker-tables/Makefile
 create mode 100644 tools/linker-tables/README
 create mode 100644 tools/linker-tables/arch/x86/include/asm/asm.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/boot.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/bootparam.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/kprobes.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ps_const.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/ranges.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/section-core.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/setup.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/tables.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86.h
 create mode 100644 tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
 create mode 100644 tools/linker-tables/arch/x86/kernel/alpha.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/alternative.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/beta.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/head64.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/init.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kasan.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/kprobes.c
 create mode 100644 tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
 create mode 100644 tools/linker-tables/arch/x86/mm/init.c
 create mode 100644 tools/linker-tables/arch/x86/xen/init.c
 create mode 100644 tools/linker-tables/drivers/acme.c
 create mode 100644 tools/linker-tables/drivers/synth/common.c
 create mode 100644 tools/linker-tables/drivers/synth/common.h
 create mode 100644 tools/linker-tables/drivers/synth/main.c
 create mode 100644 tools/linker-tables/drivers/synth/or.S
 create mode 100644 tools/linker-tables/drivers/synth/synth.h
 create mode 100644 tools/linker-tables/drivers/xen-driver.c
 create mode 100644 tools/linker-tables/include/asm-generic/arch_init_fn.h
 create mode 100644 tools/linker-tables/include/asm-generic/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/bitops.h
 create mode 100644 tools/linker-tables/include/linux/init.h
 create mode 100644 tools/linker-tables/include/linux/kasan.h
 create mode 100644 tools/linker-tables/include/linux/kernel.h
 create mode 100644 tools/linker-tables/include/linux/kprobes.h
 create mode 100644 tools/linker-tables/include/linux/module.h
 create mode 100644 tools/linker-tables/include/linux/mutex.h
 create mode 100644 tools/linker-tables/include/linux/pci.h
 create mode 100644 tools/linker-tables/include/linux/printk.h
 create mode 100644 tools/linker-tables/include/linux/ps_const.h
 create mode 100644 tools/linker-tables/include/linux/sched.h
 create mode 100644 tools/linker-tables/include/linux/spinlock.h
 create mode 100644 tools/linker-tables/include/linux/start_kernel.h
 create mode 100644 tools/linker-tables/include/linux/types.h
 create mode 100644 tools/linker-tables/include/linux/workqueue.h
 create mode 100644 tools/linker-tables/include/xen/xen.h
 create mode 100644 tools/linker-tables/kernel/locking/mutex.c
 create mode 100644 tools/linker-tables/kernel/locking/spinlock.c
 create mode 100644 tools/linker-tables/kernel/main.c
 create mode 100644 tools/linker-tables/kernel/workqueue.c
 create mode 100644 tools/linker-tables/lib/string.c
 create mode 100644 tools/linker-tables/main.c
 create mode 100644 tools/linker-tables/pci-quirks.c
 create mode 100644 tools/linker-tables/pci.c

diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
index bc2d9f46cde6..2f2bb1fc0798 100644
--- a/Documentation/sections/linker-tables.rst
+++ b/Documentation/sections/linker-tables.rst
@@ -11,11 +11,11 @@ About Linker tables
 .. kernel-doc:: include/linux/tables.h
    :doc: Introduction
 
-Linker table provenance
+Linker table provenance and userspace testing
 ---------------------------------------------
 
 .. kernel-doc:: include/linux/tables.h
-   :doc: Linker table provenance
+   :doc: Linker table provenance and userspace testing
 
 Benefits of using Linker tables
 ===============diff --git a/MAINTAINERS b/MAINTAINERS
index cee1efd50e04..b83bd957011e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5429,6 +5429,7 @@ L:	linux-kernel@vger.kernel.org
 S:	Supported
 F:	include/asm-generic/tables.h
 F:	include/linux/tables.h
+F:	tools/linker-tables/
 F:	Documentation/sections/linker-tables.rst
 
 GENERIC PHY FRAMEWORK
diff --git a/include/linux/tables.h b/include/linux/tables.h
index f295fbe74734..9dd8f947b60b 100644
--- a/include/linux/tables.h
+++ b/include/linux/tables.h
@@ -35,12 +35,13 @@
  */
 
 /**
- * DOC: Linker table provenance
+ * DOC: Linker table provenance and userspace testing
  *
  * 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].
+ * userspace linker-table tree [1]. Linux has a similar userspace application
+ * in tools/linker-tables/ to help more easily test adding new extensions.
  *
  * Contrary to iPXE's solution which strives to force compilation of
  * everything using linker tables, Linux's solution allows for developers to be
diff --git a/tools/Makefile b/tools/Makefile
index 00caacd3ed92..ecb2e651c930 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -19,6 +19,7 @@ help:
 	@echo '  kvm_stat               - top-like utility for displaying kvm statistics'
 	@echo '  leds                   - LEDs  tools'
 	@echo '  lguest                 - a minimal 32-bit x86 hypervisor'
+	@echo '  linker-tables		- userspace liker table sandbox and related tools'
 	@echo '  net                    - misc networking tools'
 	@echo '  perf                   - Linux performance measurement and analysis tool'
 	@echo '  selftests              - various kernel selftests'
@@ -86,7 +87,7 @@ tmon: FORCE
 freefall: FORCE
 	$(call descend,laptop/$@)
 
-all: acpi cgroup cpupower gpio hv firewire lguest \
+all: acpi cgroup cpupower gpio hv firewire lguest linker-tables \
 		perf selftests turbostat usb \
 		virtio vm net x86_energy_perf_policy \
 		tmon freefall objtool
diff --git a/tools/arch/x86/include/generated/asm/section-core.h b/tools/arch/x86/include/generated/asm/section-core.h
new file mode 100644
index 000000000000..06be2b1c424f
--- /dev/null
+++ b/tools/arch/x86/include/generated/asm/section-core.h
@@ -0,0 +1 @@
+#include <asm-generic/section-core.h>
diff --git a/tools/arch/x86/include/generated/ranges.h b/tools/arch/x86/include/generated/ranges.h
new file mode 100644
index 000000000000..dac1a9a11367
--- /dev/null
+++ b/tools/arch/x86/include/generated/ranges.h
@@ -0,0 +1 @@
+#include <asm-generic/ranges.h>
diff --git a/tools/arch/x86/include/generated/tables.h b/tools/arch/x86/include/generated/tables.h
new file mode 100644
index 000000000000..d437818275c5
--- /dev/null
+++ b/tools/arch/x86/include/generated/tables.h
@@ -0,0 +1 @@
+#include <asm-generic/tables.h>
diff --git a/tools/include/asm-generic/ranges.h b/tools/include/asm-generic/ranges.h
new file mode 100644
index 000000000000..10e67bcf6dbe
--- /dev/null
+++ b/tools/include/asm-generic/ranges.h
@@ -0,0 +1,93 @@
+#ifndef _ASM_GENERIC_RANGES_H_
+#define _ASM_GENERIC_RANGES_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/.
+ */
+#include <asm/section-core.h>
+
+#ifndef set_section_rng
+# define set_section_rng(section, name, flags)				\
+	 set_section_core(section, rng, name,				\
+			  any, flags)
+#endif
+
+#ifndef set_section_rng_type
+# define set_section_rng_type(section, name, flags, type)		\
+	 set_section_core_type(section, rng, name,			\
+			       any, flags, type)
+#endif
+
+#ifndef set_section_rng_level
+# define set_section_rng_level(section, name, level, flags)		\
+	 set_section_core(section, rng, name, level, flags)
+#endif
+
+#ifndef push_section_rng
+# define push_section_rng(section, name, flags)				\
+	 push_section_core(section, rng, name,				\
+			   any, flags)
+#endif
+
+#ifndef push_section_rng_level
+# define push_section_rng_level(section, name, level, flags)		\
+	 push_section_core(section, rng, name,				\
+			   level, flags)
+#endif
+
+#ifndef __ASSEMBLY__
+/**
+ * __LINUX_RANGE - short hand association into a section range
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ *
+ * This helper can be used by subsystems to define their own subsystem
+ * specific helpers to easily associate a piece of code being defined to a
+ * section range.
+ */
+#define __LINUX_RANGE(section, name)					\
+	__attribute__((__section__(#section "..rng.name.any")))
+
+/**
+ * __LINUX_RANGE_ORDER - short hand association into a section range of order
+ *
+ * @section: ELF section name to place section range into
+ * @name: section range name
+ * @level: order level, a number. The order level gets tucked into the
+ *	section as a postfix string. Order levels are sorted using binutils
+ *	SORT(), the number is sorted as a string, as such be sure to fill with
+ *	zeroes any empty digits. For instance if you are using 3 levels of
+ *	digits for order levels, use 001 for the first entry, 0002 for the
+ *	second, 999 for the last entry. You can use however many digits you
+ *	need.
+ *
+ * This helper can be used by subsystems to define their own subsystem specific
+ * helpers to easily associate a piece of code being defined to a section range
+ * with an associated specific order level. The order level provides the
+ * ability for explicit user ordering of code. Sorting takes place at link
+ * time, after compilation.
+ */
+#define __LINUX_RANGE_ORDER(section, name, level)			\
+	__attribute__((__section__(#section "..rng.name." #level)))
+
+#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/tools/include/asm-generic/section-core.h b/tools/include/asm-generic/section-core.h
new file mode 100644
index 000000000000..e2db4da87222
--- /dev/null
+++ b/tools/include/asm-generic/section-core.h
@@ -0,0 +1,348 @@
+#ifndef _ASM_GENERIC_SECTION_CORE_H_
+#define _ASM_GENERIC_SECTION_CORE_H_
+/*
+ * Linux section core definitions
+ *
+ * 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/.
+ */
+
+/**
+ * DOC: Linux ELF program specific sections
+ *
+ * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and
+ * definition of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
+ * sections. This chapter is dedicated to documenting Linux program specific
+ * sections and helpers available to make use of these easier to implement and
+ * use.
+ *
+ * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
+ */
+
+/**
+ * DOC: Linux linker script
+ *
+ * Linux uses a custom linker script to build the vmlinux binary, it uses it to
+ * strategically place and define Linux ELF sections.  Each architecture needs
+ * to implement its own linker script, it is expected to reside in
+ * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
+ * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
+ * as well as some helpers documented in this chapter.
+ *
+ * In assembly it is common practice to use dots (``.``) in labels to avoid
+ * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
+ * name but not a C symbol. Historically then, two dots are used (``..``)
+ * have been used in linker scripts when adding program specific sections
+ * when there are concerns to avoid clashes with compiler generated sections.
+ */
+
+/**
+ * DOC: Memory protection
+ *
+ * Linux allows architectures which support memory protection features to
+ * take advantage of them by letting architectures define and enable
+ * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.
+ * mark_rodata_ro() can be used for instance to mark specific sections as
+ * read-only or non-executable.
+ *
+ * Linux typically follows a convention to have the .rodata ELF section follow
+ * after the .text ELF section, it does this to help architectures which
+ * support memory protection to mark both .text and .rodata as read-only in
+ * one shot.
+ *
+ * For more details refer to mark_rodata_ro().
+ */
+
+/**
+ * DOC: .rodata
+ *
+ * ELF section used for data which must be protected from write access.
+ */
+
+/**
+ * DOC: .text
+ *
+ * ELF section name used for code (functions) used during regular
+ * kernel run time.
+ */
+
+/**
+ * DOC: .data
+ *
+ * ELF section used for read-write data.
+ */
+
+/**
+ * DOC: Linux init sections
+ *
+ * These sections are used for code and data structures used during boot or
+ * module initialization. On architectures that support it (x86, x86_64), all
+ * this code is freed up by the kernel right before the fist userspace init
+ * process is called when built-in to the kernel, and if modular it is freed
+ * after module initialization. Since the code is freed so early, in theory
+ * there should be no races against freeing this code with other CPUs. Init
+ * section code and data structures should never be exported with
+ * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
+ * after bootup.
+ */
+
+/**
+ * DOC: .init.text
+ *
+ * ELF section for code (functions) used only during boot or driver
+ * initialization.
+ *
+ */
+
+/**
+ * DOC: .init.data
+ *
+ * ELF section used for data structures used only during boot or driver
+ * initialization.
+ */
+
+/**
+ * DOC: .init.rodata
+ *
+ * ELF section used for read-only code (functions) used only during boot
+ * or driver initialization.
+ */
+
+/**
+ * DOC: .initcall
+ *
+ * ELF section used for subsystem init calls. There are init levels
+ * representing different functionality in the kernel. For more details
+ * refer to __define_initcall().
+ */
+
+/**
+ * DOC: Linux exit sections
+ *
+ * These sections are used to declare a functions and data structures which
+ * are only required on exit, the function or data structure will be dropped
+ * if the code declaring this section is not compiled as a module on
+ * architectures that support this (x86, x86_64). There is no special case
+ * handling for this code when built-in to the kernel.
+ */
+
+/**
+ * DOC: .exit.text
+ *
+ * ELF section used to for code (functions) used only during module unload.
+ */
+
+/**
+ * DOC: .exit.data
+ *
+ * ELF section used to for data structures used only during module
+ * unload.
+ */
+
+/**
+ * DOC: .exitcall.exit
+ *
+ * ELF section used for exit routines, order is important and maintained by
+ * link order.
+ */
+
+/**
+ * DOC: Linux references to init sections
+ *
+ * These sections are used to teach modpost to not warn about possible
+ * misuses of init section code from other sections. If you use this
+ * your use case should document why you are certain such use of init
+ * sectioned code is valid. For more details refer to ``include/linux/init.h``
+ * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
+ */
+
+/**
+ * DOC: .ref.text
+ *
+ * ELF section used to annotate code (functions) which has been vetted as
+ * valid for its reference or use of other code (functions) or data structures
+ * which are part of the init sections.
+ */
+
+/**
+ * DOC: .ref.data
+ *
+ * ELF section used for data structures which have been vetted for its
+ * reference or use of other code (functions) or data structures part of the
+ * init sections.
+ */
+
+/**
+ * DOC: .ref.rodata
+ *
+ * ELF section used to annotate const code (functions) const data structures
+ * which has been vetted for its reference or use of other code (functions)
+ * or data structures part of the init sections.
+ */
+
+/**
+ * DOC: Linux section ordering
+ *
+ * Linux may use binutils linker-script 'SORT()' on sections to sort Linux
+ * sections alpha numerically. Linux has historically used 'SORT()' in
+ * ``include/asm-generic/vmlinux.lds.h``, its a well established practice. If
+ * 'SORT()' is used on a section one can provide ordering using a postfix on
+ * each section entry added. For instance if a linker script uses::
+ *
+ *    SORT(.foo.*)
+ *
+ * one can then add entries with explicit ordering using numeric postfixes for
+ * each entry, we refer to these as 'order levels'. Since 'SORT()' sorts alpha
+ * numerically a specific series set of digits must be agreed a-priori which
+ * would give also an idea of the max expected number of entries added to a
+ * section. For instance, if you expect a maximum of 999 entries you can use
+ * 3 digits for a section order level. If you wanted an entry to be ordered
+ * first you could use the postfix '000', if you wanted an entry to follow this
+ * you could use '001', and so on. We could for instance have::
+ *
+ *    .foo.000
+ *    .foo.001
+ *    .foo.002
+ *
+ * Often times one may want the option to specify no order is required for
+ * certain elements added to a section which does use 'SORT()' on the linker
+ * script. You can use any arbitrary string value to to specify no order is
+ * used, so long as its used consistantly. For instance, one possibility is to
+ * use the 'any' postfix.  All entries on the section would then have no
+ * specific ordering::
+ *
+ *    .foo.any
+ *    .foo.any
+ *    .foo.any
+ *
+ * To help establish a convention we reserve the special name 'any' for this
+ * purpose. Developers can use and expect the 'any' postfix string on sections
+ * as a helper to annotate section ordering at link time is not relevant
+ * for entries on a section.
+ */
+
+/* Can be used on foo.S for instance */
+#ifndef __set_section_core_type
+# define __set_section_core_type(___section, ___core, ___name,		\
+				 ___level, ___flags, ___type)		\
+	.section ___section..___core.___name.___level, ___flags, ___type
+#endif
+
+#ifndef __set_section_core
+# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
+	.section ___section..___core.___name.___level, ___flags
+#endif
+
+#ifndef __push_section_core
+# define __push_section_core(__section, __core, __name, __level, __flags) \
+	.pushsection __section..__core.__name.__level, __flags
+#endif
+
+#ifdef __KERNEL__
+#include <linux/stringify.h>
+#endif
+
+#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
+
+# ifndef LINKER_SCRIPT
+
+#  ifndef push_section_core
+#   define push_section_core(__section, __core, __name, __level, __flags) \
+	 __push_section_core(__section, __core, __name,			  \
+			     __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core
+#   define set_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__set_section_core(__section, __core, __name,			\
+			   __level, __stringify(__flags))
+#  endif
+
+#  ifndef set_section_core_type
+#   define set_section_core_type(__section, __core, __name,		\
+				 __level, __flags, __type)		\
+	__set_section_core_type(__section, __core, __name, __level,	\
+				__stringify(__flags), __type)
+#  endif
+
+# endif /* LINKER_SCRIPT */
+#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+
+/*
+ * As per gcc's documentation a common asm separator is a new line followed
+ * by tab [0], it however seems possible to also just use a newline as its
+ * the most commonly empirically observed semantic and folks seem to agree
+ * this even works on S390. In case your architecture disagrees you may
+ * override this and define your own and keep the rest of the macros.
+ *
+ * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
+ */
+# ifndef ASM_CMD_SEP
+#  define ASM_CMD_SEP	"\n"
+# endif
+
+# ifndef set_section_core
+#  define set_section_core(__section, __core, __name, __level, __flags)	\
+	__stringify(__set_section_core_type(__section, __core, __name,	\
+					    __level, __stringify(__flags))) \
+	ASM_CMD_SEP
+# endif
+
+/*
+ * Some architectures (arm, and avr32 are two examples on kprobes) seem
+ * currently explicitly specify the type [0] -- this can be any of the
+ * optional constants on ELF:
+ *
+ * @progbits - section contains data
+ * @nobits - section does not contain data (i.e., section only occupies space)
+ * @note - section contains data which is used by things other than the program
+ * @init_array - section contains an array of pointers to init functions
+ * @fini_array - section contains an array of pointers to finish functions
+ * @preinit_array - section contains an array of pointers to pre-init functions
+ *
+ * ARM requires % instead of @.
+ *
+ * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
+ * defaults are as follows:
+ *
+ * section .text    progbits  alloc   exec    nowrite  align\x16
+ * section .rodata  progbits  alloc   noexec  nowrite  align=4
+ * section .lrodata progbits  alloc   noexec  nowrite  align=4
+ * section .data    progbits  alloc   noexec  write    align=4
+ * section .ldata   progbits  alloc   noexec  write    align=4
+ * section .bss     nobits    alloc   noexec  write    align=4
+ * section .lbss    nobits    alloc   noexec  write    align=4
+ * section .tdata   progbits  alloc   noexec  write    align=4    tls
+ * section .tbss    nobits    alloc   noexec  write    align=4    tls
+ * section .comment progbits  noalloc noexec  nowrite  align=1
+ * section other    progbits  alloc   noexec  nowrite  align=1
+ *
+ * gas should have sensible defaults for architectures...
+ *
+ * [0] http://www.nasm.us/doc/nasmdoc7.html
+ */
+# ifndef set_section_core_type
+#  define set_section_core_type(__section, __core, __name, __level,	\
+				__flags, __type)			\
+	__stringify(__set_section_core_type(__section, __core,		\
+					    __name, __level,		\
+					    __stringify(__flags),	\
+					    __type))			\
+	ASM_CMD_SEP
+# endif
+
+# ifndef push_section_core
+#  define push_section_core(__section, __core, __name,			\
+			    __level, __flags)				\
+	__stringify(__push_section_core(__section, __core,		\
+					__name,	__level,		\
+					__stringify(__flags)))		\
+	ASM_CMD_SEP
+# endif
+
+#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
+#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
diff --git a/tools/include/asm-generic/tables.h b/tools/include/asm-generic/tables.h
new file mode 100644
index 000000000000..567775b292c2
--- /dev/null
+++ b/tools/include/asm-generic/tables.h
@@ -0,0 +1,48 @@
+#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..tbl.name.level
+
+/* Some toolchains are buggy, let them override */
+#ifndef SECTION_TBL_RO
+# define SECTION_TBL_RO	.rodata
+#endif
+
+#define SECTION_TBL_RO_STR __stringify(SECTION_TBL_RO)
+
+#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, 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, any, flags)
+#endif
+
+#endif /* _ASM_GENERIC_TABLES_H_ */
diff --git a/tools/include/linux/ranges.h b/tools/include/linux/ranges.h
new file mode 100644
index 000000000000..3368fc475cd8
--- /dev/null
+++ b/tools/include/linux/ranges.h
@@ -0,0 +1,183 @@
+#ifndef _LINUX_RANGES_H
+#define _LINUX_RANGES_H
+/*
+ * Linux section ranges
+ *
+ * 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/sections.h>
+#include <asm/ranges.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * A section ranges consists of explicitly annotated series executable code
+ * stitched together for the purpose of selective placement into standard or
+ * architecture specific ELF sections. What ELF section is used is utility
+ * specific. Linux has historically implicitly used section ranges, however
+ * they were all built in an adhoc manner and typically required linker script
+ * modifications per architecture. The section range API allows adding new
+ * bundles of stiched executable code into custom ELF sections by only
+ * modifying C or asm code in an architecture agnostic form.
+ *
+ * This documents the set of helpers available to declare, and define section
+ * ranges and associate each section range to a specific Linux ELF section.
+ */
+
+/**
+ * DOC: Section range module support
+ *
+ * Modules can use section ranges, however the section range definition must be
+ * built-in to the kernel. That is, the code that implements
+ * DEFINE_SECTION_RANGE() must be built-in, and modular code cannot add more
+ * items in to the section range (with __LINUX_RANGE() or
+ * __LINUX_RANGE_ORDER()), 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: Section range helpers
+ *
+ * These are helpers for section ranges.
+ */
+
+/**
+ * SECTION_RANGE_START - get address of start of section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the start address of the section range.
+ * This should give you the address of the first entry.
+ *
+ */
+#define SECTION_RANGE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * SECTION_RANGE_END - get address of end of the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define SECTION_RANGE_END(name)		LINUX_SECTION_END(name)
+
+/**
+ * SECTION_RANGE_SIZE - get number of entries in the section range
+ *
+ * @name: name of the section range
+ *
+ * This gives you the number of entries in the section range.
+ * Example usage:
+ *
+ *   unsigned int num_ents = LINKTABLE_SIZE(some_fns);
+ */
+#define SECTION_RANGE_SIZE(name)					\
+	((SECTION_RANGE_END(name)) - (SECTION_RANGE_START(name)))
+
+/**
+ * SECTION_RANGE_EMPTY - check if section range has no entries
+ *
+ * @name: name of the section range
+ *
+ * Returns true if the section range is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(some_fns);
+ */
+#define SECTION_RANGE_EMPTY(name)	(SECTION_RANGE_SIZE(name) = 0)
+
+/**
+ * SECTION_RANGE_ADDR_WITHIN - returns true if address is in the section range
+ *
+ * @name: name of the section range
+ * @addr: address to query for
+ *
+ * Returns true if the address is in the section range.
+ */
+#define SECTION_RANGE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) SECTION_RANGE_START(name) &&		\
+	  addr < (unsigned long) SECTION_RANGE_END(name))
+
+/**
+ * SECTION_RANGE_ALIGNMENT - get the alignment of the section range
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the section range.
+ */
+#define SECTION_RANGE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * DECLARE_SECTION_RANGE - Declares a section range
+ *
+ * @name: section range name
+ *
+ * Declares a section range to help code access the range. Typically if
+ * a subsystems needs code to have direct access to the section range the
+ * subsystem's header file would declare the section range. Care should be
+ * taken to only declare the section range in a header file if access to it
+ * is truly needed outside of the code defining it. You typically would
+ * rather instead provide helpers which access the section range with special
+ * code on behalf of the caller.
+ */
+#define DECLARE_SECTION_RANGE(name)					\
+	DECLARE_LINUX_SECTION_RO(char, name)
+
+/**
+ * __SECTION_RANGE_BEGIN - Constructs the beginning of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the beginning of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_BEGIN(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.")))
+
+/**
+ * __SECTION_RANGE_END - Constructs the end of a section range
+ *
+ * @name: section range name
+ * @__section: ELF section to place section range into
+ *
+ * Constructs the end of a section range. You will typically not need
+ * to use this directly.
+ */
+#define __SECTION_RANGE_END(name, __section)				\
+	const __typeof__(SECTION_RANGE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(SECTION_RANGE_ALIGNMENT(name)),\
+			     section(#__section "..rng.name.~")))
+
+/**
+ * DEFINE_SECTION_RANGE - Defines a section range
+ *
+ * @name: section range name
+ * @section: ELF section name to place section range into
+ *
+ * Defines a section range, used for executable code. Section ranges are
+ * defined in the code that takes ownership and makes use of the section
+ * range.
+ */
+#define DEFINE_SECTION_RANGE(name, section)				\
+	DECLARE_LINUX_SECTION_RO(char, name);				\
+	__SECTION_RANGE_BEGIN(name, section) SECTION_RANGE_START(name)[0] = {};\
+	__SECTION_RANGE_END(name, section) SECTION_RANGE_END(name)[0] = {}
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_RANGES_H */
diff --git a/tools/include/linux/sections.h b/tools/include/linux/sections.h
new file mode 100644
index 000000000000..6771c727bcd1
--- /dev/null
+++ b/tools/include/linux/sections.h
@@ -0,0 +1,87 @@
+#ifndef _LINUX_SECTIONS_H
+#define _LINUX_SECTIONS_H
+/*
+ * Linux de-facto sections
+ *
+ * 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>
+#include <linux/export.h>
+
+#ifndef __ASSEMBLY__
+
+/**
+ * DOC: Introduction
+ *
+ * Linux defines a set of common helpers which can be used to against its use
+ * of standard or custom Linux sections, this section is dedicated to these
+ * helpers.
+ */
+
+/**
+ * LINUX_SECTION_ALIGNMENT - get section alignment
+ *
+ * @name: section name
+ *
+ * Gives you the alignment for the section.
+ */
+#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))
+
+/**
+ * LINUX_SECTION_START - get address of start of section
+ *
+ * @name: section name
+ *
+ * This gives you the start address of the section.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)
+
+/**
+ * LINUX_SECTION_END - get address of end of the section
+ *
+ * @name: section name
+ *
+ * This gives you the end address of the section.
+ * This should give you the address of the end of the
+ * section. This will match the start address if the
+ * section is empty.
+ */
+#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
+
+/**
+ * DECLARE_LINUX_SECTION - Declares a custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-write custom Linux section
+ */
+#define DECLARE_LINUX_SECTION(type, name)				\
+	 extern type VMLINUX_SYMBOL(name)[], \
+		     VMLINUX_SYMBOL(name##__end)[]
+
+/**
+ * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section
+ *
+ * @type: type of custom Linux section
+ * @name: custom section name
+ *
+ * Declares a read-only custom Linux section
+ */
+#define DECLARE_LINUX_SECTION_RO(type, name)				\
+	 extern const type VMLINUX_SYMBOL(name)[],			\
+			   VMLINUX_SYMBOL(name##__end)[]
+
+#define __SECTION_CORE(section, core, name, level)			\
+	#section ".." #core "." #name "." #level
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_SECTIONS_H */
diff --git a/tools/include/linux/string.h b/tools/include/linux/string.h
index f436d2420a18..a6b12564bbd9 100644
--- a/tools/include/linux/string.h
+++ b/tools/include/linux/string.h
@@ -3,6 +3,7 @@
 
 
 #include <linux/types.h>	/* for size_t */
+#include <string.h>
 
 void *memdup(const void *src, size_t len);
 
diff --git a/tools/include/linux/tables.h b/tools/include/linux/tables.h
new file mode 100644
index 000000000000..9dd8f947b60b
--- /dev/null
+++ b/tools/include/linux/tables.h
@@ -0,0 +1,684 @@
+#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 and userspace testing
+ *
+ * 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]. Linux has a similar userspace application
+ * in tools/linker-tables/ to help more easily test adding new extensions.
+ *
+ * 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(.foo..tbl.*))
+ *
+ * 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: The code bit-rot problem
+ *
+ * Linux provides a rich array of features, enabling each feature
+ * however increases the size of the kernel and there are many
+ * features which users often want disabled. The traditional
+ * solution to this problem is for each feature to have its own
+ * Kconfig symbol, followed by a series of #ifdef statements
+ * in C code and header files, allowing the feature to be compiled
+ * only when desirable. As the variability of Linux increases build
+ * tests can and are often done with random kernel configurations,
+ * allyesconfig, and allmodconfig to help find code issues. This
+ * however doesn't catch all errors and as a consequence code that
+ * is typically not enabled often can suffer from bit-rot over time.
+ */
+
+/**
+ * DOC: The build-all selective-link philosophy
+ *
+ * A code architecture philosophy to help avoid code bit-rot consists
+ * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
+ * by instead having each feature implemented it its own C file, and force
+ * compilation for all features. Only features that are enabled get linked in,
+ * the forced compilation therefore has no size impact on the final result of
+ * the kernel. The practice of having each feature implemented in its own C
+ * file is already prevalent in many subsystems, however #ifdefs are still
+ * typically required during feature initialization. For instance in::
+ *
+ *	#ifdef CONFIG_FOO
+ *	foo_init();
+ *	#endif
+ *
+ * We cannot remove the #ifdef and leave foo_init() as we'd either
+ * need to always enable the feature or add a respective #ifdef in a
+ * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
+ */
+
+/**
+ * DOC: Avoiding the code bit-rot problem with linker tables
+ *
+ * Linker tables can be used to further help avoid the code bit-rot problem
+ * when embracing the 'build-all selective-link philosophy' by lifting the
+ * requirement to use of #ifdefs during initialization. With linker tables
+ * initialization sequences can be aggregated into a custom ELF section at
+ * link time, during run time the table can be iterated over and each init
+ * sequence enabled can be called. A feature's init routine is only added to a
+ * table when its respective Kconfig symbols has been enabled and therefore
+ * linked in. Linker tables enable subsystems to completely do away with
+ * #ifdefs if one is comfortable in accepting all subsystem's feature's
+ * structural size implications.
+ *
+ * To further help with this the Linux build system supports two special
+ * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
+ * follow the 'build-all selective-link philosophy' can use these targets for a
+ * feature's kconfig symbol. Using these targets will always require
+ * compilation of the kconfig's objects if the kconfig symbol's dependencies
+ * are met but only link the objects into the kernel, and therefore enable the
+ * feature, if and only if the kconfig symbol has been enabled.
+ *
+ * Not all users or build systems may want to opt-in to compile all objects
+ * following the 'build-all selective-link philosophy', as such the targets
+ * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
+ * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
+ * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
+ * ``obj-y`` and ``lib-y`` respectively.
+ *
+ * Example use::
+ *
+ *	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
+ */
+
+/**
+ * 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_START - get address of start of linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the start address of the linker table.
+ * This should give you the address of the first entry.
+ *
+ */
+#define LINKTABLE_START(name)	LINUX_SECTION_START(name)
+
+/**
+ * LINKTABLE_END - get address of end of the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the end address of the linker table.
+ * This will match the start address if the linker table
+ * is empty.
+ */
+#define LINKTABLE_END(name)	LINUX_SECTION_END(name)
+
+/**
+ * LINKTABLE_SIZE - get number of entries in the linker table
+ *
+ * @name: name of the linker table
+ *
+ * This gives you the number of entries in the linker table.
+ * Example usage:
+ *
+ *   unsigned int num_frobs = LINKTABLE_SIZE(frobnicator_fns);
+ */
+#define LINKTABLE_SIZE(name)					\
+	((LINKTABLE_END(name)) - (LINKTABLE_START(name)))
+
+/**
+ * LINKTABLE_EMPTY - check if linker table has no entries
+ *
+ * @name: name of linker table
+ *
+ * Returns true if the linker table is emtpy.
+ *
+ *   bool is_empty = LINKTABLE_EMPTY(frobnicator_fns);
+ */
+#define LINKTABLE_EMPTY(name)	(LINKTABLE_SIZE(name) = 0)
+
+/**
+ * LINKTABLE_ADDR_WITHIN - returns true if address is in the linker table
+ *
+ * @name: name of the linker table
+ * @addr: address to query for
+ *
+ * Returns true if the address is part of the linker table.
+ */
+#define LINKTABLE_ADDR_WITHIN(name, addr)				\
+	 (addr >= (unsigned long) LINKTABLE_START(name) &&		\
+	  addr < (unsigned long) LINKTABLE_END(name))
+
+/**
+ * LINKTABLE_ALIGNMENT - get the alignment of the linker table
+ *
+ * @name: name of linker table
+ *
+ * Gives you the alignment for the linker table.
+ */
+#define LINKTABLE_ALIGNMENT(name)	LINUX_SECTION_ALIGNMENT(name)
+
+/**
+ * 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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     weak,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".data..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(SECTION_TBL_RO_STR "..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.text..tbl." #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__(LINKTABLE_START(name)[0])			\
+	      __attribute__((used,					\
+			     __aligned__(LINKTABLE_ALIGNMENT(name)),	\
+			     section(".init.data..tbl." #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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_TEXT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};		\
+	LINKTABLE_RO(name, ~) LINKTABLE_END(name)[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_RO(type, name);				\
+	LINKTABLE_INIT_WEAK(name,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT(name, ~) LINKTABLE_END(name)[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,) LINKTABLE_START(name)[0] = {};	\
+	LINKTABLE_INIT_DATA(name, ~) LINKTABLE_END(name)[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 = LINKTABLE_START(tbl);				\
+	     pointer < LINKTABLE_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 < LINKTABLE_SIZE(tbl); i++)			\
+		(LINKTABLE_START(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 < LINKTABLE_SIZE(tbl); i++)		\
+		err = (LINKTABLE_START(tbl)[i]).func(args);		\
+	err;								\
+})
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_LINKER_TABLES_H */
diff --git a/tools/linker-tables/.gitignore b/tools/linker-tables/.gitignore
new file mode 100644
index 000000000000..8275b0c55385
--- /dev/null
+++ b/tools/linker-tables/.gitignore
@@ -0,0 +1,2 @@
+arch/x86/kernel/vmlinux.lds
+demo
diff --git a/tools/linker-tables/Makefile b/tools/linker-tables/Makefile
new file mode 100644
index 000000000000..9d4e6fb0d176
--- /dev/null
+++ b/tools/linker-tables/Makefile
@@ -0,0 +1,184 @@
+include ../scripts/Makefile.include
+
+all:
+
+include ../scripts/utilities.mak
+
+MAKEFLAGS += --no-print-directory
+
+unexport LC_ALL
+LC_COLLATE=C
+LC_NUMERIC=C
+export LC_COLLATE LC_NUMERIC
+
+ifeq ($(srctree),)
+	srctree := $(patsubst %/,%,$(dir $(shell pwd)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+#$(info Determined 'srctree' to be $(srctree))
+endif
+
+ifneq ($(objtree),)
+#$(info Determined 'objtree' to be $(objtree))
+endif
+
+ifneq ($(OUTPUT),)
+#$(info Determined 'OUTPUT' to be $(OUTPUT))
+# Adding $(OUTPUT) as a directory to look for source files,
+# because use generated output files as sources dependency
+# for flex/bison parsers.
+VPATH += $(OUTPUT)
+export VPATH
+endif
+
+export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK
+include $(srctree)/tools/build/Makefile.include
+
+ifeq ($(V),1)
+	Q+	NQ=@true
+else
+	Q=@
+	NQ=@echo
+endif
+
+MAKEFLAGS += -r
+
+define allow-override
+  $(if $(or $(findstring environment,$(origin $(1))),\
+            $(findstring command line,$(origin $(1)))),,\
+    $(eval $(1) = $(2)))
+endef
+
+# Allow setting CC and AR and LD, or setting CROSS_COMPILE as a prefix.
+$(call allow-override,CC,$(CROSS_COMPILE)gcc)
+$(call allow-override,AR,$(CROSS_COMPILE)ar)
+$(call allow-override,LD,$(CROSS_COMPILE)ld)
+
+LD += $(EXTRA_LDFLAGS)
+
+include $(srctree)/tools/scripts/Makefile.arch
+
+# Refer to README to learn how to support your architecture
+SUPPORTED_ARCHS = x86
+
+ifeq ($(filter $(ARCH),$(SUPPORTED_ARCHS)),)
+$(error Unsupported arch: $(ARCH))
+endif
+
+CFLAGS += -O2 -g
+CFLAGS += -std=gnu99 -Wall -Werror
+CFLAGS += -lpthread
+CFLAGS += -DCONFIG_KPROBES
+
+# We confine the includes used below to those we know are safe
+# for this type of hack.
+CFLAGS += -D__KERNEL__
+
+# CFLAGS += -DCONFIG_HAVE_ARCH_PS_CONST
+INCLUDES = \
+	   -I include/ \
+	   -I arch/$(ARCH)/include/ \
+	   -I ../include/ \
+	   -I ../arch/$(ARCH)/include/ \
+	   -I ../arch/$(ARCH)/include/generated/
+
+CFLAGS += $(INCLUDES)
+CFLAGS +=-Wl,-Tarch/$(ARCH)/kernel/vmlinux.lds
+
+HEADERS = \
+	  ../../include/asm-generic/section-core.h \
+	  ../../include/asm-generic/ranges.h \
+	  ../../include/asm-generic/tables.h \
+	  ../../include/linux/sections.h \
+	  ../../include/linux/ranges.h \
+	  ../../include/linux/tables.h
+
+__check_headers: $(HEADERS)
+	@$(foreach h, $(HEADERS), \
+		(test -f $(h) && ( \
+			(diff -B $(subst ../,../,$(h)) $(h) >/dev/null) \
+			|| echo "Warning: $(subst ../../,tools/,$(h)) differs from kernel" >&2 ) || true);)
+
+$(OUTPUT)arch/$(ARCH)/kernel/vmlinux.lds: arch/$(ARCH)/kernel/vmlinux.lds.S
+	$(NQ) '  LD  ' $@
+	$(Q)$(CC) $(CFLAGS) $(INCLUDES) -E -P \
+		-D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $<
+
+# Note, we use obj-y as a convenience factor, the cmd build
+# stuff doesn't allow this magic, it resolves our depds but
+# we still need to provide a series of targets for our objects.
+# We stick to the convenient shorthand we're used to in the
+# kernel. The final object resolution build stuff is handled
+# by tool_target_obj and its caller below. This also enables
+# OUTPUT=foo-path support so you can build externally.
+obj-y += \
+	arch/$(ARCH)/kernel/head64.o \
+	arch/$(ARCH)/mm/init.o \
+	kernel/locking/mutex.o \
+	kernel/locking/spinlock.o \
+	kernel/workqueue.o \
+	kernel/main.o \
+	pci.o \
+	lib/string.o \
+	pci-quirks.o \
+	drivers/acme.o \
+	drivers/synth/main.o \
+	drivers/synth/common.o \
+	drivers/synth/or.s \
+	main.o
+
+ifeq ($(ARCH),x86)
+obj-y += \
+	arch/$(ARCH)/kernel/alternative.o \
+	arch/$(ARCH)/kernel/init.o \
+	arch/$(ARCH)/kernel/kprobes.o \
+	arch/$(ARCH)/kernel/kasan.o \
+	arch/$(ARCH)/kernel/beta.o \
+	arch/$(ARCH)/kernel/alpha.o \
+	arch/$(ARCH)/xen/init.o	\
+	drivers/xen-driver.o
+endif
+
+obj-y-out = $(patsubst %,$(OUTPUT)%,$(obj-y))
+
+__build-dir = $(subst $(OUTPUT),,$(dir $1))
+build-dir   = $(if $(__build-dir),$(__build-dir),.)
+
+build := -f $(srctree)/tools/build/Makefile.build dir=$(build-dir)
+
+define tool_target_obj
+$(1): $(subst .s,.S,$(subst .o,.c,$(patsubst $(OUTPUT)%,%,$(1))))
+	$(Q)$(MAKE) $(build) obj=$(1)
+endef
+
+$(foreach tool_obj, $(obj-y-out), \
+	$(eval $(call tool_target_obj, $(tool_obj))))
+
+$(OUTPUT)demo: $(obj-y-out)
+	$(NQ) '  CC  ' $@
+	$(Q)$(CC) $(obj-y-out) -o $@ $(CPPFLAGS) $(CFLAGS)
+
+CHECK_HEADERS := __check_headers
+PHONY += $(CHECK_HEADERS)
+
+CMD_TARGETS = $(OUTPUT)arch/$(ARCH)/kernel/vmlinux.lds $(OUTPUT)demo
+TARGETS = $(CMD_TARGETS)
+
+all: $(CHECK_HEADERS) all_cmd
+
+all_cmd: $(CMD_TARGETS)
+
+ifeq ($(OUTPUT),)
+clean_dir = ./
+else
+clean_dir = $(OUTPUT)
+endif
+
+clean::
+	$(NQ)  '  CLEAN deps'
+	$(Q)find $(clean_dir) -name \*.o \
+		-o -name \*.s \
+		-o -name \*.o.d \
+		-o -name \*.o.cmd | xargs rm -f
+	$(NQ)  '  CLEAN targets'
+	$(Q)$(foreach f, $(CMD_TARGETS), rm -f $(f);)
diff --git a/tools/linker-tables/README b/tools/linker-tables/README
new file mode 100644
index 000000000000..729241f9e4c4
--- /dev/null
+++ b/tools/linker-tables/README
@@ -0,0 +1,114 @@
+Linux linker table userspace sandbox
+==================
+
+This is a userspace sandbox to allow easy experimentation and
+test extensions with linker tables. It tries to mimic the Linux
+kernel development flow as much as possible, it however relies
+on and uses libc and is nothing but a simple stupid userspace
+application demo.
+
+You can use the sandbox to modify the kernel's linker table
+solution or add use it in creative ways without having to run
+qemu with a real kernel or user mode linux. You can simply try
+to extend this sandbox as you would for a regular userspace
+application.
+
+History
+===+
+This was hacked on first in an external repository, that tree has
+the full set of history of how this work came about. Refer to that
+tree for more details if you are interested in the logic used for
+a lot of decisions made for linker tables:
+
+https://git.kernel.org/cgit/linux/kernel/git/mcgrof/linker-tables.git/
+
+This tree is discontinued now in favor of an upstream solution which
+is kept in sync with the kernel.
+
+Compile
+===+
+Run:
+	make
+
+Clean:
+	make clean
+
+If you need to get object files outside of the source tree:
+
+	make OUTPUT=/tmp/path/
+	make OUTPUT=/tmp/path/ clean
+
+Supported architectures
+===========+
+x86_64
+
+Currently only x86_64 is supported for the demo. It should be
+relatively easy to add more. To add a new architecture you need
+a toolchain available with libc. You then need to generate a
+respective base template custom linker script for userspace
+as is provided on x86 in arch/x86/kernel/vmlinux.lds.S.
+
+A respective architecture tools/arch/$(ARCH)/include/* file for
+each section-core.h, ranges.h, tables.h will need to be provided
+as well. If your architecture's file is generated copy the generated
+file over.
+
+x86 Simulated boots
+=========+
+This programs simulates boot on both bare metal and with the
+Xen PV entry on x86.
+
+Emulate bare metal boot:
+
+./demo
+
+Emulate Xen boot (x86):
+
+./demo -x
+
+Testing new features
+==========
+
+A copy of each kernel header file is maintained in tools/include/,
+as well as a respective generated asm file for each sandbox supported
+architecture. This sandbox has a built in checker for when these files
+get out of sync.
+
+If testing new extensions on the files:
+
+  o section-core
+  o ranges.h
+  o tables.h
+
+You'll want to copy them into tools as well. If you are working on
+using these files you can work within the current directory's namespace,
+including its own set of header files, so tools/linker-tables/include/ and
+each respective tools/linker-tables/arch/$(ARCH)/include/asm/.
+
+Features evaluation
+=========+
+This lists features currently being evaluated in the sandbox, not yet
+present upstream. These make use of the existing set of header files
+without modification.
+
+ o Demo use of initialization on for x86, refer to arch/x86/kernel/init.c
+
+ o Demo use of porting the kernel's init call levels to linker tables, refer
+   to the init_calls linker table use on kernel/main.c
+
+ o Demo use of an asm-generic architecture init family, which could potentially
+   be used to help share initialization sequences on simple architectures.
+   Refer to include/asm-generic/arch_init_fn.h
+
+ o Building synthetic routines with the option to provide enhancements
+   per architecture in asm, refer to drivers/synth/or.S and its use on
+   synth_init_or().
+
+ o User of linker tables for alternatives with consts - refer to
+   use of the ps_set_const_table linker table and its use in
+   arch/x86/kernel/alternative.c
diff --git a/tools/linker-tables/arch/x86/include/asm/asm.h b/tools/linker-tables/arch/x86/include/asm/asm.h
new file mode 100644
index 000000000000..155a52920dfb
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/asm.h
@@ -0,0 +1,17 @@
+#ifndef _ASM_X86_ASM_H
+
+#ifdef __ASSEMBLY__
+# define __ASM_FORM(x)	x
+# define __ASM_FORM_RAW(x)     x
+# define __ASM_FORM_COMMA(x) x,
+#else
+# define __ASM_FORM(x)	" " #x " "
+# define __ASM_FORM_RAW(x)     #x
+# define __ASM_FORM_COMMA(x) " " #x ","
+#endif
+
+# define __ASM_SEL(a,b) __ASM_FORM(b)
+# define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(b)
+#define _ASM_PTR	__ASM_SEL(.long, .quad)
+
+#endif /* _ASM_X86_ASM_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/boot.h b/tools/linker-tables/arch/x86/include/asm/boot.h
new file mode 100644
index 000000000000..af91b94ad5a6
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/boot.h
@@ -0,0 +1 @@
+extern struct boot_params boot_params;
diff --git a/tools/linker-tables/arch/x86/include/asm/bootparam.h b/tools/linker-tables/arch/x86/include/asm/bootparam.h
new file mode 100644
index 000000000000..a7ef34216f7f
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/bootparam.h
@@ -0,0 +1,32 @@
+#ifndef __BOOTPARAM_H
+#define __BOOTPARAM_H
+
+#include <linux/types.h>
+
+struct setup_header {
+	__u32 hardware_subarch;
+} __attribute__((packed));
+
+struct boot_params {
+	struct setup_header hdr;
+} __attribute__((packed));
+
+enum {
+	X86_SUBARCH_PC = 0,
+	X86_SUBARCH_LGUEST,
+	X86_SUBARCH_XEN,
+	X86_SUBARCH_INTEL_MID,
+	X86_SUBARCH_CE4100,
+	X86_NR_SUBARCHS,
+};
+
+#define X86_SUBARCH_ALL_SUBARCHS 	\
+	(				\
+	BIT(X86_SUBARCH_PC) |		\
+	BIT(X86_SUBARCH_LGUEST) |	\
+	BIT(X86_SUBARCH_XEN) |		\
+	BIT(X86_SUBARCH_INTEL_MID) |	\
+	BIT(X86_SUBARCH_CE4100)		\
+	)
+
+#endif /* __BOOTPARAM_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/kprobes.h b/tools/linker-tables/arch/x86/include/asm/kprobes.h
new file mode 100644
index 000000000000..f702fc359efe
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/kprobes.h
@@ -0,0 +1,7 @@
+#ifndef _SANDBOX_ASM_X86_KPROBES_H
+#define _SANDBOX_ASM_X86_KPROBES_H
+
+/* This is all we need for the demo */
+#include <asm-generic/kprobes.h>
+
+#endif /* _SANDBOX_ASM_X86_KPROBES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/ps_const.h b/tools/linker-tables/arch/x86/include/asm/ps_const.h
new file mode 100644
index 000000000000..3847f03fca92
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/ps_const.h
@@ -0,0 +1,23 @@
+#ifndef __X86_PS_CONST
+#define __X86_PS_CONST
+
+#include <linux/stringify.h>
+#include <linux/tables.h>
+#include <asm/asm.h>
+
+#define ps_shr(in, _func)						\
+({									\
+	 __typeof__(in) _count;						\
+									\
+	asm volatile(							\
+		"shr %P[_in],%[_count]\n"				\
+		"1:\n"							\
+		push_section_tbl(.init.data, ps_set_const_table, 01,)	\
+		_ASM_PTR "1b-1, %P2, %P3\n"				\
+		".popsection\n"						\
+		: [_count] "=g" (_count)				\
+		: [_in] "i" (in), "i" (SET_CONST_U8), "i" (_func));	\
+	(_count);							\
+})
+
+#endif /* __X86_PS_CONST */
diff --git a/tools/linker-tables/arch/x86/include/asm/ranges.h b/tools/linker-tables/arch/x86/include/asm/ranges.h
new file mode 100644
index 000000000000..823789d2b010
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/ranges.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_RANGES_H
+#define _ASM_X86_RANGES_H
+
+#include <asm-generic/ranges.h>
+
+#endif  /* _ASM_X86_RANGES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/section-core.h b/tools/linker-tables/arch/x86/include/asm/section-core.h
new file mode 100644
index 000000000000..06be2b1c424f
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/section-core.h
@@ -0,0 +1 @@
+#include <asm-generic/section-core.h>
diff --git a/tools/linker-tables/arch/x86/include/asm/setup.h b/tools/linker-tables/arch/x86/include/asm/setup.h
new file mode 100644
index 000000000000..366c36bd2910
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/setup.h
@@ -0,0 +1,6 @@
+#ifndef __LINUX_X86_USER_SETUP_H
+#define __LINUX_X86_USER_SETUP_H
+
+/* I'm lazy */
+
+#endif /* __LINUX_X86_USER_SETUP_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/tables.h b/tools/linker-tables/arch/x86/include/asm/tables.h
new file mode 100644
index 000000000000..797df3407ee1
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/tables.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_TABLES_H
+#define _ASM_X86_TABLES_H
+
+#include <asm-generic/tables.h>
+
+#endif  /* _ASM_X86_RANGES_H */
diff --git a/tools/linker-tables/arch/x86/include/asm/x86.h b/tools/linker-tables/arch/x86/include/asm/x86.h
new file mode 100644
index 000000000000..680c1141e0de
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/x86.h
@@ -0,0 +1,4 @@
+int startup_64(void);
+int x86_64_start_reservations(void);
+void setup_arch(void);
+void late_init(void);
diff --git a/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h b/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
new file mode 100644
index 000000000000..afece8ce6dd4
--- /dev/null
+++ b/tools/linker-tables/arch/x86/include/asm/x86_init_fn.h
@@ -0,0 +1,169 @@
+#ifndef __X86_INIT_TABLES_H
+#define __X86_INIT_TABLES_H
+
+#include <linux/types.h>
+#include <linux/tables.h>
+
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <asm/bootparam.h>
+
+/**
+ * struct x86_init_fn - x86 generic kernel init call
+ *
+ * Linux x86 features vary in complexity, features may require work done at
+ * different levels of the full x86 init sequence. Today there are also two
+ * different possible entry points for Linux on x86, one for bare metal, KVM
+ * and Xen HVM, and another for Xen PV guests / dom0.  Assuming a bootloader
+ * has set up 64-bit mode, roughly the x86 init sequence follows this path:
+ *
+ * Bare metal, KVM, Xen HVM                      Xen PV / dom0
+ *       startup_64()                             startup_xen()
+ *              \                                     /
+ *      x86_64_start_kernel()                 xen_start_kernel()
+ *                           \               /
+ *                      x86_64_start_reservations()
+ *                                   |
+ *                              start_kernel()
+ *                              [   ...        ]
+ *                              [ setup_arch() ]
+ *                              [   ...        ]
+ *                                  init
+ *
+ * x86_64_start_kernel() and xen_start_kernel() are the respective first C code
+ * entry starting points. The different entry points exist to enable Xen to
+ * skip a lot of hardware setup already done and managed on behalf of the
+ * hypervisor, we refer to this as "paravirtualization yielding". The different
+ * levels of init calls on the x86 init sequence exist to account for these
+ * slight differences and requirements. These different entry points also share
+ * a common entry x86 specific path, x86_64_start_reservations().
+ *
+ * A generic x86 feature can have different initialization calls, one on each
+ * of the different main x86 init sequences, but must also address both entry
+ * points in order to work properly across the board on all supported x86
+ * subarchitectures. Since x86 features can also have dependencies on other
+ * setup code or features, x86 features can at times be subordinate to other
+ * x86 features, or conditions. struct x86_init_fn enables feature developers
+ * to annotate dependency relationships to ensure subsequent init calls only
+ * run once a subordinate's dependencies have run. When needed custom
+ * dependency requirements can also be spelled out through a custom dependency
+ * checker. In order to account for the dual entry point nature of x86-64 Linux
+ * for "paravirtualization yielding" and to make annotations for support for
+ * these explicit each struct x86_init_fn must specify supported
+ * subarchitectures. The earliest x86-64 code can read the subarchitecture
+ * though is after load_idt(), as such the earliest we can currently rely on
+ * subarchitecture for semantics and a common init sequences is on the shared
+ * common x86_64_start_reservations().  Each struct x86_init_fn is associated
+ * with a specific special link order number which has been careflly thought
+ * out by x86 maintainers. You should pick a link order level associated with
+ * the specific directory your code lies in, a respective macro is used to
+ * build association to a link oder with a routine, you should use one of the
+ * provided x86_init_*() macros. You should not use __x86_init() directly.
+ *
+ * x86_init_fn enables strong semantics and dependencies to be defined and
+ * implemented on the full x86 initialization sequence.
+ *
+ * @supp_hardware_subarch: must be set, it represents the bitmask of supported
+ *	subarchitectures.  We require each struct x86_init_fn to have this set
+ *	to require developer considerations for each supported x86
+ *	subarchitecture and to build strong annotations of different possible
+ *	run time states particularly in consideration for the two main
+ *	different entry points for x86 Linux, to account for paravirtualization
+ *	yielding.
+ *
+ *	The subarchitecture is read by the kernel at early boot from the
+ *	struct boot_params hardware_subarch. Support for the subarchitecture
+ *	exists as of x86 boot protocol 2.07. The bootloader would have set up
+ *	the respective hardware_subarch on the boot sector as per
+ *	Documentation/x86/boot.txt.
+ *
+ *	What x86 entry point is used is determined at run time by the
+ *	bootloader. Linux pv_ops was designed to help enable to build one Linux
+ *	binary to support bare metal and different hypervisors.  pv_ops setup
+ *	code however is limited in that all pv_ops setup code is run late in
+ *	the x86 init sequence, during setup_arch(). In fact cpu_has_hypervisor
+ *	only works after early_cpu_init() during setup_arch(). If an x86
+ *	feature requires an earlier determination of what hypervisor was used,
+ *	or if it needs to annotate only support for certain hypervisors, the
+ *	x86 hardware_subarch should be set by the bootloader and
+ *	@supp_hardware_subarch set by the x86 feature. Using hardware_subarch
+ *	enables x86 features to fill the semantic gap between the Linux x86
+ *	entry point used and what pv_ops has to offer through a hypervisor
+ *	agnostic mechanism.
+ *
+ *	Each supported subarchitecture is set using the respective
+ *	X86_SUBARCH_* as a bit in the bitmask. For instance if a feature
+ *	is supported on PC and Xen subarchitectures only you would set this
+ *	bitmask to:
+ *
+ *		BIT(X86_SUBARCH_PC) |
+ *		BIT(X86_SUBARCH_XEN);
+ *
+ * @early_init: required, routine which will run in x86_64_start_reservations()
+ *	after we ensure boot_params.hdr.hardware_subarch is accessible and
+ *	properly set. Memory is not yet available. This the earliest we can
+ *	currently define a common shared callback since all callbacks need to
+ *	check for boot_params.hdr.hardware_subarch and this becomes accessible
+ *	on x86-64 until after load_idt().
+ */
+struct x86_init_fn {
+	__u32 supp_hardware_subarch;
+	void (*early_init)(void);
+};
+
+DECLARE_LINKTABLE(struct x86_init_fn, x86_init_fns);
+
+/* Init order levels, we can start at 0000 but reserve 0000-0999 for now */
+
+/*
+ * X86_INIT_ORDER_EARLY - early kernel init code
+ *
+ * This consists of the first parts of the Linux kernel executed.
+ */
+#define X86_INIT_ORDER_EARLY	1000
+
+/* X86_INIT_ORDER_PLATFORM - platform kernel code
+ *
+ * Code the kernel needs to initialize under arch/x86/platform/
+ * early in boot.
+ */
+#define X86_INIT_ORDER_PLATFORM	3000
+
+#define __x86_init(__level,						\
+		   __supp_hardware_subarch,				\
+		   __early_init)					\
+	static LINKTABLE_INIT_DATA(x86_init_fns, __level)		\
+	__x86_init_fn_##__early_init = {				\
+		.supp_hardware_subarch = __supp_hardware_subarch,	\
+		.early_init = __early_init,				\
+	};
+
+#define x86_init_early(__supp_hardware_subarch,				\
+		       __early_init)					\
+	__x86_init(X86_INIT_ORDER_EARLY, __supp_hardware_subarch,	\
+		   __early_init);
+
+#define x86_init_platform(__supp_hardware_subarch,			\
+		       __early_init)					\
+	__x86_init(__name, X86_INIT_ORDER_PLATFORM, __supp_hardware_subarch,\
+		   __early_init);
+
+#define x86_init_early_all(__early_init)				\
+	x86_init_early(X86_SUBARCH_ALL_SUBARCHS,			\
+		       __early_init);
+
+#define x86_init_early_pc(__early_init)					\
+	x86_init_early(BIT(X86_SUBARCH_PC),				\
+		       __early_init);
+
+#define x86_init_early_xen(__early_init)				\
+	x86_init_early(BIT(X86_SUBARCH_XEN),				\
+		       __early_init);
+/**
+ * x86_init_fn_early_init: call all early_init() callbacks
+ *
+ * This calls all early_init() callbacks on the x86_init_fns linker table.
+ */
+void x86_init_fn_early_init(void);
+
+#endif /* __X86_INIT_TABLES_H */
diff --git a/tools/linker-tables/arch/x86/kernel/alpha.c b/tools/linker-tables/arch/x86/kernel/alpha.c
new file mode 100644
index 000000000000..477227d817a3
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/alpha.c
@@ -0,0 +1,10 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_alpha(void)
+{
+	pr_info("Initializing alpha ...\n");
+	pr_info("Completed initializing alpha !\n");
+}
+
+x86_init_early_pc(early_init_alpha);
diff --git a/tools/linker-tables/arch/x86/kernel/alternative.c b/tools/linker-tables/arch/x86/kernel/alternative.c
new file mode 100644
index 000000000000..380c184172b3
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/alternative.c
@@ -0,0 +1,31 @@
+#include <asm/x86_init_fn.h>
+
+#include <linux/kernel.h>
+#include <linux/ps_const.h>
+
+void apply_alternatives_linker_tables(void)
+{
+	unsigned int num_consts = LINKTABLE_SIZE(ps_set_const_table);
+	struct ps_set_const *ps_const;
+
+	if (!num_consts)
+		return;
+
+	pr_debug("Number of init entries: %d\n", num_consts);
+
+	linktable_for_each(ps_const, ps_set_const_table) {
+		switch (ps_const->type) {
+		case SET_CONST_U8:
+			*ps_const->count = (__u8) ps_const->func();
+			break;
+		case SET_CONST_U16:
+			*ps_const->count = (__u16) ps_const->func();
+			break;
+		case SET_CONST_U32:
+			*ps_const->count = (__u16) ps_const->func();
+			break;
+		}
+	}
+}
+
+x86_init_early_pc(apply_alternatives_linker_tables);
diff --git a/tools/linker-tables/arch/x86/kernel/beta.c b/tools/linker-tables/arch/x86/kernel/beta.c
new file mode 100644
index 000000000000..6cbbb3144928
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/beta.c
@@ -0,0 +1,10 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_beta(void)
+{
+	pr_info("Initializing beta ...\n");
+	pr_info("Completed initializing beta !\n");
+}
+
+x86_init_early_pc(early_init_beta);
diff --git a/tools/linker-tables/arch/x86/kernel/head64.c b/tools/linker-tables/arch/x86/kernel/head64.c
new file mode 100644
index 000000000000..d14dcdfd0ea9
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/head64.c
@@ -0,0 +1,58 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+
+#include <asm/x86_init_fn.h>
+#include <asm/boot.h>
+#include <asm/bootparam.h>
+
+#include <linux/start_kernel.h>
+#include <linux/kasan.h>
+
+void x86_64_start_reservations(void)
+{
+	switch (boot_params.hdr.hardware_subarch) {
+	case X86_SUBARCH_PC:
+		pr_info("Booting bare metal\n");
+		break;
+	case X86_SUBARCH_LGUEST:
+		pr_info("Booting lguest not supported\n");
+		BUG();
+	case X86_SUBARCH_XEN:
+		pr_info("Booting a Xen guest\n");
+		break;
+	case X86_SUBARCH_INTEL_MID:
+		pr_info("Booting Intel MID not supported\n");
+		BUG();
+	case X86_SUBARCH_CE4100:
+		pr_info("Booting Intel CE4100 not supported\n");
+		BUG();
+	default:
+		pr_info("Booting sunsupported x86 hardware subarch\n");
+		BUG();
+	}
+
+	start_kernel();
+}
+
+static void x86_64_start_kernel(void)
+{
+	x86_init_fn_early_init();
+
+	x86_64_start_reservations();
+}
+
+void startup_64(void)
+{
+	pr_info("Initializing x86 bare metal world\n");
+	x86_64_start_kernel();
+}
+
+void setup_arch(void)
+{
+	/* TODO: x86_init_fn_setup_arch(); */
+}
+
+void late_init(void)
+{
+	/* TODO: x86_init_fn_late_init(); */
+}
diff --git a/tools/linker-tables/arch/x86/kernel/init.c b/tools/linker-tables/arch/x86/kernel/init.c
new file mode 100644
index 000000000000..1eed92d1acb2
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/init.c
@@ -0,0 +1,42 @@
+#define pr_fmt(fmt) "x86-init: " fmt
+
+#include <linux/bug.h>
+#include <linux/kernel.h>
+
+#include <asm/x86_init_fn.h>
+#include <asm/bootparam.h>
+#include <asm/boot.h>
+#include <asm/setup.h>
+
+DEFINE_LINKTABLE_INIT_DATA(struct x86_init_fn, x86_init_fns);
+
+static bool x86_init_fn_supports_subarch(struct x86_init_fn *fn)
+{
+	if (!fn->supp_hardware_subarch) {
+		//pr_err("Init sequence fails to declares any supported subarchs: %pF\n", fn->early_init);
+		WARN_ON(1);
+	}
+	if (BIT(boot_params.hdr.hardware_subarch) & fn->supp_hardware_subarch)
+		return true;
+	return false;
+}
+
+void __ref x86_init_fn_early_init(void)
+{
+	struct x86_init_fn *init_fn;
+	unsigned int num_inits = LINKTABLE_SIZE(x86_init_fns);
+
+	if (!num_inits)
+		return;
+
+	pr_debug("Number of init entries: %d\n", num_inits);
+
+	linktable_for_each(init_fn, x86_init_fns) {
+		if (!x86_init_fn_supports_subarch(init_fn))
+			continue;
+
+		//pr_debug("Running early init %pF ...\n", init_fn->early_init);
+		init_fn->early_init();
+		//pr_debug("Completed early init %pF\n", init_fn->early_init);
+	}
+}
diff --git a/tools/linker-tables/arch/x86/kernel/kasan.c b/tools/linker-tables/arch/x86/kernel/kasan.c
new file mode 100644
index 000000000000..a1e6a5b72c23
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/kasan.c
@@ -0,0 +1,11 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+void kasan_early_init(void)
+{
+	pr_info("Initializing kasan ...\n");
+	pr_info("Early init for Kasan...\n");
+	pr_info("Completed initializing kasan !\n");
+}
+
+x86_init_early_pc(kasan_early_init);
diff --git a/tools/linker-tables/arch/x86/kernel/kprobes.c b/tools/linker-tables/arch/x86/kernel/kprobes.c
new file mode 100644
index 000000000000..c4e42beae55b
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/kprobes.c
@@ -0,0 +1,51 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <linux/ranges.h>
+#include <linux/kprobes.h>
+
+DEFINE_SECTION_RANGE(kprobes, .text);
+
+void __kprobes test_kprobe_0001(void)
+{
+	pr_info("test_kprobe\n");
+}
+
+void test_kprobe_0002(void)
+{
+	pr_info("test_kprobe\n");
+}
+
+void test_kprobe_addr(const char *test, unsigned long addr, bool should_match)
+{
+	if (SECTION_RANGE_ADDR_WITHIN(kprobes, addr))
+		if (should_match)
+			pr_info("= OK: %s within range!\n", test);
+		else
+			pr_info("= FAIL: %s should not be in range...\n",
+				test);
+	else
+		if (should_match)
+			pr_info("= FAIL: %s should be in range...\n", test);
+		else
+			pr_info("= OK: %s not in range as expected!\n", test);
+}
+
+void early_init_kprobes(void)
+{
+	unsigned long addr;
+
+	pr_info("Initializing kprobes ...\n");
+
+	addr = (unsigned long) &test_kprobe_0001;
+
+	test_kprobe_addr("test_kprobe_0001", addr, true);
+
+	addr = (unsigned long) &test_kprobe_0002;
+
+	test_kprobe_addr("test_kprobe_0002", addr, false);
+
+	pr_info("Completed initializing kprobes !\n");
+}
+
+x86_init_early_all(early_init_kprobes);
diff --git a/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S b/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
new file mode 100644
index 000000000000..783735fb897a
--- /dev/null
+++ b/tools/linker-tables/arch/x86/kernel/vmlinux.lds.S
@@ -0,0 +1,277 @@
+/* Script for -z combreloc: combine and sort reloc sections */
+/* Copyright (C) 2014 Free Software Foundation, Inc.
+   Copying and distribution of this script, with or without modification,
+   are permitted in any medium without royalty provided the copyright
+   notice and this notice are preserved.  */
+
+#include <asm/section-core.h>
+#include <asm/ranges.h>
+#include <asm/tables.h>
+
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
+	      "elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(_start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
+  .interp         : { *(.interp) }
+  .note.gnu.build-id : { *(.note.gnu.build-id) }
+  .hash           : { *(.hash) }
+  .gnu.hash       : { *(.gnu.hash) }
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+  .rela.dyn       :
+    {
+      *(.rela.init)
+      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+      *(.rela.fini)
+      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+      *(.rela.ctors)
+      *(.rela.dtors)
+      *(.rela.got)
+      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+      *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
+      *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
+      *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
+      *(.rela.ifunc)
+    }
+  .rela.plt       :
+    {
+      *(.rela.plt)
+      PROVIDE_HIDDEN (__rela_iplt_start = .);
+      *(.rela.iplt)
+      PROVIDE_HIDDEN (__rela_iplt_end = .);
+    }
+  .init           :
+  {
+    KEEP (*(SORT_NONE(.init)))
+  }
+  .plt            : { *(.plt) *(.iplt) }
+  .plt.bnd        : { *(.plt.bnd) }
+  .text           :
+  {
+    *(.text.unlikely .text.*_unlikely .text.unlikely.*)
+    *(.text.exit .text.exit.*)
+    *(.text.startup .text.startup.*)
+    *(.text.hot .text.hot.*)
+
+    *(SORT(.text..rng.*))
+    *(SORT(.text..tbl.*))
+
+    *(SORT(.init.text..rng.*))
+    *(SORT(.init.text..tbl.*))
+
+    *(SORT(.initcall..rng.*))
+    *(SORT(.initcall..tbl.*))
+
+    *(SORT(.exit.text..rng.*))
+    *(SORT(.exit.text..tbl.*))
+
+    *(SORT(.exitcall.exit..rng.*))
+    *(SORT(.exitcall.exit..tbl.*))
+
+    *(.text .stub .text.* .gnu.linkonce.t.*)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  }
+  .fini           :
+  {
+    KEEP (*(SORT_NONE(.fini)))
+  }
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+  .rodata         :
+  {
+	*(.rodata)
+
+	*(SORT(.rodata.*))
+
+	*(SORT(.rodata..rng.*))
+	*(SORT(.rodata..tbl.*))
+
+	*(SORT(.init.rodata..rng.*))
+	*(SORT(.init.rodata..tbl.*))
+
+	*(SORT(.ref.rodata..rng.*))
+	*(SORT(.ref.rodata..tbl.*))
+
+	*(.gnu.linkonce.r.*)
+  }
+  .rodata1        : { *(.rodata1) }
+  .eh_frame_hdr : { *(.eh_frame_hdr) }
+  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table
+  .gcc_except_table.*) }
+  /* These sections are generated by the Sun/Oracle C++ compiler.  */
+  .exception_ranges   : ONLY_IF_RO { *(.exception_ranges
+  .exception_ranges*) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  */
+  . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+  /* Exception handling  */
+  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
+  .exception_ranges   : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
+  /* Thread Local Storage sections  */
+  .tdata	  : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+  .preinit_array     :
+  {
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP (*(.preinit_array))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+  }
+  .init_array     :
+  {
+    PROVIDE_HIDDEN (__init_array_start = .);
+    KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
+    KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
+    PROVIDE_HIDDEN (__init_array_end = .);
+  }
+  .fini_array     :
+  {
+    PROVIDE_HIDDEN (__fini_array_start = .);
+    KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
+    KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
+    PROVIDE_HIDDEN (__fini_array_end = .);
+  }
+  .ctors          :
+  {
+    /* gcc uses crtbegin.o to find the start of
+       the constructors, so we make sure it is
+       first.  Because this is a wildcard, it
+       doesn't matter if the user does not
+       actually link against crtbegin.o; the
+       linker won't look for a file to match a
+       wildcard.  The wildcard also means that it
+       doesn't matter which directory crtbegin.o
+       is in.  */
+    KEEP (*crtbegin.o(.ctors))
+    KEEP (*crtbegin?.o(.ctors))
+    /* We don't want to include the .ctor section from
+       the crtend.o file until after the sorted ctors.
+       The .ctor section from the crtend file contains the
+       end of ctors marker and it must be last */
+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+  .dtors          :
+  {
+    KEEP (*crtbegin.o(.dtors))
+    KEEP (*crtbegin?.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  .jcr            : { KEEP (*(.jcr)) }
+  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
+  .dynamic        : { *(.dynamic) }
+  .got            : { *(.got) *(.igot) }
+  . = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
+  .got.plt        : { *(.got.plt)  *(.igot.plt) }
+  .data           :
+  {
+    *(.data .data.* .gnu.linkonce.d.*)
+
+    *(SORT(.data..rng.*))
+    *(SORT(.data..tbl.*))
+
+    *(SORT(.init.data..rng.*))
+    *(SORT(.init.data..tbl.*))
+
+    *(SORT(.ref.rodata..rng.*))
+    *(SORT(.ref.rodata..tbl.*))
+
+    *(SORT(.exit.data..rng.*))
+    *(SORT(.exit.data..tbl.*))
+
+    SORT(CONSTRUCTORS)
+  }
+  .data1          : { *(.data1) }
+  _edata = .; PROVIDE (edata = .);
+  . = .;
+
+  __bss_start = .;
+  .bss            :
+  {
+   *(.dynbss)
+   *(.bss .bss.* .gnu.linkonce.b.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.
+      FIXME: Why do we need it? When there is no .bss section, we don't
+      pad the .data section.  */
+   . = ALIGN(. != 0 ? 64 / 8 : 1);
+  }
+  .lbss   :
+  {
+    *(.dynlbss)
+    *(.lbss .lbss.* .gnu.linkonce.lb.*)
+    *(LARGE_COMMON)
+  }
+  . = ALIGN(64 / 8);
+  . = SEGMENT_START("ldata-segment", .);
+  .lrodata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+  {
+    *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
+  }
+  .ldata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+  {
+    *(.ldata .ldata.* .gnu.linkonce.l.*)
+    . = ALIGN(. != 0 ? 64 / 8 : 1);
+  }
+  . = ALIGN(64 / 8);
+  _end = .; PROVIDE (end = .);
+  . = DATA_SEGMENT_END (.);
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line .debug_line.* .debug_line_end ) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+  /* DWARF 3 */
+  .debug_pubtypes 0 : { *(.debug_pubtypes) }
+  .debug_ranges   0 : { *(.debug_ranges) }
+  /* DWARF Extension.  */
+  .debug_macro    0 : { *(.debug_macro) }
+  .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
+}
diff --git a/tools/linker-tables/arch/x86/mm/init.c b/tools/linker-tables/arch/x86/mm/init.c
new file mode 100644
index 000000000000..33e5700e2864
--- /dev/null
+++ b/tools/linker-tables/arch/x86/mm/init.c
@@ -0,0 +1,11 @@
+#include <linux/kernel.h>
+#include <asm/x86_init_fn.h>
+
+static void early_init_memory(void)
+{
+	pr_info("Initializing memory ...\n");
+	sleep(1);
+	pr_info("Completed initializing memory !\n");
+}
+
+x86_init_early_all(early_init_memory);
diff --git a/tools/linker-tables/arch/x86/xen/init.c b/tools/linker-tables/arch/x86/xen/init.c
new file mode 100644
index 000000000000..40ad493daee8
--- /dev/null
+++ b/tools/linker-tables/arch/x86/xen/init.c
@@ -0,0 +1,13 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <asm/x86.h>
+
+void startup_xen(void)
+{
+	pr_info("Initializing Xen guest\n");
+
+	x86_init_fn_early_init();
+
+	x86_64_start_reservations();
+}
diff --git a/tools/linker-tables/drivers/acme.c b/tools/linker-tables/drivers/acme.c
new file mode 100644
index 000000000000..975e4b8bf48d
--- /dev/null
+++ b/tools/linker-tables/drivers/acme.c
@@ -0,0 +1,33 @@
+#define pr_fmt(fmt) "ACME: " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/workqueue.h>
+
+void *acme_todo(void *arg);
+static DECLARE_WORK(acme_work, acme_todo);
+
+void *acme_todo(void *arg)
+{
+	pr_info("Running scheduled work\n");
+	pthread_exit(NULL);
+}
+
+static int acme_init_driver(void)
+{
+	pr_info("Initializing ...\n");
+	sleep(2);
+	pr_info("Finished init ... !\n");
+
+	init_work(&acme_work);
+	schedule_work(&acme_work);
+
+	return 0;
+}
+module_init(acme_init_driver);
+
+static void acme_exit(void)
+{
+	cancel_work_sync(&acme_work);
+};
+module_exit(acme_exit);
diff --git a/tools/linker-tables/drivers/synth/common.c b/tools/linker-tables/drivers/synth/common.c
new file mode 100644
index 000000000000..b44d9fcc7a9b
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/common.c
@@ -0,0 +1,16 @@
+int demo_or_1(int arg)
+{
+	switch (arg) {
+	case 1:
+		return 0xDEA00000;
+	case 2:
+		return 0X000D0000;
+	default:
+		return arg * 2;
+	}
+}
+
+int demo_or_2(void)
+{
+	return 0x0000BEEF;
+}
diff --git a/tools/linker-tables/drivers/synth/common.h b/tools/linker-tables/drivers/synth/common.h
new file mode 100644
index 000000000000..92827004f532
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/common.h
@@ -0,0 +1,2 @@
+int demo_or_1(int arg);
+int demo_or_2(void);
diff --git a/tools/linker-tables/drivers/synth/main.c b/tools/linker-tables/drivers/synth/main.c
new file mode 100644
index 000000000000..b9c2f876afa0
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/main.c
@@ -0,0 +1,36 @@
+#define pr_fmt(fmt) "Synthetics: " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ps_const.h>
+
+#include "common.h"
+#include "synth.h"
+
+DEFINE_LINKTABLE_INIT_DATA(struct ps_set_const, ps_set_const_table);
+
+unsigned int get_demo_shr(void)
+{
+	return 16;
+}
+
+static int synth_init(void)
+{
+	int synth_or;
+	int val = 2;
+	const unsigned int reg =  ps_shr(0xDEADBEEF, get_demo_shr);
+
+	synth_or = synth_init_or(val);
+	pr_info("synth_init_or(%d) returns: 0x%08X\n", val, synth_or);
+
+	pr_info("ps_shr(0x%08X, get_demo_shr) returns: 0x%08X\n",
+		0xDEADBEEF, reg);
+
+	return 0;
+}
+module_init(synth_init);
+
+static void synth_exit(void)
+{
+}
+module_exit(synth_exit);
diff --git a/tools/linker-tables/drivers/synth/or.S b/tools/linker-tables/drivers/synth/or.S
new file mode 100644
index 000000000000..deb963fdae33
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/or.S
@@ -0,0 +1,39 @@
+#include <asm/ranges.h>
+
+	DEFINE_SECTION_RANGE(.text, synth_init_or)
+
+	push_section_rng_level(.text, synth_init_or, "01", )
+	/* err = 0; */
+	pushq %rbp
+	movq %rsp,%rbp
+	pushq %rbx
+	xorq %rbx,%rbx
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "99", )
+	/* return err; */
+	movq %rbx,%rax
+	popq %rbx
+	popq %rbp
+	retq
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "50", )
+	/* err |= demo_or_1(1); */
+	movl $1,%edi
+	call demo_or_1
+	orq %rax,%rbx
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "50", )
+	/* err |= demo_or_1(2); */
+	movl $2,%edi
+	call demo_or_1
+	orq %rax,%rbx
+	.popsection
+
+	push_section_rng_level(.text, synth_init_or, "50", )
+	/* err |= demo_or_2(); */
+	call demo_or_2
+	orq %rax,%rbx
+	.popsection
diff --git a/tools/linker-tables/drivers/synth/synth.h b/tools/linker-tables/drivers/synth/synth.h
new file mode 100644
index 000000000000..abbb9afac374
--- /dev/null
+++ b/tools/linker-tables/drivers/synth/synth.h
@@ -0,0 +1,2 @@
+/* Synthetic demos go here */
+int synth_init_or(int arg);
diff --git a/tools/linker-tables/drivers/xen-driver.c b/tools/linker-tables/drivers/xen-driver.c
new file mode 100644
index 000000000000..268166efd06c
--- /dev/null
+++ b/tools/linker-tables/drivers/xen-driver.c
@@ -0,0 +1,12 @@
+#include <asm/x86_init_fn.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <xen/xen.h>
+
+static void early_xen_init_driver(void)
+{
+	pr_info("Initializing xen driver\n");
+	sleep(2);
+}
+
+x86_init_early_xen(early_xen_init_driver);
diff --git a/tools/linker-tables/include/asm-generic/arch_init_fn.h b/tools/linker-tables/include/asm-generic/arch_init_fn.h
new file mode 100644
index 000000000000..2318cc22cbe8
--- /dev/null
+++ b/tools/linker-tables/include/asm-generic/arch_init_fn.h
@@ -0,0 +1,50 @@
+#ifndef __ARCH_INIT_TABLES_H
+#define __ARCH_INIT_TABLES_H
+
+#include <linux/types.h>
+#include <linux/tables.h>
+#include <linux/init.h>
+
+/**
+ * struct arch_init_fn - architecture-generic kernel init call
+ *
+ * Architectures must initialize a series of things prior to handing off
+ * control to the kernel. This structure can be used if the architecture is
+ * simple and it just needs a basic set of calls on its way up.
+ *
+ * @early_init: required, routine which will run in startup_64(). Memory is
+ *	not yet available.
+ */
+struct arch_init_fn {
+	void (*early_init)(void);
+};
+
+DECLARE_LINKTABLE(struct arch_init_fn, arch_init_fns);
+
+/* Init order levels, we can start at 0000 but reserve 0000-0999 for now */
+
+/*
+ * ARCH_INIT_ORDER_EARLY - early kernel init code
+ *
+ * This consists of the first parts of the Linux kernel executed.
+ */
+#define ARCH_INIT_ORDER_EARLY	1000
+
+#define __arch_init(__level,						\
+		    __early_init)					\
+	static LINKTABLE_INIT_DATA(arch_init_fns, __level)		\
+	__arch_init_fn_##__early_init = {				\
+		.early_init = __early_init,				\
+	}
+
+#define arch_init_early(__early_init)					\
+	__arch_init(ARCH_INIT_ORDER_EARLY, __early_init)
+
+/**
+ * arch_init_fn_early_init: call all early_init() callbacks
+ *
+ * This calls all early_init() callbacks on the arch_init_fns linker table.
+ */
+void arch_init_fn_early_init(void);
+
+#endif /* __ARCH_INIT_TABLES_H */
diff --git a/tools/linker-tables/include/asm-generic/kprobes.h b/tools/linker-tables/include/asm-generic/kprobes.h
new file mode 100644
index 000000000000..839d2eb464d3
--- /dev/null
+++ b/tools/linker-tables/include/asm-generic/kprobes.h
@@ -0,0 +1,26 @@
+#ifndef _SANDBOX_ASM_GENERIC_KPROBES_H
+#define _SANDBOX_ASM_GENERIC_KPROBES_H
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+#ifdef CONFIG_KPROBES
+#include <linux/tables.h>
+#include <asm/ranges.h>
+/*
+ * Blacklist ganerating macro. Specify functions which is not probed
+ * by using this macro.
+ */
+# define __NOKPROBE_SYMBOL(fname)				\
+static LINKTABLE_INIT_DATA(_kprobe_blacklist, all)		\
+	_kbl_addr_##fname = (unsigned long)fname;
+# define NOKPROBE_SYMBOL(fname)	__NOKPROBE_SYMBOL(fname)
+/* Use this to forbid a kprobes attach on very low level functions */
+# define __kprobes	__LINUX_RANGE(.text, kprobes)
+# define nokprobe_inline	__always_inline
+#else
+# define NOKPROBE_SYMBOL(fname)
+# define __kprobes
+# define nokprobe_inline	inline
+#endif
+#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
+
+#endif /* _SANDBOX_ASM_GENERIC_KPROBES_H */
diff --git a/tools/linker-tables/include/linux/bitops.h b/tools/linker-tables/include/linux/bitops.h
new file mode 100644
index 000000000000..2960e8089ebc
--- /dev/null
+++ b/tools/linker-tables/include/linux/bitops.h
@@ -0,0 +1,6 @@
+#ifndef _LINUX_BITOPS_H
+#define _LINUX_BITOPS_H
+
+#define BIT(nr)		(1UL << (nr))
+
+#endif /* _LINUX_BITOPS_H */
diff --git a/tools/linker-tables/include/linux/init.h b/tools/linker-tables/include/linux/init.h
new file mode 100644
index 000000000000..2691c3697f48
--- /dev/null
+++ b/tools/linker-tables/include/linux/init.h
@@ -0,0 +1,40 @@
+#ifndef _SANDBOX_LINUX_INIT_H
+#define _SANDBOX_LINUX_INIT_H
+
+#include_next <linux/init.h>
+#include <linux/types.h>
+#include <linux/sections.h>
+
+#define __init	__section(.init.text)
+#define __exit	__section(.exit.text)
+
+#ifndef __ASSEMBLY__
+#include <linux/tables.h>
+typedef int (*initcall_t)(void);
+typedef void (*exitcall_t)(void);
+
+DECLARE_LINKTABLE(initcall_t, init_calls);
+DECLARE_LINKTABLE(exitcall_t, exit_calls);
+
+#define __define_initcall(fn, id)					\
+	static LINKTABLE_INIT_DATA(init_calls, id)			\
+	__initcall_##fn##id = fn
+
+#define pure_initcall(fn)			__define_initcall(fn, 0)
+#define core_initcall(fn)			__define_initcall(fn, 1)
+#define postcore_initcall(fn)			__define_initcall(fn, 2)
+#define arch_initcall(fn)			__define_initcall(fn, 3)
+#define subsys_initcall(fn)			__define_initcall(fn, 4)
+#define fs_initcall(fn)				__define_initcall(fn, 5)
+#define device_initcall(fn)			__define_initcall(fn, 6)
+#define late_initcall(fn)			__define_initcall(fn, 7)
+
+#define __initcall(fn)				device_initcall(fn)
+
+#define __exitcall(fn)							\
+	static LINKTABLE_INIT_DATA(exit_calls, any)			\
+	__exitcall_##fn = fn;
+
+#endif
+
+#endif /* _SANDBOX_LINUX_INIT_H */
diff --git a/tools/linker-tables/include/linux/kasan.h b/tools/linker-tables/include/linux/kasan.h
new file mode 100644
index 000000000000..41791187854e
--- /dev/null
+++ b/tools/linker-tables/include/linux/kasan.h
@@ -0,0 +1,5 @@
+#include <linux/types.h>
+
+void kasan_early_init(void);
+int kasan_init(void);
+bool is_kasan_setup(void);
diff --git a/tools/linker-tables/include/linux/kernel.h b/tools/linker-tables/include/linux/kernel.h
new file mode 100644
index 000000000000..e2857c0b5b11
--- /dev/null
+++ b/tools/linker-tables/include/linux/kernel.h
@@ -0,0 +1,2 @@
+#include_next <linux/kernel.h>
+#include <linux/printk.h>
diff --git a/tools/linker-tables/include/linux/kprobes.h b/tools/linker-tables/include/linux/kprobes.h
new file mode 100644
index 000000000000..ecd5a0a69ae6
--- /dev/null
+++ b/tools/linker-tables/include/linux/kprobes.h
@@ -0,0 +1,11 @@
+#ifndef _SANDBOX_LINUX_KPROBES_H
+#define _SANDBOX_LINUX_KPROBES_H
+
+#include <asm/kprobes.h>
+#include <linux/ranges.h>
+
+#ifdef CONFIG_KPROBES
+DECLARE_SECTION_RANGE(kprobes);
+#endif
+
+#endif /* _SANDBOX_LINUX_KPROBES_H */
diff --git a/tools/linker-tables/include/linux/module.h b/tools/linker-tables/include/linux/module.h
new file mode 100644
index 000000000000..b59e55f3f04e
--- /dev/null
+++ b/tools/linker-tables/include/linux/module.h
@@ -0,0 +1,14 @@
+#ifndef _LINUX_MODULE_H
+#define _LINUX_MODULE_H
+
+#include <linux/init.h>
+
+#define module_init(x)  __initcall(x);
+#define module_exit(x)  __exitcall(x);
+
+struct module {
+	int (*init)(void);
+	void (*exit)(void);
+};
+
+#endif /* _LINUX_MODULE_H */
diff --git a/tools/linker-tables/include/linux/mutex.h b/tools/linker-tables/include/linux/mutex.h
new file mode 100644
index 000000000000..a74f951ceb42
--- /dev/null
+++ b/tools/linker-tables/include/linux/mutex.h
@@ -0,0 +1,17 @@
+#ifndef __LINUX_MUTEX_H
+#define __LINUX_MUTEX_H
+
+#include <sys/types.h>
+#include <linux/sched.h>
+#include <pthread.h>
+
+struct mutex {
+	pthread_mutex_t lock;
+};
+
+void mutex_init(struct mutex *lock);
+void mutex_destroy(struct mutex *lock);
+void mutex_lock(struct mutex *lock);
+void mutex_unlock(struct mutex *lock);
+
+#endif /* __LINUX_MUTEX_H */
diff --git a/tools/linker-tables/include/linux/pci.h b/tools/linker-tables/include/linux/pci.h
new file mode 100644
index 000000000000..8518c46631f7
--- /dev/null
+++ b/tools/linker-tables/include/linux/pci.h
@@ -0,0 +1,7 @@
+#include <linux/types.h>
+
+struct pci_fixup {
+	void (*hook)(void);
+};
+
+bool detect_pci(void);
diff --git a/tools/linker-tables/include/linux/printk.h b/tools/linker-tables/include/linux/printk.h
new file mode 100644
index 000000000000..dc137d3421e8
--- /dev/null
+++ b/tools/linker-tables/include/linux/printk.h
@@ -0,0 +1,26 @@
+#ifndef _SANDBOX_KERNEL_PRINTK
+#define _SANDBOX_KERNEL_PRINTK
+
+#ifdef __KERNEL__
+
+#include <stdio.h>
+
+#ifndef pr_fmt
+#define pr_fmt(fmt)	fmt
+#endif
+
+#ifndef pr_info
+#define pr_info(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
+#ifndef pr_err
+#define pr_err(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
+#ifndef pr_debug
+#define pr_debug(fmt, ...)	printf(pr_fmt(fmt), ##__VA_ARGS__)
+#endif
+
+#endif /* __KERNEL__ */
+
+#endif /* _SANDBOX_KERNEL_PRINTK */
diff --git a/tools/linker-tables/include/linux/ps_const.h b/tools/linker-tables/include/linux/ps_const.h
new file mode 100644
index 000000000000..5eab3a124e00
--- /dev/null
+++ b/tools/linker-tables/include/linux/ps_const.h
@@ -0,0 +1,46 @@
+#ifndef __PS_CONST
+#define __PS_CONST
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/tables.h>
+
+/* Helpers for partially static settings */
+
+enum ps_static_type {
+	SET_CONST_U8 = 0,
+	SET_CONST_U16,
+	SET_CONST_U32,
+};
+
+struct ps_set_const {
+	unsigned int *count;
+	enum ps_static_type type;
+	unsigned int (*func)(void);
+};
+
+DECLARE_LINKTABLE(struct ps_set_const, ps_set_const_table);
+
+#ifdef CONFIG_HAVE_ARCH_PS_CONST
+#include <asm/ps_const.h>
+#endif
+
+/*
+ * ps_ stands for "partially static", so we "partialloy static shift right"
+ * You can optimize this for your architecture.
+ *
+ * ps_shr(unsigned int in, unsigned char (*func)(void))
+ */
+#ifndef ps_shr
+#define ps_shr(_in, _func)						\
+({									\
+	static unsigned int _count;					\
+	static LINKTABLE_INIT_DATA(ps_set_const_table, 01)		\
+		__ps_shr##__func =					\
+		{ &_count, SET_CONST_U8, (_func) };			\
+									\
+	(_in) >> _count;						\
+})
+#endif /* ps_shr */
+
+#endif /* __PS_CONST */
diff --git a/tools/linker-tables/include/linux/sched.h b/tools/linker-tables/include/linux/sched.h
new file mode 100644
index 000000000000..0fe3526e88bf
--- /dev/null
+++ b/tools/linker-tables/include/linux/sched.h
@@ -0,0 +1,9 @@
+#ifndef _LINUX_SCHED_H
+#define _LINUX_SCHED_H
+
+#include <linux/ranges.h>
+
+DECLARE_SECTION_RANGE(sched_text);
+#define __sched		__LINUX_RANGE(.text, sched_text)
+
+#endif /* _LINUX_SCHED_H */
diff --git a/tools/linker-tables/include/linux/spinlock.h b/tools/linker-tables/include/linux/spinlock.h
new file mode 100644
index 000000000000..e62bc3bc5e6a
--- /dev/null
+++ b/tools/linker-tables/include/linux/spinlock.h
@@ -0,0 +1,13 @@
+#ifndef __LINUX_SPINLOCK_H
+#define __LINUX_SPINLOCK_H
+
+#include <pthread.h>
+
+#define spinlock_t pthread_spinlock_t
+
+void spin_lock_init(spinlock_t *lock);
+void spin_lock_destroy(spinlock_t *lock);
+void spin_lock(spinlock_t *lock);
+void spin_unlock(spinlock_t *lock);
+
+#endif /* __LINUX_SPINLOCK_H */
diff --git a/tools/linker-tables/include/linux/start_kernel.h b/tools/linker-tables/include/linux/start_kernel.h
new file mode 100644
index 000000000000..5c2cb9a5cb0c
--- /dev/null
+++ b/tools/linker-tables/include/linux/start_kernel.h
@@ -0,0 +1 @@
+int start_kernel(void);
diff --git a/tools/linker-tables/include/linux/types.h b/tools/linker-tables/include/linux/types.h
new file mode 100644
index 000000000000..3fc87b2c84e2
--- /dev/null
+++ b/tools/linker-tables/include/linux/types.h
@@ -0,0 +1,13 @@
+#ifndef __LINUX_USER_TYPES_H
+#define __LINUX_USER_TYPES_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+typedef unsigned char __u8;
+typedef unsigned short __u16;
+typedef unsigned int __u32;
+
+#endif /* __LINUX_USER_TYPES_H */
diff --git a/tools/linker-tables/include/linux/workqueue.h b/tools/linker-tables/include/linux/workqueue.h
new file mode 100644
index 000000000000..69e1c6de5051
--- /dev/null
+++ b/tools/linker-tables/include/linux/workqueue.h
@@ -0,0 +1,51 @@
+#ifndef _LINUX_WORKQUEUE_H
+#define _LINUX_WORKQUEUE_H
+
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <pthread.h>
+
+struct work {
+	bool ready;
+
+	pthread_t thread;
+	struct mutex mutex;
+	pthread_cond_t cond;
+
+	void *arg;
+	void *(*work_cb)(void *arg);
+};
+
+#define DECLARE_WORK(_w, _w_cb) \
+struct work _w = { \
+	.work_cb = _w_cb, \
+	.arg = NULL, \
+};
+
+extern void *run_work(void *arg);
+
+static inline void init_work(struct work *w)
+{
+	w->ready = false;
+
+	mutex_init(&w->mutex);
+	pthread_cond_init(&w->cond, NULL);
+
+	pthread_create(&w->thread, NULL, run_work, (void *) w);
+
+	while (1) {
+		mutex_lock(&w->mutex);
+		if (w->ready) {
+			pthread_mutex_unlock(&w->mutex.lock);
+			break;
+		}
+		mutex_unlock(&w->mutex);
+	}
+}
+
+void schedule_work(struct work *w);
+void cancel_work_sync(struct work *w);
+void init_work(struct work *w);
+
+#endif /* _LINUX_WORKQUEUE_H */
diff --git a/tools/linker-tables/include/xen/xen.h b/tools/linker-tables/include/xen/xen.h
new file mode 100644
index 000000000000..782c799a0064
--- /dev/null
+++ b/tools/linker-tables/include/xen/xen.h
@@ -0,0 +1,4 @@
+#include <linux/types.h>
+
+bool booting_xen(void);
+int startup_xen(void);
diff --git a/tools/linker-tables/kernel/locking/mutex.c b/tools/linker-tables/kernel/locking/mutex.c
new file mode 100644
index 000000000000..950e4a18461e
--- /dev/null
+++ b/tools/linker-tables/kernel/locking/mutex.c
@@ -0,0 +1,28 @@
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+
+DEFINE_SECTION_RANGE(sched_text, .text);
+
+void __sched mutex_init(struct mutex *lock)
+{
+	int r;
+
+	r = pthread_mutex_init(&lock->lock, NULL);
+	if (r)
+		BUG_ON(r);
+}
+
+void __sched mutex_destroy(struct mutex *lock)
+{
+	pthread_mutex_destroy(&lock->lock);
+}
+
+void __sched mutex_lock(struct mutex *lock)
+{
+	pthread_mutex_lock(&lock->lock);
+}
+
+void __sched mutex_unlock(struct mutex *lock)
+{
+	pthread_mutex_unlock(&lock->lock);
+}
diff --git a/tools/linker-tables/kernel/locking/spinlock.c b/tools/linker-tables/kernel/locking/spinlock.c
new file mode 100644
index 000000000000..5be2bc7cdece
--- /dev/null
+++ b/tools/linker-tables/kernel/locking/spinlock.c
@@ -0,0 +1,26 @@
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+
+void spin_lock_init(spinlock_t *lock)
+{
+	int r;
+
+	r = pthread_spin_init(lock, PTHREAD_PROCESS_SHARED);
+	if (r)
+		BUG_ON(r);
+}
+
+void spin_lock_destroy(spinlock_t *lock)
+{
+	pthread_spin_destroy(lock);
+}
+
+void spin_lock(spinlock_t *lock)
+{
+	pthread_spin_lock(lock);
+}
+
+void spin_unlock(spinlock_t *lock)
+{
+	pthread_spin_unlock(lock);
+}
diff --git a/tools/linker-tables/kernel/main.c b/tools/linker-tables/kernel/main.c
new file mode 100644
index 000000000000..ad7a19c038bf
--- /dev/null
+++ b/tools/linker-tables/kernel/main.c
@@ -0,0 +1,32 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/x86_init_fn.h>
+#include <asm/x86.h>
+
+DEFINE_LINKTABLE_INIT_DATA(initcall_t, init_calls);
+
+int do_one_initcall(initcall_t fn)
+{
+	int ret;
+
+	ret = fn();
+
+	return ret;
+}
+
+static void do_initcalls(void)
+{
+	initcall_t *fn;
+
+	 linktable_for_each(fn, init_calls)
+		 do_one_initcall(*fn);
+}
+
+void start_kernel(void)
+{
+	pr_info("Calling start_kernel()...\n");
+
+	setup_arch();
+	late_init();
+	do_initcalls();
+}
diff --git a/tools/linker-tables/kernel/workqueue.c b/tools/linker-tables/kernel/workqueue.c
new file mode 100644
index 000000000000..5ba73c7e7c8b
--- /dev/null
+++ b/tools/linker-tables/kernel/workqueue.c
@@ -0,0 +1,43 @@
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <linux/workqueue.h>
+#include <linux/kernel.h>
+
+void schedule_work(struct work *w)
+{
+	mutex_lock(&w->mutex);
+	pthread_cond_signal(&w->cond);
+	mutex_unlock(&w->mutex);
+}
+
+void cancel_work_sync(struct work *w)
+{
+	pthread_exit(NULL);
+}
+
+void *run_work(void *arg)
+{
+	struct work *w;
+	int r;
+
+	w = (struct work *) arg;
+
+	mutex_lock(&w->mutex);
+
+	while (true) {
+		if (!w->ready)
+			w->ready = true;
+		r = pthread_cond_wait(&w->cond, &w->mutex.lock);
+		if (r != 0) {
+			printf("(%s)\n", strerror(r));
+			BUG_ON(r);
+		}
+		w->work_cb(w->arg);
+	}
+
+	mutex_unlock(&w->mutex);
+
+	pthread_exit(NULL);
+}
diff --git a/tools/linker-tables/lib/string.c b/tools/linker-tables/lib/string.c
new file mode 100644
index 000000000000..95631c742f1d
--- /dev/null
+++ b/tools/linker-tables/lib/string.c
@@ -0,0 +1,26 @@
+/*
+ *  linux/lib/string.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  Licensed under GPLv2 - taken from linux-next next-20160803
+ */
+
+#include <linux/kernel.h>
+
+/**
+ * memset - Fill a region of memory with the given value
+ * @s: Pointer to the start of the area.
+ * @c: The byte to fill the area with
+ * @count: The size of the area.
+ *
+ * Do not use memset() to access IO space, use memset_io() instead.
+ */
+void *memset(void *s, int c, size_t count)
+{
+	char *xs = s;
+
+	while (count--)
+		*xs++ = c;
+	return s;
+}
diff --git a/tools/linker-tables/main.c b/tools/linker-tables/main.c
new file mode 100644
index 000000000000..c0b1f4c95112
--- /dev/null
+++ b/tools/linker-tables/main.c
@@ -0,0 +1,20 @@
+#include <linux/string.h>
+#include <xen/xen.h>
+#include <asm/x86.h>
+#include <asm/bootparam.h>
+
+struct boot_params boot_params __attribute__((aligned(16)));
+
+int main(int arg, char *argc[])
+{
+	memset(&boot_params, 0, sizeof(struct boot_params));
+
+	if (arg <= 1)
+		startup_64();
+	else {
+		boot_params.hdr.hardware_subarch = X86_SUBARCH_XEN;
+		startup_xen();
+	}
+
+	return 0;
+}
diff --git a/tools/linker-tables/pci-quirks.c b/tools/linker-tables/pci-quirks.c
new file mode 100644
index 000000000000..8aac79477eab
--- /dev/null
+++ b/tools/linker-tables/pci-quirks.c
@@ -0,0 +1,14 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <linux/pci.h>
+
+DEFINE_LINKTABLE_RO(struct pci_fixup, pci_fixup_early);
+
+static void foo_fixup(void)
+{
+	pr_info("foo_fixup\n");
+};
+
+LINKTABLE_RO(pci_fixup_early, 50) quirk_foo = {
+	.hook = foo_fixup,
+};
diff --git a/tools/linker-tables/pci.c b/tools/linker-tables/pci.c
new file mode 100644
index 000000000000..a452c0766800
--- /dev/null
+++ b/tools/linker-tables/pci.c
@@ -0,0 +1,30 @@
+#include <linux/kernel.h>
+#include <linux/tables.h>
+#include <asm/x86_init_fn.h>
+#include <asm/bootparam.h>
+#include <linux/pci.h>
+
+DECLARE_LINKTABLE(struct pci_fixup, pci_fixup_early);
+
+void early_init_pci(void)
+{
+
+	const struct pci_fixup *fixup;
+	unsigned int tbl_size = LINKTABLE_SIZE(pci_fixup_early);
+
+	pr_info("Initializing pci ...\n");
+
+	pr_info("PCI fixup size: %d\n", tbl_size);
+
+	sleep(1);
+	pr_info("Demo: Using linktable_for_each\n");
+	linktable_for_each(fixup, pci_fixup_early)
+		fixup->hook();
+
+	pr_info("Demo: Using linktable_run_all\n");
+	linktable_run_all(pci_fixup_early, hook,);
+
+	pr_info("Completed initializing pci !\n");
+}
+
+x86_init_early_all(early_init_pci);
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 480+ messages in thread

* Re: [PATCH v6 01/14] generic-sections: add section core helpers
  2017-01-09 14:58         ` Luis R. Rodriguez
                             ` (2 preceding siblings ...)
  (?)
@ 2017-01-16 14:46           ` Borislav Petkov
  -1 siblings, 0 replies; 480+ messages in thread
From: Borislav Petkov @ 2017-01-16 14:46 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, gregkh, rusty, gnomes, alan, dwmw2,
	arnd, ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="windows-1254", Size: 33888 bytes --]

On Mon, Jan 09, 2017 at 06:58:19AM -0800, Luis R. Rodriguez wrote:
> Linux makes extensive use of custom ELF header sections,
> documentation for these are well scatterred. Unify this

			  is

> documentation in a central place and provide helpers to
> build custom Linux sections.

This patch contains at least three logical changes and needs splitting:

* unify documentation
* adding helpers
* MAINTAINERS addition

Documentation and MAINTAINERS changes should go last in the patchset.

Accordingly, the huuge commit message below should be spread around
those three patches.

> 
> This also generalizes sections code to enable avoiding
> modifying the linker scripts when we want to add new
> custom Linux sections. In order to make this generally
> useful we need to ensure all architectures can make use of
> core section helpers but that they can also override should
> this be needed. Instead of relying on section.h this adds
> a sections-core.h since this will be targetted to be safe
> to be used on asm code, linker scripts and C code.
> 
> v5:
> 
> o Huge documentation revamp based on a careful review of the ELF
>   specifications. Includes documentation now also about usage of
>   two dots (..) when prefixing ELF program specific sections.
> 
> o Replace macros for sections names in favor of just using
>   the section names explicitly in the linker script. This is
>   perhaps more work to grep but this is what folks seem to
>   currently prefer.
> 
> o Fix .text and .rodata documentation to explain memory protection
>   strategies which architectures can embrace upon initialization
>   (documents CONFIG_DEBUG_RODATA and mark_rodata_ro())
> 
> o Skip the 'Linux section ordering' documentation section, we'll instead
>   add this on subsequent patch which will expand on it considerably
> 
> o Dropped tree on MAINTAINERS -- as per discussions with Arnd, hpa and
>   Josh, its easier to just let changes for sections go in through the
>   respective tree that needs the changes.
> 
> o Fix typos on documentation
> 
> o Dropped SECTION_ALL(), __SECTION_CORE(), SECTION_CORE_ALL() macros
>   since we are favoring using explicit section names. These are
>   useless if we are being explicit.
> 
> o Drop LINUX_SECTION_SIZE(), LINUX_SECTION_EMPTY() in favor of having
>   section ranges and linker tables define their own, to avoid confusion
>   and make code more readable.
> 
> o Add __define_initcall() documentation and a small section describing
>   our current initcall levels. This should help also clarify what was
>   meant about keeping backward compatiblity.
> 
> v4:
> 
> o Port to shiny new sphinx documentation format

This looks like a 4th patch ontop of the unifying documentation one.

> 
> o fix a unicore32 build, turns out this actually fixes unicore32
>   defconfig builds which were failing for a long while. unicore32
>   does not seem to grok well the type passed on a section declaration,
>   this ignores it.
> 
> o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
>   this was causing final linker issues with blackfin -- this is
>   a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
>   being metatag. metatag is not supported on 0-day so I cannot confirm
>   compilation there.

...

> +++ b/Documentation/sections/background.rst
> @@ -0,0 +1,105 @@
> +===========
> +ELF section background
> +===========
> +
> +About
> +==> +
> +The purpose of this chapter is to help those not familiar with ELF to brush up
> +the latest ELF specifications in order to help understand how Linux uses and
> +defines its own ELF sections.
> +
> +Standardized ELF
> +========
> +
> +The first publication documenting ELF was UNIX System Laboratories' (USL)
> +*System V Release 4 Application Binary Interface* (`SRV4 ABI`_) specification.
> +Originally ELF was only a small part of the SRV4 ABI, with time however new
> +specifications only put focus on ELF, such was the case of the *TIS Portable
> +Formats Specification version 1.2* (`TIS 1.2`_). As of TIS 1.2, ELF was
> +supplemented with processor specific ELF addendums, available on the *Linux
> +Foundation referenced specification page* (`LF ref page`_). The latest ELF
> +specification is the *System V Application Binary Interface - DRAFT - 24 April
> +2001* (`gabi4`_).
> +
> +.. _SRV4 ABI: http://www.sco.com/developers/devspecs/gabi41.pdf
> +.. _TIS 1.2: https://refspecs.linuxbase.org/elf/elf.pdf
> +.. _LF ref page: https://refspecs.linuxbase.org/
> +.. _gabi4: https://refspecs.linuxbase.org/elf/gabi4+/contents.html
> +

A pointer to the wikipedia page would suffice instead of us repeating
ELF history here.

> +ELF views on Linux
> +=========
> +
> +There are two views which can be used for inspecting data in an ELF file, a
> +Linking view, and an Execution view. A Section Header Table enables one to
> +describe an object using the Linking view while a Program Header Table enables
> +one to describe an object using the Execution view. The views are not mutually
> +exclusive. For intance, vmlinux can be viewed under both views, ``readelf -S

s/intance/instance/

> +vmlinux`` for the Linking view, and ``readelf -l vmlinux`` for the Execution
> +view.  In Linux only the vmlinux file will have an Execution view, even modules
> +lack an Execution view given that vmlinux is the only file that describes how
> +the the kernel runs from the start.  All other Linux kernel object files have

s/the //

> +an available Linking view.

s/n available// - "have a Linking view" is fine.

> +
> +Under the Linking view, the Section Header Table describes all available
> +sections. The Section Header Table is an array of ELF section header data
> +structures. If on a 32-bit system this is ``struct elf32_shd``, if on a 64-bit
> +this is ``struct elf64_shdr``.

"If on ... if on" doesn't work as a sentence.

> Sections are only visible on object files that

s/on/in/

> +have a Linking view, since all Linux kernel files have Linking view, all kernel
> +objects have ELF sections.

Btw, that last sentence is kinda funny and not really needed. Or do you
wanna say that everything-code is in a section?

> +
> +Limitations on ELF sections

ELF sections limitations

> +=============> +
> +We provide a summary on the limitations of ELF sections.

Kill that sentence.

> Refer to the public
> +ELF specifications for details. Note that 64-bit limitations may depend
> +on processor specific section attributes to be used, refer to your processsor

"processsor" - the 's' button stuck? :-)

> +specification if unsure.

Better yet, kill that whole paragraph.

> +
> +Its worth ellaborating on the limitations on the name of an ELF section:

"elaborating"

> +ELF section names are stored as strings as per the ELF specification, and
> +as can be expected, these don't have explicit limitations. The implicit
> +limitation then depends on the size of an ELF object file and ELF section.
> +
> +If using really large kernels or objects with large amounts of sections one
> +would still need to be sure that ELF loader in charge of loading the Linux
> +kernel is properly updated to handle coping with the latest ELF extensions.
> +
> +   .. flat-table:: Limitations on ELF Sections
> +
> +      * - Section attribute
> +        - 32-bit
> +        - 64-bit
> +
> +      * - ELF section name
> +        - Size of an ELF section
> +        - Size of an ELF section
> +
> +      * - Size of an ELF section
> +        - 4 GiB
> +        - 16 EiB
> +
> +      * - Max number of sections in an object file
> +        - 4 GiEntries (4294967296)
> +        - 16 EiEntries (18446744073709551616)
> +
> +Program specific ELF sections

Program-specific

> +==============> +
> +The ELF specification allows for a section type to be specified as
> +*Program specific section*, defined as ``SHT_PROGBITS``. This sections type

								 section

> +enables programs to customize sections for their own use. In assembly this
									^
									is

> +specified ``@progbits`` on most architectures, on ARM this is ``%progbits``.
	     ^		  ^

	     with the	  flag				s/this is/it is called/

> +
> +``SHT_PROGBITS`` is used by Linux for defining and using Linux ELF sections.
> +
> +Special ELF Sections
> +==========
> +
> +The ELF specification defines *Special ELF Sections* on chapter 4 (`gabi4
> +ch4`_). These are defined as sections which hold program and control
> +information. Of these sections, a few have the section type as
> +``SHT_PROGBITS``. This enables Linux to *further customize* use of the section
> +beyond what the ELF specification suggests.
> +
> +.. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
> diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
> new file mode 100644
> index 000000000000..faa1c57595e1
> --- /dev/null
> +++ b/Documentation/sections/conf.py
> @@ -0,0 +1,4 @@
> +# -*- coding: utf-8; mode: python -*-
> +
> +project = 'Linux Kernel ELF sections'
> +html_search_language = 'en'
> diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
> new file mode 100644
> index 000000000000..f37511ef05e7
> --- /dev/null
> +++ b/Documentation/sections/index.rst
> @@ -0,0 +1,17 @@
> +============> +Linux Kernel ELF sections
> +============> +
> +This book documents the different ELF sections used on the Linux kernel.

							in

> +We start off by providing references to how ELF was standardized, references
> +to the standards on ELF sections, review limitations of ELF sections, and
> +finally how Linux uses ELF sections in the Linux kernel. Certain important
> +Linux ELF sections are documented carefully: we describe the goal of the
> +ELF section, and address concurrency considerations when applicable. A few
> +common a set of Linux helpers for ELF sections are also documented.

s/few common a //

> +
> +.. toctree::
> +   :maxdepth: 4
> +
> +   background
> +   section-core

...

> diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
> new file mode 100644
> index 000000000000..0b9c68429a1a
> --- /dev/null
> +++ b/arch/unicore32/include/asm/section-core.h
> @@ -0,0 +1,19 @@
> +#ifndef __UNICORE_SECTION_CORE_ASM_H__
> +#define __UNICORE_SECTION_CORE_ASM_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/.

Isn't all kernel code GPLv2?

> + */
> +
> +/* Unicore32 has known to not work properly with the type set, so ignore it */
> +
> +#define __set_section_core_type(___section, ___core, ___name,		\
> +				___level, ___flags, ___type)		\
> +	.section ___section..___core.___name.___level, ___flags
> +
> +#include <asm-generic/section-core.h>
> +
> +#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
> diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
> index 2b892e2313a9..af975f21eeee 100644
> --- a/arch/x86/include/asm/Kbuild
> +++ b/arch/x86/include/asm/Kbuild
> @@ -12,3 +12,4 @@ generic-y += dma-contiguous.h
>  generic-y += early_ioremap.h
>  generic-y += mcs_spinlock.h
>  generic-y += mm-arch-hooks.h
> +generic-y += section-core.h
> diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
> index b7fbaa56b51a..7879c31e66a7 100644
> --- a/arch/xtensa/include/asm/Kbuild
> +++ b/arch/xtensa/include/asm/Kbuild
> @@ -32,3 +32,4 @@ generic-y += topology.h
>  generic-y += trace_clock.h
>  generic-y += word-at-a-time.h
>  generic-y += xor.h
> +generic-y += section-core.h
> diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
> new file mode 100644
> index 000000000000..bb16befc4251
> --- /dev/null
> +++ b/include/asm-generic/section-core.h
> @@ -0,0 +1,307 @@
> +#ifndef _ASM_GENERIC_SECTION_CORE_H_
> +#define _ASM_GENERIC_SECTION_CORE_H_
> +/*
> + * Linux section core definitions
> + *
> + * 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/.

Ditto.

> + */
> +
> +/**
> + * DOC: Linux ELF program specific sections
> + *
> + * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and definition
							     ^^^^^^^^^^^^^^^^^^^^^^^^

							     needs rewording

> of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
> + * sections. This chaper is dedicated to documenting Linux program specific

"chapter"

Please spellcheck the whole patchset before next submission.

> + * sections and helpers available to make use of these easier to implement and
> + * use.

Huh, come again? This sentence is funny.

> + *
> + * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
> + */
> +
> +/**
> + * DOC: Linux linker script
> + *
> + * Linux uses a custom linker script to build the vmlinux binary, it uses it to
> + * strategically place and define Linux ELF sections.  Each architecture needs
> + * to implement its own linker script, it is expected to reside in

			      ... script which is expected ...

> + * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
> + * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
> + * as well as some helpers documented in this chapter.
> + *
> + * In assembly it is common practice to use dots (``.``) in labels to avoid
> + * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
> + * name but not a C symbol. Historically then, two dots are used (``..``)
> + * have been used in linker scripts when adding program specific sections

are used .. have been used?

> + * when there are concerns to avoid clashes with compiler generated sections.

This last sentence needs simplifying.

> + */
> +
> +/**
> + * DOC: Memory protection
> + *
> + * Linux allows architectures which support memory protection features to
> + * take advantage of them by letting architectures define and enable
> + * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.

Simplify: "Architectures with memory protection features can define and
enable CONFIG_DEBUG_RODATA... "

> + * mark_rodata_ro() can be used for instance to mark specific sections as
				  , for instance, 


> + * read-only or non-executable.
> + *
> + * Linux typically follows a convention to have the .rodata ELF section follow
> + * after the .text ELF section, it does this to help architectures which
				 . It does this...

> + * support memory protection to mark both .text and .rodata as read-only in
> + * one shot.
> + *
> + * For more details refer to mark_rodata_ro().
> + */
> +
> +/**
> + * DOC: .rodata
> + *
> + * ELF section used for data which must be protected from write access.
> + */
> +
> +/**
> + * DOC: .text
> + *
> + * ELF section name used for code (functions) used during regular
> + * kernel run time.
> + */
> +
> +/**
> + * DOC: .data
> + *
> + * ELF section used for read-write data.
> + */
> +
> +/**
> + * DOC: Linux init sections
> + *
> + * These sections are used for code and data structures used during boot or
> + * module initialization. On architectures that support it (x86, x86_64), all
> + * this code is freed up by the kernel right before the fist userspace init
> + * process is called when built-in to the kernel, and if modular it is freed
> + * after module initialization. Since the code is freed so early, in theory
> + * there should be no races against freeing this code with other CPUs. Init
> + * section code and data structures should never be exported with
> + * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
> + * after bootup.
> + */
> +
> +/**
> + * DOC: .init.text
> + *
> + * ELF section for code (functions) used only during boot or driver
> + * initialization.
> + *
> + */
> +
> +/**
> + * DOC: .init.data
> + *
> + * ELF section used for data structures used only during boot or driver
> + * initialization.
> + */
> +
> +/**
> + * DOC: .init.rodata
> + *
> + * ELF section used for read-only code (functions) used only during boot
> + * or driver initialization.
> + */
> +
> +/**
> + * DOC: .initcall
> + *
> + * ELF section used for subsystem init calls. There are init levels
> + * representing different functionality in the kernel. For more details
> + * refer to __define_initcall().
> + */
> +
> +/**
> + * DOC: Linux exit sections
> + *
> + * These sections are used to declare a functions and data structures which

s/a //

> + * are only required on exit, the function or data structure will be dropped
> + * if the code declaring this section is not compiled as a module on
> + * architectures that support this (x86, x86_64). There is no special case
> + * handling for this code when built-in to the kernel.
> + */
> +
> +/**
> + * DOC: .exit.text
> + *
> + * ELF section used to for code (functions) used only during module unload.
> + */
> +
> +/**
> + * DOC: .exit.data
> + *
> + * ELF section used to for data structures used only during module
> + * unload.
> + */
> +
> +/**
> + * DOC: .exitcall.exit
> + *
> + * ELF section used for exit routines, order is important and maintained by
> + * link order.
> + */
> +
> +/**
> + * DOC: Linux references to init sections
> + *
> + * These sections are used to teach modpost to not warn about possible
> + * misuses of init section code from other sections. If you use this
> + * your use case should document why you are certain such use of init
> + * sectioned code is valid. For more details refer to ``include/linux/init.h``
> + * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
> + */
> +
> +/**
> + * DOC: .ref.text
> + *
> + * ELF section used to annotate code (functions) which has been vetteed as

vetted?

> + * valid for its reference or use of other code (functions) or data structures
> + * which are part of the init sections.
> + */
> +
> +/**
> + * DOC: .ref.data
> + *
> + * ELF section used for data structures which have been vetteed for its

ditto.

> + * reference or use of other code (functions) or data structures part of the
> + * init sections.
> + */
> +
> +/**
> + * DOC: .ref.rodata
> + *
> + * ELF section used to annotate const code (functions) const data structures
> + * which has been vetteed for its reference or use of other code (functions)

ditto.

> + * or data structures part of the init sections.
> + */
> +
> +/* Can be used on foo.S for instance */

What does that comment mean?

> +#ifndef __set_section_core_type
> +# define __set_section_core_type(___section, ___core, ___name,		\
> +				 ___level, ___flags, ___type)		\
> +	.section ___section..___core.___name.___level, ___flags, ___type

Are you sure we need 4 levels of hierarchy?

If so, we should document what all those section, core, name and level
mean and how the whole sections hierarchy is supposed to look like.

> +#endif
> +
> +#ifndef __set_section_core
> +# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
> +	.section ___section..___core.___name.___level, ___flags
> +#endif
> +
> +#ifndef __push_section_core
> +# define __push_section_core(__section, __core, __name, __level, __flags) \
> +	.pushsection __section..__core.__name.__level, __flags
> +#endif
> +
> +#ifdef __KERNEL__
> +#include <linux/stringify.h>
> +#endif
> +
> +#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
> +
> +# ifndef LINKER_SCRIPT
> +
> +#  ifndef push_section_core
> +#   define push_section_core(__section, __core, __name, __level, __flags) \
> +	 __push_section_core(__section, __core, __name,			  \
> +			     __level, __stringify(__flags))
> +#  endif
> +
> +#  ifndef set_section_core
> +#   define set_section_core(__section, __core, __name,			\
> +			    __level, __flags)				\
> +	__set_section_core(__section, __core, __name,			\
> +			   __level, __stringify(__flags))
> +#  endif
> +
> +#  ifndef set_section_core_type
> +#   define set_section_core_type(__section, __core, __name,		\
> +				 __level, __flags, __type)		\
> +	__set_section_core_type(__section, __core, __name, __level,	\
> +				__stringify(__flags), __type)
> +#  endif
> +
> +# endif /* LINKER_SCRIPT */
> +#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
> +
> +/*
> + * As per gcc's documentation a common asm separator is a new line followed
> + * by tab [0], it however seems possible to also just use a newline as its

		. It, however, seems ...

> + * the most commonly empirically observed semantic and folks seem to agree
> + * this even works on S390. In case your architecture disagrees you may
> + * override this and define your own and keep the rest of the macros.
> + *
> + * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
> + */
> +# ifndef ASM_CMD_SEP
> +#  define ASM_CMD_SEP	"\n"
> +# endif
> +
> +# ifndef set_section_core
> +#  define set_section_core(__section, __core, __name, __level, __flags)	\
> +	__stringify(__set_section_core_type(__section, __core, __name,	\
> +					    __level, __stringify(__flags))) \
> +	ASM_CMD_SEP
> +# endif
> +
> +/*
> + * Some architectures (arm, and avr32 are two examples on kprobes) seem
> + * currently explicitly specify the type [0] -- this can be any of the
> + * optional constants on ELF:
> + *
> + * @progbits - section contains data
> + * @nobits - section does not contain data (i.e., section only occupies space)
> + * @note - section contains data which is used by things other than the program
> + * @init_array - section contains an array of pointers to init functions
> + * @fini_array - section contains an array of pointers to finish functions
> + * @preinit_array - section contains an array of pointers to pre-init functions
> + *
> + * ARM requires % instead of @.
> + *
> + * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
> + * defaults are as follows:
> + *
> + * section .text    progbits  alloc   exec    nowrite  align\x16
> + * section .rodata  progbits  alloc   noexec  nowrite  align=4
> + * section .lrodata progbits  alloc   noexec  nowrite  align=4
> + * section .data    progbits  alloc   noexec  write    align=4
> + * section .ldata   progbits  alloc   noexec  write    align=4
> + * section .bss     nobits    alloc   noexec  write    align=4
> + * section .lbss    nobits    alloc   noexec  write    align=4
> + * section .tdata   progbits  alloc   noexec  write    align=4    tls
> + * section .tbss    nobits    alloc   noexec  write    align=4    tls
> + * section .comment progbits  noalloc noexec  nowrite  align=1
> + * section other    progbits  alloc   noexec  nowrite  align=1
> + *
> + * gas should have sensible defaults for architectures...
> + *
> + * [0] http://www.nasm.us/doc/nasmdoc7.html
> + */
> +# ifndef set_section_core_type
> +#  define set_section_core_type(__section, __core, __name, __level,	\
> +				__flags, __type)			\
> +	__stringify(__set_section_core_type(__section, __core,		\
> +					    __name, __level,		\
> +					    __stringify(__flags),	\
> +					    __type))			\
> +	ASM_CMD_SEP
> +# endif
> +
> +# ifndef push_section_core
> +#  define push_section_core(__section, __core, __name,			\
> +			    __level, __flags)				\
> +	__stringify(__push_section_core(__section, __core,		\
> +					__name,	__level,		\
> +					__stringify(__flags)))		\
> +	ASM_CMD_SEP
> +# endif
> +
> +#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
> +#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
> diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
> index 4df64a1fc09e..b145ae8d9cbe 100644
> --- a/include/asm-generic/sections.h
> +++ b/include/asm-generic/sections.h
> @@ -1,6 +1,8 @@
>  #ifndef _ASM_GENERIC_SECTIONS_H_
>  #define _ASM_GENERIC_SECTIONS_H_
>  
> +#include <asm/section-core.h>
> +
>  /* References to section boundaries */
>  
>  #include <linux/compiler.h>
> diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
> index 0968d13b3885..483f60c451f9 100644
> --- a/include/asm-generic/vmlinux.lds.h
> +++ b/include/asm-generic/vmlinux.lds.h
> @@ -55,6 +55,7 @@
>  #endif
>  
>  #include <linux/export.h>
> +#include <asm/section-core.h>
>  
>  /* Align . to a 8 byte boundary equals to maximum function alignment. */
>  #define ALIGN_FUNCTION()  . = ALIGN(8)
> diff --git a/include/linux/init.h b/include/linux/init.h
> index 885c3e6d0f9d..116e3262332a 100644
> --- a/include/linux/init.h
> +++ b/include/linux/init.h
> @@ -130,6 +130,24 @@ int __init init_rootfs(void);
>  extern bool rodata_enabled;
>  #endif
>  #ifdef CONFIG_DEBUG_RODATA
> +/**
> + * mark_rodata_ro - implemement memory protection for ELF sections
> + *
> + * Architectures which support memory protection define a kernel configuration
> + * entry for CONFIG_DEBUG_RODATA,

That's just too many words for nothing. You can just as well say:

"Architectures which support memory protection enable CONFIG_DEBUG_RODATA and
implement mark_rodata_ro()."

> enable it in and implement mark_rodata_ro().
> + * mark_rodata_ro() should strive to adjust the .rodata and .text ELF sections
> + * with read-only memory protection to prevent modifications of these sections

"mark_rodata_ro() marks .rodata and .text section read-only..."

Simple.

> + * after bootup. It can also try to use memory protection to prevent execution
> + * on the .rodata ELF section.
> + *
> + * In order to help architectures set both .text and .rodata as read-only with
> + * memory protections in one shot Linux has typically followed the convention
> + * to have the .rodata ELF section follow the .text ELF section on the vmlinux

								   in

> + * linker script.
> + *
> + * Linux calls mark_rodata_ro() after freeing .init code and prior to calling
> + * the first init userspace process.

"first init userspace process" either say "prior to calling init" or
"prior to calling the first userspace process" but both is jambalayed
into something confusing.

> + */
>  void mark_rodata_ro(void);
>  #endif
>  
> @@ -140,25 +158,70 @@ extern bool initcall_debug;
>  #endif
>    
>  #ifndef MODULE
> +/**
> + * DOC: Initcall levels
> + *
> + * When Linux boots the kernel do_initcalls() iterates over each Linux

When Linux boots the kernel?!? You're joking, right?

Just do "During boot, do_initcalls() ..."

> + * initialization level ID and calls all routines embedded on each level ID.
> + * Prior to v2.5.2.3 Linux had only one init level onto which all init
> + * functions folded onto using __initcall(). After v2.5.2.4 Linux split up
> + * initcalls into 7 separate initcall subsection levels, each level describing
> + * different functionality part of the kernel (commit `9d6ba121b7e17085`_
> + * (v2.5.2.3 -> v2.5.2.4)). In order to remain backward compatible __initcall()
> + * calls were left mapped to device_initcall().

And why do we need all that git archeology here?

> + * Each init level consists of a dedicated ELF section, init functions are
> + * associated to an init level by linking it into the respective level's
		 with

> + * ELF section.
> + *
> + * Lower order init levels run prior to higher order init levels. Ordering
> + * inside each initcall level is determined by respective link order.

Those last two sentences are enough.

> + *
> + * .. _9d6ba121b7e17085: https://git.kernel.org/cgit/linux/kernel/git/history/history.git/commit/?id6ba121b7e17085c95139233686b27a4d4c650e

That's one ugly footnote. Also, the git commit id suffices, you don't
need the URL.

> + */
>  
>  #ifndef __ASSEMBLY__
>  
> -/*
> - * initcalls are now grouped by functionality into separate
> - * subsections. Ordering inside the subsections is determined
> - * by link order. 
> - * For backwards compatibility, initcall() puts the call in 
> - * the device init subsection.
> +/**
> + * __define_initcall - wrapper for definiting init levels
		       ()

also s/definiting/defining/

Also, this is not what __define_initcall() does. It is not defining init levels.

>   *
> - * The `id' arg to __define_initcall() is needed so that multiple initcalls
> - * can point at the same handler without causing duplicate-symbol build errors.
> + * @fn: init routine
> + * @id: init level
>   *
> - * Initcalls are run by placing pointers in initcall sections that the
> - * kernel iterates at runtime. The linker can do dead code / data elimination
> - * and remove that completely, so the initcall sections have to be marked
> - * as KEEP() in the linker script.
> + * Defines a kernel initialization level. A respective linker script entry
> + * is required to ensure the init level is accounted for and to ensure symbols
> + * exist for iterating over all functions in the init level. A init level
								An

> + * represents a series of functionality in the kernel.

That sounds yucky.

An init level is a bunch of functions which are called after init_level
- 1 and before init_level + 1.

> + *
> + * Ordering within an initialization level is determined by link order, so
> + * for instance if a Makefile had::
> + *
> + *	obj-y += foo.o
> + *	obj-y += bar.o
> + *
> + * And foo.c::
> + *
> + *	subsys_initcall(foo_init);
> + *
> + * And bar.c had::
> + *
> + *	subsys_initcall(bar_init);
> + *
> + * foo_init() would be called prior to bar_init().
> + *
> + * Note that @id in __define_initcall() also enables multiple initcalls
> + * to be created using the same handler for different init levels without
> + * causing duplicate-symbol build errors.
> + *
> + * Initcalls are run by placing start symbols to initcall levels inside ELF
> + * sections, the kernel in turn uses these symbols to iterate over each init
> + * level at runtime with do_initcall_level(). The end of each init level is
> + * marked by the subsequent's symbol's start address until we reach the symbol
> + * ``__initcall_end``.

Needlessly complex, simplify.

> The linker can do dead code / data elimination and each
> + * init level start symbol could be removed completely in this process, to
									 . To   <-- new sentence

> + * avoid this each init level start symbols must be marked as 'KEEP()' in the
> + * linker script to avoid any linker optimization heuristic on initcalls.
>   */
> -
>  #define __define_initcall(fn, id) \
>  	static initcall_t __initcall_##fn##id __used \
>  	__attribute__((__section__(".initcall" #id ".init"))) = fn;
> diff --git a/include/linux/sections.h b/include/linux/sections.h
> new file mode 100644
> index 000000000000..6771c727bcd1
> --- /dev/null
> +++ b/include/linux/sections.h
> @@ -0,0 +1,87 @@
> +#ifndef _LINUX_SECTIONS_H
> +#define _LINUX_SECTIONS_H
> +/*
> + * Linux de-facto sections

Useless.

> + *
> + * 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>
> +#include <linux/export.h>
> +
> +#ifndef __ASSEMBLY__
> +
> +/**
> + * DOC: Introduction
> + *
> + * Linux defines a set of common helpers which can be used to against its use
						      ^^^^^^^^^^^^^^^^^^^^^^^^^^

??

> + * of standard or custom Linux sections, this section is dedicated to these

this section is talking about sections, that's too much.

> + * helpers.
> + */
> +
> +/**
> + * LINUX_SECTION_ALIGNMENT - get section alignment
> + *
> + * @name: section name
> + *
> + * Gives you the alignment for the section.
> + */
> +#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))

Eeww, too long and it is a getter but doesn't have "GET" in its name.

How about GET_SECTION_ALIGN() ?

And what's with the "LINUX_" prefix - that's like useless use of screen
real estate.

> +
> +/**
> + * LINUX_SECTION_START - get address of start of section

GET_SECTION_START()	-  get address of section start

> + *
> + * @name: section name
> + *
> + * This gives you the start address of the section.
> + * This should give you the address of the first entry.

Huh?

> + *
> + */
> +#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)

Ditto.

> +
> +/**
> + * LINUX_SECTION_END - get address of end of the section
> + *
> + * @name: section name
> + *
> + * This gives you the end address of the section.
> + * This should give you the address of the end of the
> + * section. This will match the start address if the
> + * section is empty.
> + */
> +#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
> +
> +/**
> + * DECLARE_LINUX_SECTION - Declares a custom Linux section

DECLARE_SECTION() is perfectly fine IMO.

> + *
> + * @type: type of custom Linux section
> + * @name: custom section name
> + *
> + * Declares a read-write custom Linux section
> + */
> +#define DECLARE_LINUX_SECTION(type, name)				\
> +	 extern type VMLINUX_SYMBOL(name)[], \
> +		     VMLINUX_SYMBOL(name##__end)[]
> +
> +/**
> + * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section

DECLARE_SECTION_RO()

> + *
> + * @type: type of custom Linux section
> + * @name: custom section name
> + *
> + * Declares a read-only custom Linux section
> + */
> +#define DECLARE_LINUX_SECTION_RO(type, name)				\
> +	 extern const type VMLINUX_SYMBOL(name)[],			\
> +			   VMLINUX_SYMBOL(name##__end)[]
> +
> +#define __SECTION_CORE(section, core, name, level)			\
> +	#section ".." #core "." #name "." #level
> +
> +#endif /* __ASSEMBLY__ */
> +
> +#endif /* _LINUX_SECTIONS_H */
> -- 

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.
--
To unsubscribe from this list: send the line "unsubscribe linux-sh" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v6 01/14] generic-sections: add section core helpers
@ 2017-01-16 14:46           ` Borislav Petkov
  0 siblings, 0 replies; 480+ messages in thread
From: Borislav Petkov @ 2017-01-16 14:46 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, gregkh, rusty, gnomes, alan, dwmw2,
	arnd, ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Mon, Jan 09, 2017 at 06:58:19AM -0800, Luis R. Rodriguez wrote:
> Linux makes extensive use of custom ELF header sections,
> documentation for these are well scatterred. Unify this

			  is

> documentation in a central place and provide helpers to
> build custom Linux sections.

This patch contains at least three logical changes and needs splitting:

* unify documentation
* adding helpers
* MAINTAINERS addition

Documentation and MAINTAINERS changes should go last in the patchset.

Accordingly, the huuge commit message below should be spread around
those three patches.

> 
> This also generalizes sections code to enable avoiding
> modifying the linker scripts when we want to add new
> custom Linux sections. In order to make this generally
> useful we need to ensure all architectures can make use of
> core section helpers but that they can also override should
> this be needed. Instead of relying on section.h this adds
> a sections-core.h since this will be targetted to be safe
> to be used on asm code, linker scripts and C code.
> 
> v5:
> 
> o Huge documentation revamp based on a careful review of the ELF
>   specifications. Includes documentation now also about usage of
>   two dots (..) when prefixing ELF program specific sections.
> 
> o Replace macros for sections names in favor of just using
>   the section names explicitly in the linker script. This is
>   perhaps more work to grep but this is what folks seem to
>   currently prefer.
> 
> o Fix .text and .rodata documentation to explain memory protection
>   strategies which architectures can embrace upon initialization
>   (documents CONFIG_DEBUG_RODATA and mark_rodata_ro())
> 
> o Skip the 'Linux section ordering' documentation section, we'll instead
>   add this on subsequent patch which will expand on it considerably
> 
> o Dropped tree on MAINTAINERS -- as per discussions with Arnd, hpa and
>   Josh, its easier to just let changes for sections go in through the
>   respective tree that needs the changes.
> 
> o Fix typos on documentation
> 
> o Dropped SECTION_ALL(), __SECTION_CORE(), SECTION_CORE_ALL() macros
>   since we are favoring using explicit section names. These are
>   useless if we are being explicit.
> 
> o Drop LINUX_SECTION_SIZE(), LINUX_SECTION_EMPTY() in favor of having
>   section ranges and linker tables define their own, to avoid confusion
>   and make code more readable.
> 
> o Add __define_initcall() documentation and a small section describing
>   our current initcall levels. This should help also clarify what was
>   meant about keeping backward compatiblity.
> 
> v4:
> 
> o Port to shiny new sphinx documentation format

This looks like a 4th patch ontop of the unifying documentation one.

> 
> o fix a unicore32 build, turns out this actually fixes unicore32
>   defconfig builds which were failing for a long while. unicore32
>   does not seem to grok well the type passed on a section declaration,
>   this ignores it.
> 
> o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
>   this was causing final linker issues with blackfin -- this is
>   a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
>   being metatag. metatag is not supported on 0-day so I cannot confirm
>   compilation there.

...

> +++ b/Documentation/sections/background.rst
> @@ -0,0 +1,105 @@
> +======================
> +ELF section background
> +======================
> +
> +About
> +=====
> +
> +The purpose of this chapter is to help those not familiar with ELF to brush up
> +the latest ELF specifications in order to help understand how Linux uses and
> +defines its own ELF sections.
> +
> +Standardized ELF
> +================
> +
> +The first publication documenting ELF was UNIX System Laboratories' (USL)
> +*System V Release 4 Application Binary Interface* (`SRV4 ABI`_) specification.
> +Originally ELF was only a small part of the SRV4 ABI, with time however new
> +specifications only put focus on ELF, such was the case of the *TIS Portable
> +Formats Specification version 1.2* (`TIS 1.2`_). As of TIS 1.2, ELF was
> +supplemented with processor specific ELF addendums, available on the *Linux
> +Foundation referenced specification page* (`LF ref page`_). The latest ELF
> +specification is the *System V Application Binary Interface - DRAFT - 24 April
> +2001* (`gabi4`_).
> +
> +.. _SRV4 ABI: http://www.sco.com/developers/devspecs/gabi41.pdf
> +.. _TIS 1.2: https://refspecs.linuxbase.org/elf/elf.pdf
> +.. _LF ref page: https://refspecs.linuxbase.org/
> +.. _gabi4: https://refspecs.linuxbase.org/elf/gabi4+/contents.html
> +

A pointer to the wikipedia page would suffice instead of us repeating
ELF history here.

> +ELF views on Linux
> +==================
> +
> +There are two views which can be used for inspecting data in an ELF file, a
> +Linking view, and an Execution view. A Section Header Table enables one to
> +describe an object using the Linking view while a Program Header Table enables
> +one to describe an object using the Execution view. The views are not mutually
> +exclusive. For intance, vmlinux can be viewed under both views, ``readelf -S

s/intance/instance/

> +vmlinux`` for the Linking view, and ``readelf -l vmlinux`` for the Execution
> +view.  In Linux only the vmlinux file will have an Execution view, even modules
> +lack an Execution view given that vmlinux is the only file that describes how
> +the the kernel runs from the start.  All other Linux kernel object files have

s/the //

> +an available Linking view.

s/n available// - "have a Linking view" is fine.

> +
> +Under the Linking view, the Section Header Table describes all available
> +sections. The Section Header Table is an array of ELF section header data
> +structures. If on a 32-bit system this is ``struct elf32_shd``, if on a 64-bit
> +this is ``struct elf64_shdr``.

"If on ... if on" doesn't work as a sentence.

> Sections are only visible on object files that

s/on/in/

> +have a Linking view, since all Linux kernel files have Linking view, all kernel
> +objects have ELF sections.

Btw, that last sentence is kinda funny and not really needed. Or do you
wanna say that everything-code is in a section?

> +
> +Limitations on ELF sections

ELF sections limitations

> +===========================
> +
> +We provide a summary on the limitations of ELF sections.

Kill that sentence.

> Refer to the public
> +ELF specifications for details. Note that 64-bit limitations may depend
> +on processor specific section attributes to be used, refer to your processsor

"processsor" - the 's' button stuck? :-)

> +specification if unsure.

Better yet, kill that whole paragraph.

> +
> +Its worth ellaborating on the limitations on the name of an ELF section:

"elaborating"

> +ELF section names are stored as strings as per the ELF specification, and
> +as can be expected, these don't have explicit limitations. The implicit
> +limitation then depends on the size of an ELF object file and ELF section.
> +
> +If using really large kernels or objects with large amounts of sections one
> +would still need to be sure that ELF loader in charge of loading the Linux
> +kernel is properly updated to handle coping with the latest ELF extensions.
> +
> +   .. flat-table:: Limitations on ELF Sections
> +
> +      * - Section attribute
> +        - 32-bit
> +        - 64-bit
> +
> +      * - ELF section name
> +        - Size of an ELF section
> +        - Size of an ELF section
> +
> +      * - Size of an ELF section
> +        - 4 GiB
> +        - 16 EiB
> +
> +      * - Max number of sections in an object file
> +        - 4 GiEntries (4294967296)
> +        - 16 EiEntries (18446744073709551616)
> +
> +Program specific ELF sections

Program-specific

> +=============================
> +
> +The ELF specification allows for a section type to be specified as
> +*Program specific section*, defined as ``SHT_PROGBITS``. This sections type

								 section

> +enables programs to customize sections for their own use. In assembly this
									^
									is

> +specified ``@progbits`` on most architectures, on ARM this is ``%progbits``.
	     ^		  ^

	     with the	  flag				s/this is/it is called/

> +
> +``SHT_PROGBITS`` is used by Linux for defining and using Linux ELF sections.
> +
> +Special ELF Sections
> +====================
> +
> +The ELF specification defines *Special ELF Sections* on chapter 4 (`gabi4
> +ch4`_). These are defined as sections which hold program and control
> +information. Of these sections, a few have the section type as
> +``SHT_PROGBITS``. This enables Linux to *further customize* use of the section
> +beyond what the ELF specification suggests.
> +
> +.. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
> diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
> new file mode 100644
> index 000000000000..faa1c57595e1
> --- /dev/null
> +++ b/Documentation/sections/conf.py
> @@ -0,0 +1,4 @@
> +# -*- coding: utf-8; mode: python -*-
> +
> +project = 'Linux Kernel ELF sections'
> +html_search_language = 'en'
> diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
> new file mode 100644
> index 000000000000..f37511ef05e7
> --- /dev/null
> +++ b/Documentation/sections/index.rst
> @@ -0,0 +1,17 @@
> +=========================
> +Linux Kernel ELF sections
> +=========================
> +
> +This book documents the different ELF sections used on the Linux kernel.

							in

> +We start off by providing references to how ELF was standardized, references
> +to the standards on ELF sections, review limitations of ELF sections, and
> +finally how Linux uses ELF sections in the Linux kernel. Certain important
> +Linux ELF sections are documented carefully: we describe the goal of the
> +ELF section, and address concurrency considerations when applicable. A few
> +common a set of Linux helpers for ELF sections are also documented.

s/few common a //

> +
> +.. toctree::
> +   :maxdepth: 4
> +
> +   background
> +   section-core

...

> diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
> new file mode 100644
> index 000000000000..0b9c68429a1a
> --- /dev/null
> +++ b/arch/unicore32/include/asm/section-core.h
> @@ -0,0 +1,19 @@
> +#ifndef __UNICORE_SECTION_CORE_ASM_H__
> +#define __UNICORE_SECTION_CORE_ASM_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/.

Isn't all kernel code GPLv2?

> + */
> +
> +/* Unicore32 has known to not work properly with the type set, so ignore it */
> +
> +#define __set_section_core_type(___section, ___core, ___name,		\
> +				___level, ___flags, ___type)		\
> +	.section ___section..___core.___name.___level, ___flags
> +
> +#include <asm-generic/section-core.h>
> +
> +#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
> diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
> index 2b892e2313a9..af975f21eeee 100644
> --- a/arch/x86/include/asm/Kbuild
> +++ b/arch/x86/include/asm/Kbuild
> @@ -12,3 +12,4 @@ generic-y += dma-contiguous.h
>  generic-y += early_ioremap.h
>  generic-y += mcs_spinlock.h
>  generic-y += mm-arch-hooks.h
> +generic-y += section-core.h
> diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
> index b7fbaa56b51a..7879c31e66a7 100644
> --- a/arch/xtensa/include/asm/Kbuild
> +++ b/arch/xtensa/include/asm/Kbuild
> @@ -32,3 +32,4 @@ generic-y += topology.h
>  generic-y += trace_clock.h
>  generic-y += word-at-a-time.h
>  generic-y += xor.h
> +generic-y += section-core.h
> diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
> new file mode 100644
> index 000000000000..bb16befc4251
> --- /dev/null
> +++ b/include/asm-generic/section-core.h
> @@ -0,0 +1,307 @@
> +#ifndef _ASM_GENERIC_SECTION_CORE_H_
> +#define _ASM_GENERIC_SECTION_CORE_H_
> +/*
> + * Linux section core definitions
> + *
> + * 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/.

Ditto.

> + */
> +
> +/**
> + * DOC: Linux ELF program specific sections
> + *
> + * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and definition
							     ^^^^^^^^^^^^^^^^^^^^^^^^

							     needs rewording

> of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
> + * sections. This chaper is dedicated to documenting Linux program specific

"chapter"

Please spellcheck the whole patchset before next submission.

> + * sections and helpers available to make use of these easier to implement and
> + * use.

Huh, come again? This sentence is funny.

> + *
> + * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
> + */
> +
> +/**
> + * DOC: Linux linker script
> + *
> + * Linux uses a custom linker script to build the vmlinux binary, it uses it to
> + * strategically place and define Linux ELF sections.  Each architecture needs
> + * to implement its own linker script, it is expected to reside in

			      ... script which is expected ...

> + * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
> + * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
> + * as well as some helpers documented in this chapter.
> + *
> + * In assembly it is common practice to use dots (``.``) in labels to avoid
> + * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
> + * name but not a C symbol. Historically then, two dots are used (``..``)
> + * have been used in linker scripts when adding program specific sections

are used .. have been used?

> + * when there are concerns to avoid clashes with compiler generated sections.

This last sentence needs simplifying.

> + */
> +
> +/**
> + * DOC: Memory protection
> + *
> + * Linux allows architectures which support memory protection features to
> + * take advantage of them by letting architectures define and enable
> + * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.

Simplify: "Architectures with memory protection features can define and
enable CONFIG_DEBUG_RODATA... "

> + * mark_rodata_ro() can be used for instance to mark specific sections as
				  , for instance, 


> + * read-only or non-executable.
> + *
> + * Linux typically follows a convention to have the .rodata ELF section follow
> + * after the .text ELF section, it does this to help architectures which
				 . It does this...

> + * support memory protection to mark both .text and .rodata as read-only in
> + * one shot.
> + *
> + * For more details refer to mark_rodata_ro().
> + */
> +
> +/**
> + * DOC: .rodata
> + *
> + * ELF section used for data which must be protected from write access.
> + */
> +
> +/**
> + * DOC: .text
> + *
> + * ELF section name used for code (functions) used during regular
> + * kernel run time.
> + */
> +
> +/**
> + * DOC: .data
> + *
> + * ELF section used for read-write data.
> + */
> +
> +/**
> + * DOC: Linux init sections
> + *
> + * These sections are used for code and data structures used during boot or
> + * module initialization. On architectures that support it (x86, x86_64), all
> + * this code is freed up by the kernel right before the fist userspace init
> + * process is called when built-in to the kernel, and if modular it is freed
> + * after module initialization. Since the code is freed so early, in theory
> + * there should be no races against freeing this code with other CPUs. Init
> + * section code and data structures should never be exported with
> + * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
> + * after bootup.
> + */
> +
> +/**
> + * DOC: .init.text
> + *
> + * ELF section for code (functions) used only during boot or driver
> + * initialization.
> + *
> + */
> +
> +/**
> + * DOC: .init.data
> + *
> + * ELF section used for data structures used only during boot or driver
> + * initialization.
> + */
> +
> +/**
> + * DOC: .init.rodata
> + *
> + * ELF section used for read-only code (functions) used only during boot
> + * or driver initialization.
> + */
> +
> +/**
> + * DOC: .initcall
> + *
> + * ELF section used for subsystem init calls. There are init levels
> + * representing different functionality in the kernel. For more details
> + * refer to __define_initcall().
> + */
> +
> +/**
> + * DOC: Linux exit sections
> + *
> + * These sections are used to declare a functions and data structures which

s/a //

> + * are only required on exit, the function or data structure will be dropped
> + * if the code declaring this section is not compiled as a module on
> + * architectures that support this (x86, x86_64). There is no special case
> + * handling for this code when built-in to the kernel.
> + */
> +
> +/**
> + * DOC: .exit.text
> + *
> + * ELF section used to for code (functions) used only during module unload.
> + */
> +
> +/**
> + * DOC: .exit.data
> + *
> + * ELF section used to for data structures used only during module
> + * unload.
> + */
> +
> +/**
> + * DOC: .exitcall.exit
> + *
> + * ELF section used for exit routines, order is important and maintained by
> + * link order.
> + */
> +
> +/**
> + * DOC: Linux references to init sections
> + *
> + * These sections are used to teach modpost to not warn about possible
> + * misuses of init section code from other sections. If you use this
> + * your use case should document why you are certain such use of init
> + * sectioned code is valid. For more details refer to ``include/linux/init.h``
> + * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
> + */
> +
> +/**
> + * DOC: .ref.text
> + *
> + * ELF section used to annotate code (functions) which has been vetteed as

vetted?

> + * valid for its reference or use of other code (functions) or data structures
> + * which are part of the init sections.
> + */
> +
> +/**
> + * DOC: .ref.data
> + *
> + * ELF section used for data structures which have been vetteed for its

ditto.

> + * reference or use of other code (functions) or data structures part of the
> + * init sections.
> + */
> +
> +/**
> + * DOC: .ref.rodata
> + *
> + * ELF section used to annotate const code (functions) const data structures
> + * which has been vetteed for its reference or use of other code (functions)

ditto.

> + * or data structures part of the init sections.
> + */
> +
> +/* Can be used on foo.S for instance */

What does that comment mean?

> +#ifndef __set_section_core_type
> +# define __set_section_core_type(___section, ___core, ___name,		\
> +				 ___level, ___flags, ___type)		\
> +	.section ___section..___core.___name.___level, ___flags, ___type

Are you sure we need 4 levels of hierarchy?

If so, we should document what all those section, core, name and level
mean and how the whole sections hierarchy is supposed to look like.

> +#endif
> +
> +#ifndef __set_section_core
> +# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
> +	.section ___section..___core.___name.___level, ___flags
> +#endif
> +
> +#ifndef __push_section_core
> +# define __push_section_core(__section, __core, __name, __level, __flags) \
> +	.pushsection __section..__core.__name.__level, __flags
> +#endif
> +
> +#ifdef __KERNEL__
> +#include <linux/stringify.h>
> +#endif
> +
> +#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
> +
> +# ifndef LINKER_SCRIPT
> +
> +#  ifndef push_section_core
> +#   define push_section_core(__section, __core, __name, __level, __flags) \
> +	 __push_section_core(__section, __core, __name,			  \
> +			     __level, __stringify(__flags))
> +#  endif
> +
> +#  ifndef set_section_core
> +#   define set_section_core(__section, __core, __name,			\
> +			    __level, __flags)				\
> +	__set_section_core(__section, __core, __name,			\
> +			   __level, __stringify(__flags))
> +#  endif
> +
> +#  ifndef set_section_core_type
> +#   define set_section_core_type(__section, __core, __name,		\
> +				 __level, __flags, __type)		\
> +	__set_section_core_type(__section, __core, __name, __level,	\
> +				__stringify(__flags), __type)
> +#  endif
> +
> +# endif /* LINKER_SCRIPT */
> +#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
> +
> +/*
> + * As per gcc's documentation a common asm separator is a new line followed
> + * by tab [0], it however seems possible to also just use a newline as its

		. It, however, seems ...

> + * the most commonly empirically observed semantic and folks seem to agree
> + * this even works on S390. In case your architecture disagrees you may
> + * override this and define your own and keep the rest of the macros.
> + *
> + * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
> + */
> +# ifndef ASM_CMD_SEP
> +#  define ASM_CMD_SEP	"\n"
> +# endif
> +
> +# ifndef set_section_core
> +#  define set_section_core(__section, __core, __name, __level, __flags)	\
> +	__stringify(__set_section_core_type(__section, __core, __name,	\
> +					    __level, __stringify(__flags))) \
> +	ASM_CMD_SEP
> +# endif
> +
> +/*
> + * Some architectures (arm, and avr32 are two examples on kprobes) seem
> + * currently explicitly specify the type [0] -- this can be any of the
> + * optional constants on ELF:
> + *
> + * @progbits - section contains data
> + * @nobits - section does not contain data (i.e., section only occupies space)
> + * @note - section contains data which is used by things other than the program
> + * @init_array - section contains an array of pointers to init functions
> + * @fini_array - section contains an array of pointers to finish functions
> + * @preinit_array - section contains an array of pointers to pre-init functions
> + *
> + * ARM requires % instead of @.
> + *
> + * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
> + * defaults are as follows:
> + *
> + * section .text    progbits  alloc   exec    nowrite  align=16
> + * section .rodata  progbits  alloc   noexec  nowrite  align=4
> + * section .lrodata progbits  alloc   noexec  nowrite  align=4
> + * section .data    progbits  alloc   noexec  write    align=4
> + * section .ldata   progbits  alloc   noexec  write    align=4
> + * section .bss     nobits    alloc   noexec  write    align=4
> + * section .lbss    nobits    alloc   noexec  write    align=4
> + * section .tdata   progbits  alloc   noexec  write    align=4    tls
> + * section .tbss    nobits    alloc   noexec  write    align=4    tls
> + * section .comment progbits  noalloc noexec  nowrite  align=1
> + * section other    progbits  alloc   noexec  nowrite  align=1
> + *
> + * gas should have sensible defaults for architectures...
> + *
> + * [0] http://www.nasm.us/doc/nasmdoc7.html
> + */
> +# ifndef set_section_core_type
> +#  define set_section_core_type(__section, __core, __name, __level,	\
> +				__flags, __type)			\
> +	__stringify(__set_section_core_type(__section, __core,		\
> +					    __name, __level,		\
> +					    __stringify(__flags),	\
> +					    __type))			\
> +	ASM_CMD_SEP
> +# endif
> +
> +# ifndef push_section_core
> +#  define push_section_core(__section, __core, __name,			\
> +			    __level, __flags)				\
> +	__stringify(__push_section_core(__section, __core,		\
> +					__name,	__level,		\
> +					__stringify(__flags)))		\
> +	ASM_CMD_SEP
> +# endif
> +
> +#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
> +#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
> diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
> index 4df64a1fc09e..b145ae8d9cbe 100644
> --- a/include/asm-generic/sections.h
> +++ b/include/asm-generic/sections.h
> @@ -1,6 +1,8 @@
>  #ifndef _ASM_GENERIC_SECTIONS_H_
>  #define _ASM_GENERIC_SECTIONS_H_
>  
> +#include <asm/section-core.h>
> +
>  /* References to section boundaries */
>  
>  #include <linux/compiler.h>
> diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
> index 0968d13b3885..483f60c451f9 100644
> --- a/include/asm-generic/vmlinux.lds.h
> +++ b/include/asm-generic/vmlinux.lds.h
> @@ -55,6 +55,7 @@
>  #endif
>  
>  #include <linux/export.h>
> +#include <asm/section-core.h>
>  
>  /* Align . to a 8 byte boundary equals to maximum function alignment. */
>  #define ALIGN_FUNCTION()  . = ALIGN(8)
> diff --git a/include/linux/init.h b/include/linux/init.h
> index 885c3e6d0f9d..116e3262332a 100644
> --- a/include/linux/init.h
> +++ b/include/linux/init.h
> @@ -130,6 +130,24 @@ int __init init_rootfs(void);
>  extern bool rodata_enabled;
>  #endif
>  #ifdef CONFIG_DEBUG_RODATA
> +/**
> + * mark_rodata_ro - implemement memory protection for ELF sections
> + *
> + * Architectures which support memory protection define a kernel configuration
> + * entry for CONFIG_DEBUG_RODATA,

That's just too many words for nothing. You can just as well say:

"Architectures which support memory protection enable CONFIG_DEBUG_RODATA and
implement mark_rodata_ro()."

> enable it in and implement mark_rodata_ro().
> + * mark_rodata_ro() should strive to adjust the .rodata and .text ELF sections
> + * with read-only memory protection to prevent modifications of these sections

"mark_rodata_ro() marks .rodata and .text section read-only..."

Simple.

> + * after bootup. It can also try to use memory protection to prevent execution
> + * on the .rodata ELF section.
> + *
> + * In order to help architectures set both .text and .rodata as read-only with
> + * memory protections in one shot Linux has typically followed the convention
> + * to have the .rodata ELF section follow the .text ELF section on the vmlinux

								   in

> + * linker script.
> + *
> + * Linux calls mark_rodata_ro() after freeing .init code and prior to calling
> + * the first init userspace process.

"first init userspace process" either say "prior to calling init" or
"prior to calling the first userspace process" but both is jambalayed
into something confusing.

> + */
>  void mark_rodata_ro(void);
>  #endif
>  
> @@ -140,25 +158,70 @@ extern bool initcall_debug;
>  #endif
>    
>  #ifndef MODULE
> +/**
> + * DOC: Initcall levels
> + *
> + * When Linux boots the kernel do_initcalls() iterates over each Linux

When Linux boots the kernel?!? You're joking, right?

Just do "During boot, do_initcalls() ..."

> + * initialization level ID and calls all routines embedded on each level ID.
> + * Prior to v2.5.2.3 Linux had only one init level onto which all init
> + * functions folded onto using __initcall(). After v2.5.2.4 Linux split up
> + * initcalls into 7 separate initcall subsection levels, each level describing
> + * different functionality part of the kernel (commit `9d6ba121b7e17085`_
> + * (v2.5.2.3 -> v2.5.2.4)). In order to remain backward compatible __initcall()
> + * calls were left mapped to device_initcall().

And why do we need all that git archeology here?

> + * Each init level consists of a dedicated ELF section, init functions are
> + * associated to an init level by linking it into the respective level's
		 with

> + * ELF section.
> + *
> + * Lower order init levels run prior to higher order init levels. Ordering
> + * inside each initcall level is determined by respective link order.

Those last two sentences are enough.

> + *
> + * .. _9d6ba121b7e17085: https://git.kernel.org/cgit/linux/kernel/git/history/history.git/commit/?id=9d6ba121b7e17085c95139233686b27a4d4c650e

That's one ugly footnote. Also, the git commit id suffices, you don't
need the URL.

> + */
>  
>  #ifndef __ASSEMBLY__
>  
> -/*
> - * initcalls are now grouped by functionality into separate
> - * subsections. Ordering inside the subsections is determined
> - * by link order. 
> - * For backwards compatibility, initcall() puts the call in 
> - * the device init subsection.
> +/**
> + * __define_initcall - wrapper for definiting init levels
		       ()

also s/definiting/defining/

Also, this is not what __define_initcall() does. It is not defining init levels.

>   *
> - * The `id' arg to __define_initcall() is needed so that multiple initcalls
> - * can point at the same handler without causing duplicate-symbol build errors.
> + * @fn: init routine
> + * @id: init level
>   *
> - * Initcalls are run by placing pointers in initcall sections that the
> - * kernel iterates at runtime. The linker can do dead code / data elimination
> - * and remove that completely, so the initcall sections have to be marked
> - * as KEEP() in the linker script.
> + * Defines a kernel initialization level. A respective linker script entry
> + * is required to ensure the init level is accounted for and to ensure symbols
> + * exist for iterating over all functions in the init level. A init level
								An

> + * represents a series of functionality in the kernel.

That sounds yucky.

An init level is a bunch of functions which are called after init_level
- 1 and before init_level + 1.

> + *
> + * Ordering within an initialization level is determined by link order, so
> + * for instance if a Makefile had::
> + *
> + *	obj-y += foo.o
> + *	obj-y += bar.o
> + *
> + * And foo.c::
> + *
> + *	subsys_initcall(foo_init);
> + *
> + * And bar.c had::
> + *
> + *	subsys_initcall(bar_init);
> + *
> + * foo_init() would be called prior to bar_init().
> + *
> + * Note that @id in __define_initcall() also enables multiple initcalls
> + * to be created using the same handler for different init levels without
> + * causing duplicate-symbol build errors.
> + *
> + * Initcalls are run by placing start symbols to initcall levels inside ELF
> + * sections, the kernel in turn uses these symbols to iterate over each init
> + * level at runtime with do_initcall_level(). The end of each init level is
> + * marked by the subsequent's symbol's start address until we reach the symbol
> + * ``__initcall_end``.

Needlessly complex, simplify.

> The linker can do dead code / data elimination and each
> + * init level start symbol could be removed completely in this process, to
									 . To   <-- new sentence

> + * avoid this each init level start symbols must be marked as 'KEEP()' in the
> + * linker script to avoid any linker optimization heuristic on initcalls.
>   */
> -
>  #define __define_initcall(fn, id) \
>  	static initcall_t __initcall_##fn##id __used \
>  	__attribute__((__section__(".initcall" #id ".init"))) = fn;
> diff --git a/include/linux/sections.h b/include/linux/sections.h
> new file mode 100644
> index 000000000000..6771c727bcd1
> --- /dev/null
> +++ b/include/linux/sections.h
> @@ -0,0 +1,87 @@
> +#ifndef _LINUX_SECTIONS_H
> +#define _LINUX_SECTIONS_H
> +/*
> + * Linux de-facto sections

Useless.

> + *
> + * 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>
> +#include <linux/export.h>
> +
> +#ifndef __ASSEMBLY__
> +
> +/**
> + * DOC: Introduction
> + *
> + * Linux defines a set of common helpers which can be used to against its use
						      ^^^^^^^^^^^^^^^^^^^^^^^^^^

??

> + * of standard or custom Linux sections, this section is dedicated to these

this section is talking about sections, that's too much.

> + * helpers.
> + */
> +
> +/**
> + * LINUX_SECTION_ALIGNMENT - get section alignment
> + *
> + * @name: section name
> + *
> + * Gives you the alignment for the section.
> + */
> +#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))

Eeww, too long and it is a getter but doesn't have "GET" in its name.

How about GET_SECTION_ALIGN() ?

And what's with the "LINUX_" prefix - that's like useless use of screen
real estate.

> +
> +/**
> + * LINUX_SECTION_START - get address of start of section

GET_SECTION_START()	-  get address of section start

> + *
> + * @name: section name
> + *
> + * This gives you the start address of the section.
> + * This should give you the address of the first entry.

Huh?

> + *
> + */
> +#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)

Ditto.

> +
> +/**
> + * LINUX_SECTION_END - get address of end of the section
> + *
> + * @name: section name
> + *
> + * This gives you the end address of the section.
> + * This should give you the address of the end of the
> + * section. This will match the start address if the
> + * section is empty.
> + */
> +#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
> +
> +/**
> + * DECLARE_LINUX_SECTION - Declares a custom Linux section

DECLARE_SECTION() is perfectly fine IMO.

> + *
> + * @type: type of custom Linux section
> + * @name: custom section name
> + *
> + * Declares a read-write custom Linux section
> + */
> +#define DECLARE_LINUX_SECTION(type, name)				\
> +	 extern type VMLINUX_SYMBOL(name)[], \
> +		     VMLINUX_SYMBOL(name##__end)[]
> +
> +/**
> + * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section

DECLARE_SECTION_RO()

> + *
> + * @type: type of custom Linux section
> + * @name: custom section name
> + *
> + * Declares a read-only custom Linux section
> + */
> +#define DECLARE_LINUX_SECTION_RO(type, name)				\
> +	 extern const type VMLINUX_SYMBOL(name)[],			\
> +			   VMLINUX_SYMBOL(name##__end)[]
> +
> +#define __SECTION_CORE(section, core, name, level)			\
> +	#section ".." #core "." #name "." #level
> +
> +#endif /* __ASSEMBLY__ */
> +
> +#endif /* _LINUX_SECTIONS_H */
> -- 

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v6 01/14] generic-sections: add section core helpers
@ 2017-01-16 14:46           ` Borislav Petkov
  0 siblings, 0 replies; 480+ messages in thread
From: Borislav Petkov @ 2017-01-16 14:46 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, gregkh, rusty, gnomes, alan, dwmw2,
	arnd, ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley

On Mon, Jan 09, 2017 at 06:58:19AM -0800, Luis R. Rodriguez wrote:
> Linux makes extensive use of custom ELF header sections,
> documentation for these are well scatterred. Unify this

			  is

> documentation in a central place and provide helpers to
> build custom Linux sections.

This patch contains at least three logical changes and needs splitting:

* unify documentation
* adding helpers
* MAINTAINERS addition

Documentation and MAINTAINERS changes should go last in the patchset.

Accordingly, the huuge commit message below should be spread around
those three patches.

> 
> This also generalizes sections code to enable avoiding
> modifying the linker scripts when we want to add new
> custom Linux sections. In order to make this generally
> useful we need to ensure all architectures can make use of
> core section helpers but that they can also override should
> this be needed. Instead of relying on section.h this adds
> a sections-core.h since this will be targetted to be safe
> to be used on asm code, linker scripts and C code.
> 
> v5:
> 
> o Huge documentation revamp based on a careful review of the ELF
>   specifications. Includes documentation now also about usage of
>   two dots (..) when prefixing ELF program specific sections.
> 
> o Replace macros for sections names in favor of just using
>   the section names explicitly in the linker script. This is
>   perhaps more work to grep but this is what folks seem to
>   currently prefer.
> 
> o Fix .text and .rodata documentation to explain memory protection
>   strategies which architectures can embrace upon initialization
>   (documents CONFIG_DEBUG_RODATA and mark_rodata_ro())
> 
> o Skip the 'Linux section ordering' documentation section, we'll instead
>   add this on subsequent patch which will expand on it considerably
> 
> o Dropped tree on MAINTAINERS -- as per discussions with Arnd, hpa and
>   Josh, its easier to just let changes for sections go in through the
>   respective tree that needs the changes.
> 
> o Fix typos on documentation
> 
> o Dropped SECTION_ALL(), __SECTION_CORE(), SECTION_CORE_ALL() macros
>   since we are favoring using explicit section names. These are
>   useless if we are being explicit.
> 
> o Drop LINUX_SECTION_SIZE(), LINUX_SECTION_EMPTY() in favor of having
>   section ranges and linker tables define their own, to avoid confusion
>   and make code more readable.
> 
> o Add __define_initcall() documentation and a small section describing
>   our current initcall levels. This should help also clarify what was
>   meant about keeping backward compatiblity.
> 
> v4:
> 
> o Port to shiny new sphinx documentation format

This looks like a 4th patch ontop of the unifying documentation one.

> 
> o fix a unicore32 build, turns out this actually fixes unicore32
>   defconfig builds which were failing for a long while. unicore32
>   does not seem to grok well the type passed on a section declaration,
>   this ignores it.
> 
> o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
>   this was causing final linker issues with blackfin -- this is
>   a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
>   being metatag. metatag is not supported on 0-day so I cannot confirm
>   compilation there.

...

> +++ b/Documentation/sections/background.rst
> @@ -0,0 +1,105 @@
> +======================
> +ELF section background
> +======================
> +
> +About
> +=====
> +
> +The purpose of this chapter is to help those not familiar with ELF to brush up
> +the latest ELF specifications in order to help understand how Linux uses and
> +defines its own ELF sections.
> +
> +Standardized ELF
> +================
> +
> +The first publication documenting ELF was UNIX System Laboratories' (USL)
> +*System V Release 4 Application Binary Interface* (`SRV4 ABI`_) specification.
> +Originally ELF was only a small part of the SRV4 ABI, with time however new
> +specifications only put focus on ELF, such was the case of the *TIS Portable
> +Formats Specification version 1.2* (`TIS 1.2`_). As of TIS 1.2, ELF was
> +supplemented with processor specific ELF addendums, available on the *Linux
> +Foundation referenced specification page* (`LF ref page`_). The latest ELF
> +specification is the *System V Application Binary Interface - DRAFT - 24 April
> +2001* (`gabi4`_).
> +
> +.. _SRV4 ABI: http://www.sco.com/developers/devspecs/gabi41.pdf
> +.. _TIS 1.2: https://refspecs.linuxbase.org/elf/elf.pdf
> +.. _LF ref page: https://refspecs.linuxbase.org/
> +.. _gabi4: https://refspecs.linuxbase.org/elf/gabi4+/contents.html
> +

A pointer to the wikipedia page would suffice instead of us repeating
ELF history here.

> +ELF views on Linux
> +==================
> +
> +There are two views which can be used for inspecting data in an ELF file, a
> +Linking view, and an Execution view. A Section Header Table enables one to
> +describe an object using the Linking view while a Program Header Table enables
> +one to describe an object using the Execution view. The views are not mutually
> +exclusive. For intance, vmlinux can be viewed under both views, ``readelf -S

s/intance/instance/

> +vmlinux`` for the Linking view, and ``readelf -l vmlinux`` for the Execution
> +view.  In Linux only the vmlinux file will have an Execution view, even modules
> +lack an Execution view given that vmlinux is the only file that describes how
> +the the kernel runs from the start.  All other Linux kernel object files have

s/the //

> +an available Linking view.

s/n available// - "have a Linking view" is fine.

> +
> +Under the Linking view, the Section Header Table describes all available
> +sections. The Section Header Table is an array of ELF section header data
> +structures. If on a 32-bit system this is ``struct elf32_shd``, if on a 64-bit
> +this is ``struct elf64_shdr``.

"If on ... if on" doesn't work as a sentence.

> Sections are only visible on object files that

s/on/in/

> +have a Linking view, since all Linux kernel files have Linking view, all kernel
> +objects have ELF sections.

Btw, that last sentence is kinda funny and not really needed. Or do you
wanna say that everything-code is in a section?

> +
> +Limitations on ELF sections

ELF sections limitations

> +===========================
> +
> +We provide a summary on the limitations of ELF sections.

Kill that sentence.

> Refer to the public
> +ELF specifications for details. Note that 64-bit limitations may depend
> +on processor specific section attributes to be used, refer to your processsor

"processsor" - the 's' button stuck? :-)

> +specification if unsure.

Better yet, kill that whole paragraph.

> +
> +Its worth ellaborating on the limitations on the name of an ELF section:

"elaborating"

> +ELF section names are stored as strings as per the ELF specification, and
> +as can be expected, these don't have explicit limitations. The implicit
> +limitation then depends on the size of an ELF object file and ELF section.
> +
> +If using really large kernels or objects with large amounts of sections one
> +would still need to be sure that ELF loader in charge of loading the Linux
> +kernel is properly updated to handle coping with the latest ELF extensions.
> +
> +   .. flat-table:: Limitations on ELF Sections
> +
> +      * - Section attribute
> +        - 32-bit
> +        - 64-bit
> +
> +      * - ELF section name
> +        - Size of an ELF section
> +        - Size of an ELF section
> +
> +      * - Size of an ELF section
> +        - 4 GiB
> +        - 16 EiB
> +
> +      * - Max number of sections in an object file
> +        - 4 GiEntries (4294967296)
> +        - 16 EiEntries (18446744073709551616)
> +
> +Program specific ELF sections

Program-specific

> +=============================
> +
> +The ELF specification allows for a section type to be specified as
> +*Program specific section*, defined as ``SHT_PROGBITS``. This sections type

								 section

> +enables programs to customize sections for their own use. In assembly this
									^
									is

> +specified ``@progbits`` on most architectures, on ARM this is ``%progbits``.
	     ^		  ^

	     with the	  flag				s/this is/it is called/

> +
> +``SHT_PROGBITS`` is used by Linux for defining and using Linux ELF sections.
> +
> +Special ELF Sections
> +====================
> +
> +The ELF specification defines *Special ELF Sections* on chapter 4 (`gabi4
> +ch4`_). These are defined as sections which hold program and control
> +information. Of these sections, a few have the section type as
> +``SHT_PROGBITS``. This enables Linux to *further customize* use of the section
> +beyond what the ELF specification suggests.
> +
> +.. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
> diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
> new file mode 100644
> index 000000000000..faa1c57595e1
> --- /dev/null
> +++ b/Documentation/sections/conf.py
> @@ -0,0 +1,4 @@
> +# -*- coding: utf-8; mode: python -*-
> +
> +project = 'Linux Kernel ELF sections'
> +html_search_language = 'en'
> diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
> new file mode 100644
> index 000000000000..f37511ef05e7
> --- /dev/null
> +++ b/Documentation/sections/index.rst
> @@ -0,0 +1,17 @@
> +=========================
> +Linux Kernel ELF sections
> +=========================
> +
> +This book documents the different ELF sections used on the Linux kernel.

							in

> +We start off by providing references to how ELF was standardized, references
> +to the standards on ELF sections, review limitations of ELF sections, and
> +finally how Linux uses ELF sections in the Linux kernel. Certain important
> +Linux ELF sections are documented carefully: we describe the goal of the
> +ELF section, and address concurrency considerations when applicable. A few
> +common a set of Linux helpers for ELF sections are also documented.

s/few common a //

> +
> +.. toctree::
> +   :maxdepth: 4
> +
> +   background
> +   section-core

...

> diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
> new file mode 100644
> index 000000000000..0b9c68429a1a
> --- /dev/null
> +++ b/arch/unicore32/include/asm/section-core.h
> @@ -0,0 +1,19 @@
> +#ifndef __UNICORE_SECTION_CORE_ASM_H__
> +#define __UNICORE_SECTION_CORE_ASM_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/.

Isn't all kernel code GPLv2?

> + */
> +
> +/* Unicore32 has known to not work properly with the type set, so ignore it */
> +
> +#define __set_section_core_type(___section, ___core, ___name,		\
> +				___level, ___flags, ___type)		\
> +	.section ___section..___core.___name.___level, ___flags
> +
> +#include <asm-generic/section-core.h>
> +
> +#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
> diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
> index 2b892e2313a9..af975f21eeee 100644
> --- a/arch/x86/include/asm/Kbuild
> +++ b/arch/x86/include/asm/Kbuild
> @@ -12,3 +12,4 @@ generic-y += dma-contiguous.h
>  generic-y += early_ioremap.h
>  generic-y += mcs_spinlock.h
>  generic-y += mm-arch-hooks.h
> +generic-y += section-core.h
> diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
> index b7fbaa56b51a..7879c31e66a7 100644
> --- a/arch/xtensa/include/asm/Kbuild
> +++ b/arch/xtensa/include/asm/Kbuild
> @@ -32,3 +32,4 @@ generic-y += topology.h
>  generic-y += trace_clock.h
>  generic-y += word-at-a-time.h
>  generic-y += xor.h
> +generic-y += section-core.h
> diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
> new file mode 100644
> index 000000000000..bb16befc4251
> --- /dev/null
> +++ b/include/asm-generic/section-core.h
> @@ -0,0 +1,307 @@
> +#ifndef _ASM_GENERIC_SECTION_CORE_H_
> +#define _ASM_GENERIC_SECTION_CORE_H_
> +/*
> + * Linux section core definitions
> + *
> + * 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/.

Ditto.

> + */
> +
> +/**
> + * DOC: Linux ELF program specific sections
> + *
> + * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and definition
							     ^^^^^^^^^^^^^^^^^^^^^^^^

							     needs rewording

> of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
> + * sections. This chaper is dedicated to documenting Linux program specific

"chapter"

Please spellcheck the whole patchset before next submission.

> + * sections and helpers available to make use of these easier to implement and
> + * use.

Huh, come again? This sentence is funny.

> + *
> + * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
> + */
> +
> +/**
> + * DOC: Linux linker script
> + *
> + * Linux uses a custom linker script to build the vmlinux binary, it uses it to
> + * strategically place and define Linux ELF sections.  Each architecture needs
> + * to implement its own linker script, it is expected to reside in

			      ... script which is expected ...

> + * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
> + * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
> + * as well as some helpers documented in this chapter.
> + *
> + * In assembly it is common practice to use dots (``.``) in labels to avoid
> + * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
> + * name but not a C symbol. Historically then, two dots are used (``..``)
> + * have been used in linker scripts when adding program specific sections

are used .. have been used?

> + * when there are concerns to avoid clashes with compiler generated sections.

This last sentence needs simplifying.

> + */
> +
> +/**
> + * DOC: Memory protection
> + *
> + * Linux allows architectures which support memory protection features to
> + * take advantage of them by letting architectures define and enable
> + * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.

Simplify: "Architectures with memory protection features can define and
enable CONFIG_DEBUG_RODATA... "

> + * mark_rodata_ro() can be used for instance to mark specific sections as
				  , for instance, 


> + * read-only or non-executable.
> + *
> + * Linux typically follows a convention to have the .rodata ELF section follow
> + * after the .text ELF section, it does this to help architectures which
				 . It does this...

> + * support memory protection to mark both .text and .rodata as read-only in
> + * one shot.
> + *
> + * For more details refer to mark_rodata_ro().
> + */
> +
> +/**
> + * DOC: .rodata
> + *
> + * ELF section used for data which must be protected from write access.
> + */
> +
> +/**
> + * DOC: .text
> + *
> + * ELF section name used for code (functions) used during regular
> + * kernel run time.
> + */
> +
> +/**
> + * DOC: .data
> + *
> + * ELF section used for read-write data.
> + */
> +
> +/**
> + * DOC: Linux init sections
> + *
> + * These sections are used for code and data structures used during boot or
> + * module initialization. On architectures that support it (x86, x86_64), all
> + * this code is freed up by the kernel right before the fist userspace init
> + * process is called when built-in to the kernel, and if modular it is freed
> + * after module initialization. Since the code is freed so early, in theory
> + * there should be no races against freeing this code with other CPUs. Init
> + * section code and data structures should never be exported with
> + * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
> + * after bootup.
> + */
> +
> +/**
> + * DOC: .init.text
> + *
> + * ELF section for code (functions) used only during boot or driver
> + * initialization.
> + *
> + */
> +
> +/**
> + * DOC: .init.data
> + *
> + * ELF section used for data structures used only during boot or driver
> + * initialization.
> + */
> +
> +/**
> + * DOC: .init.rodata
> + *
> + * ELF section used for read-only code (functions) used only during boot
> + * or driver initialization.
> + */
> +
> +/**
> + * DOC: .initcall
> + *
> + * ELF section used for subsystem init calls. There are init levels
> + * representing different functionality in the kernel. For more details
> + * refer to __define_initcall().
> + */
> +
> +/**
> + * DOC: Linux exit sections
> + *
> + * These sections are used to declare a functions and data structures which

s/a //

> + * are only required on exit, the function or data structure will be dropped
> + * if the code declaring this section is not compiled as a module on
> + * architectures that support this (x86, x86_64). There is no special case
> + * handling for this code when built-in to the kernel.
> + */
> +
> +/**
> + * DOC: .exit.text
> + *
> + * ELF section used to for code (functions) used only during module unload.
> + */
> +
> +/**
> + * DOC: .exit.data
> + *
> + * ELF section used to for data structures used only during module
> + * unload.
> + */
> +
> +/**
> + * DOC: .exitcall.exit
> + *
> + * ELF section used for exit routines, order is important and maintained by
> + * link order.
> + */
> +
> +/**
> + * DOC: Linux references to init sections
> + *
> + * These sections are used to teach modpost to not warn about possible
> + * misuses of init section code from other sections. If you use this
> + * your use case should document why you are certain such use of init
> + * sectioned code is valid. For more details refer to ``include/linux/init.h``
> + * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
> + */
> +
> +/**
> + * DOC: .ref.text
> + *
> + * ELF section used to annotate code (functions) which has been vetteed as

vetted?

> + * valid for its reference or use of other code (functions) or data structures
> + * which are part of the init sections.
> + */
> +
> +/**
> + * DOC: .ref.data
> + *
> + * ELF section used for data structures which have been vetteed for its

ditto.

> + * reference or use of other code (functions) or data structures part of the
> + * init sections.
> + */
> +
> +/**
> + * DOC: .ref.rodata
> + *
> + * ELF section used to annotate const code (functions) const data structures
> + * which has been vetteed for its reference or use of other code (functions)

ditto.

> + * or data structures part of the init sections.
> + */
> +
> +/* Can be used on foo.S for instance */

What does that comment mean?

> +#ifndef __set_section_core_type
> +# define __set_section_core_type(___section, ___core, ___name,		\
> +				 ___level, ___flags, ___type)		\
> +	.section ___section..___core.___name.___level, ___flags, ___type

Are you sure we need 4 levels of hierarchy?

If so, we should document what all those section, core, name and level
mean and how the whole sections hierarchy is supposed to look like.

> +#endif
> +
> +#ifndef __set_section_core
> +# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
> +	.section ___section..___core.___name.___level, ___flags
> +#endif
> +
> +#ifndef __push_section_core
> +# define __push_section_core(__section, __core, __name, __level, __flags) \
> +	.pushsection __section..__core.__name.__level, __flags
> +#endif
> +
> +#ifdef __KERNEL__
> +#include <linux/stringify.h>
> +#endif
> +
> +#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
> +
> +# ifndef LINKER_SCRIPT
> +
> +#  ifndef push_section_core
> +#   define push_section_core(__section, __core, __name, __level, __flags) \
> +	 __push_section_core(__section, __core, __name,			  \
> +			     __level, __stringify(__flags))
> +#  endif
> +
> +#  ifndef set_section_core
> +#   define set_section_core(__section, __core, __name,			\
> +			    __level, __flags)				\
> +	__set_section_core(__section, __core, __name,			\
> +			   __level, __stringify(__flags))
> +#  endif
> +
> +#  ifndef set_section_core_type
> +#   define set_section_core_type(__section, __core, __name,		\
> +				 __level, __flags, __type)		\
> +	__set_section_core_type(__section, __core, __name, __level,	\
> +				__stringify(__flags), __type)
> +#  endif
> +
> +# endif /* LINKER_SCRIPT */
> +#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
> +
> +/*
> + * As per gcc's documentation a common asm separator is a new line followed
> + * by tab [0], it however seems possible to also just use a newline as its

		. It, however, seems ...

> + * the most commonly empirically observed semantic and folks seem to agree
> + * this even works on S390. In case your architecture disagrees you may
> + * override this and define your own and keep the rest of the macros.
> + *
> + * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
> + */
> +# ifndef ASM_CMD_SEP
> +#  define ASM_CMD_SEP	"\n"
> +# endif
> +
> +# ifndef set_section_core
> +#  define set_section_core(__section, __core, __name, __level, __flags)	\
> +	__stringify(__set_section_core_type(__section, __core, __name,	\
> +					    __level, __stringify(__flags))) \
> +	ASM_CMD_SEP
> +# endif
> +
> +/*
> + * Some architectures (arm, and avr32 are two examples on kprobes) seem
> + * currently explicitly specify the type [0] -- this can be any of the
> + * optional constants on ELF:
> + *
> + * @progbits - section contains data
> + * @nobits - section does not contain data (i.e., section only occupies space)
> + * @note - section contains data which is used by things other than the program
> + * @init_array - section contains an array of pointers to init functions
> + * @fini_array - section contains an array of pointers to finish functions
> + * @preinit_array - section contains an array of pointers to pre-init functions
> + *
> + * ARM requires % instead of @.
> + *
> + * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
> + * defaults are as follows:
> + *
> + * section .text    progbits  alloc   exec    nowrite  align=16
> + * section .rodata  progbits  alloc   noexec  nowrite  align=4
> + * section .lrodata progbits  alloc   noexec  nowrite  align=4
> + * section .data    progbits  alloc   noexec  write    align=4
> + * section .ldata   progbits  alloc   noexec  write    align=4
> + * section .bss     nobits    alloc   noexec  write    align=4
> + * section .lbss    nobits    alloc   noexec  write    align=4
> + * section .tdata   progbits  alloc   noexec  write    align=4    tls
> + * section .tbss    nobits    alloc   noexec  write    align=4    tls
> + * section .comment progbits  noalloc noexec  nowrite  align=1
> + * section other    progbits  alloc   noexec  nowrite  align=1
> + *
> + * gas should have sensible defaults for architectures...
> + *
> + * [0] http://www.nasm.us/doc/nasmdoc7.html
> + */
> +# ifndef set_section_core_type
> +#  define set_section_core_type(__section, __core, __name, __level,	\
> +				__flags, __type)			\
> +	__stringify(__set_section_core_type(__section, __core,		\
> +					    __name, __level,		\
> +					    __stringify(__flags),	\
> +					    __type))			\
> +	ASM_CMD_SEP
> +# endif
> +
> +# ifndef push_section_core
> +#  define push_section_core(__section, __core, __name,			\
> +			    __level, __flags)				\
> +	__stringify(__push_section_core(__section, __core,		\
> +					__name,	__level,		\
> +					__stringify(__flags)))		\
> +	ASM_CMD_SEP
> +# endif
> +
> +#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
> +#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
> diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
> index 4df64a1fc09e..b145ae8d9cbe 100644
> --- a/include/asm-generic/sections.h
> +++ b/include/asm-generic/sections.h
> @@ -1,6 +1,8 @@
>  #ifndef _ASM_GENERIC_SECTIONS_H_
>  #define _ASM_GENERIC_SECTIONS_H_
>  
> +#include <asm/section-core.h>
> +
>  /* References to section boundaries */
>  
>  #include <linux/compiler.h>
> diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
> index 0968d13b3885..483f60c451f9 100644
> --- a/include/asm-generic/vmlinux.lds.h
> +++ b/include/asm-generic/vmlinux.lds.h
> @@ -55,6 +55,7 @@
>  #endif
>  
>  #include <linux/export.h>
> +#include <asm/section-core.h>
>  
>  /* Align . to a 8 byte boundary equals to maximum function alignment. */
>  #define ALIGN_FUNCTION()  . = ALIGN(8)
> diff --git a/include/linux/init.h b/include/linux/init.h
> index 885c3e6d0f9d..116e3262332a 100644
> --- a/include/linux/init.h
> +++ b/include/linux/init.h
> @@ -130,6 +130,24 @@ int __init init_rootfs(void);
>  extern bool rodata_enabled;
>  #endif
>  #ifdef CONFIG_DEBUG_RODATA
> +/**
> + * mark_rodata_ro - implemement memory protection for ELF sections
> + *
> + * Architectures which support memory protection define a kernel configuration
> + * entry for CONFIG_DEBUG_RODATA,

That's just too many words for nothing. You can just as well say:

"Architectures which support memory protection enable CONFIG_DEBUG_RODATA and
implement mark_rodata_ro()."

> enable it in and implement mark_rodata_ro().
> + * mark_rodata_ro() should strive to adjust the .rodata and .text ELF sections
> + * with read-only memory protection to prevent modifications of these sections

"mark_rodata_ro() marks .rodata and .text section read-only..."

Simple.

> + * after bootup. It can also try to use memory protection to prevent execution
> + * on the .rodata ELF section.
> + *
> + * In order to help architectures set both .text and .rodata as read-only with
> + * memory protections in one shot Linux has typically followed the convention
> + * to have the .rodata ELF section follow the .text ELF section on the vmlinux

								   in

> + * linker script.
> + *
> + * Linux calls mark_rodata_ro() after freeing .init code and prior to calling
> + * the first init userspace process.

"first init userspace process" either say "prior to calling init" or
"prior to calling the first userspace process" but both is jambalayed
into something confusing.

> + */
>  void mark_rodata_ro(void);
>  #endif
>  
> @@ -140,25 +158,70 @@ extern bool initcall_debug;
>  #endif
>    
>  #ifndef MODULE
> +/**
> + * DOC: Initcall levels
> + *
> + * When Linux boots the kernel do_initcalls() iterates over each Linux

When Linux boots the kernel?!? You're joking, right?

Just do "During boot, do_initcalls() ..."

> + * initialization level ID and calls all routines embedded on each level ID.
> + * Prior to v2.5.2.3 Linux had only one init level onto which all init
> + * functions folded onto using __initcall(). After v2.5.2.4 Linux split up
> + * initcalls into 7 separate initcall subsection levels, each level describing
> + * different functionality part of the kernel (commit `9d6ba121b7e17085`_
> + * (v2.5.2.3 -> v2.5.2.4)). In order to remain backward compatible __initcall()
> + * calls were left mapped to device_initcall().

And why do we need all that git archeology here?

> + * Each init level consists of a dedicated ELF section, init functions are
> + * associated to an init level by linking it into the respective level's
		 with

> + * ELF section.
> + *
> + * Lower order init levels run prior to higher order init levels. Ordering
> + * inside each initcall level is determined by respective link order.

Those last two sentences are enough.

> + *
> + * .. _9d6ba121b7e17085: https://git.kernel.org/cgit/linux/kernel/git/history/history.git/commit/?id=9d6ba121b7e17085c95139233686b27a4d4c650e

That's one ugly footnote. Also, the git commit id suffices, you don't
need the URL.

> + */
>  
>  #ifndef __ASSEMBLY__
>  
> -/*
> - * initcalls are now grouped by functionality into separate
> - * subsections. Ordering inside the subsections is determined
> - * by link order. 
> - * For backwards compatibility, initcall() puts the call in 
> - * the device init subsection.
> +/**
> + * __define_initcall - wrapper for definiting init levels
		       ()

also s/definiting/defining/

Also, this is not what __define_initcall() does. It is not defining init levels.

>   *
> - * The `id' arg to __define_initcall() is needed so that multiple initcalls
> - * can point at the same handler without causing duplicate-symbol build errors.
> + * @fn: init routine
> + * @id: init level
>   *
> - * Initcalls are run by placing pointers in initcall sections that the
> - * kernel iterates at runtime. The linker can do dead code / data elimination
> - * and remove that completely, so the initcall sections have to be marked
> - * as KEEP() in the linker script.
> + * Defines a kernel initialization level. A respective linker script entry
> + * is required to ensure the init level is accounted for and to ensure symbols
> + * exist for iterating over all functions in the init level. A init level
								An

> + * represents a series of functionality in the kernel.

That sounds yucky.

An init level is a bunch of functions which are called after init_level
- 1 and before init_level + 1.

> + *
> + * Ordering within an initialization level is determined by link order, so
> + * for instance if a Makefile had::
> + *
> + *	obj-y += foo.o
> + *	obj-y += bar.o
> + *
> + * And foo.c::
> + *
> + *	subsys_initcall(foo_init);
> + *
> + * And bar.c had::
> + *
> + *	subsys_initcall(bar_init);
> + *
> + * foo_init() would be called prior to bar_init().
> + *
> + * Note that @id in __define_initcall() also enables multiple initcalls
> + * to be created using the same handler for different init levels without
> + * causing duplicate-symbol build errors.
> + *
> + * Initcalls are run by placing start symbols to initcall levels inside ELF
> + * sections, the kernel in turn uses these symbols to iterate over each init
> + * level at runtime with do_initcall_level(). The end of each init level is
> + * marked by the subsequent's symbol's start address until we reach the symbol
> + * ``__initcall_end``.

Needlessly complex, simplify.

> The linker can do dead code / data elimination and each
> + * init level start symbol could be removed completely in this process, to
									 . To   <-- new sentence

> + * avoid this each init level start symbols must be marked as 'KEEP()' in the
> + * linker script to avoid any linker optimization heuristic on initcalls.
>   */
> -
>  #define __define_initcall(fn, id) \
>  	static initcall_t __initcall_##fn##id __used \
>  	__attribute__((__section__(".initcall" #id ".init"))) = fn;
> diff --git a/include/linux/sections.h b/include/linux/sections.h
> new file mode 100644
> index 000000000000..6771c727bcd1
> --- /dev/null
> +++ b/include/linux/sections.h
> @@ -0,0 +1,87 @@
> +#ifndef _LINUX_SECTIONS_H
> +#define _LINUX_SECTIONS_H
> +/*
> + * Linux de-facto sections

Useless.

> + *
> + * 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>
> +#include <linux/export.h>
> +
> +#ifndef __ASSEMBLY__
> +
> +/**
> + * DOC: Introduction
> + *
> + * Linux defines a set of common helpers which can be used to against its use
						      ^^^^^^^^^^^^^^^^^^^^^^^^^^

??

> + * of standard or custom Linux sections, this section is dedicated to these

this section is talking about sections, that's too much.

> + * helpers.
> + */
> +
> +/**
> + * LINUX_SECTION_ALIGNMENT - get section alignment
> + *
> + * @name: section name
> + *
> + * Gives you the alignment for the section.
> + */
> +#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))

Eeww, too long and it is a getter but doesn't have "GET" in its name.

How about GET_SECTION_ALIGN() ?

And what's with the "LINUX_" prefix - that's like useless use of screen
real estate.

> +
> +/**
> + * LINUX_SECTION_START - get address of start of section

GET_SECTION_START()	-  get address of section start

> + *
> + * @name: section name
> + *
> + * This gives you the start address of the section.
> + * This should give you the address of the first entry.

Huh?

> + *
> + */
> +#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)

Ditto.

> +
> +/**
> + * LINUX_SECTION_END - get address of end of the section
> + *
> + * @name: section name
> + *
> + * This gives you the end address of the section.
> + * This should give you the address of the end of the
> + * section. This will match the start address if the
> + * section is empty.
> + */
> +#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
> +
> +/**
> + * DECLARE_LINUX_SECTION - Declares a custom Linux section

DECLARE_SECTION() is perfectly fine IMO.

> + *
> + * @type: type of custom Linux section
> + * @name: custom section name
> + *
> + * Declares a read-write custom Linux section
> + */
> +#define DECLARE_LINUX_SECTION(type, name)				\
> +	 extern type VMLINUX_SYMBOL(name)[], \
> +		     VMLINUX_SYMBOL(name##__end)[]
> +
> +/**
> + * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section

DECLARE_SECTION_RO()

> + *
> + * @type: type of custom Linux section
> + * @name: custom section name
> + *
> + * Declares a read-only custom Linux section
> + */
> +#define DECLARE_LINUX_SECTION_RO(type, name)				\
> +	 extern const type VMLINUX_SYMBOL(name)[],			\
> +			   VMLINUX_SYMBOL(name##__end)[]
> +
> +#define __SECTION_CORE(section, core, name, level)			\
> +	#section ".." #core "." #name "." #level
> +
> +#endif /* __ASSEMBLY__ */
> +
> +#endif /* _LINUX_SECTIONS_H */
> -- 

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v6 01/14] generic-sections: add section core helpers
@ 2017-01-16 14:46           ` Borislav Petkov
  0 siblings, 0 replies; 480+ messages in thread
From: Borislav Petkov @ 2017-01-16 14:46 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, gregkh, rusty, gnomes, alan, dwmw2,
	arnd, ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="windows-1254", Size: 33890 bytes --]

On Mon, Jan 09, 2017 at 06:58:19AM -0800, Luis R. Rodriguez wrote:
> Linux makes extensive use of custom ELF header sections,
> documentation for these are well scatterred. Unify this

			  is

> documentation in a central place and provide helpers to
> build custom Linux sections.

This patch contains at least three logical changes and needs splitting:

* unify documentation
* adding helpers
* MAINTAINERS addition

Documentation and MAINTAINERS changes should go last in the patchset.

Accordingly, the huuge commit message below should be spread around
those three patches.

> 
> This also generalizes sections code to enable avoiding
> modifying the linker scripts when we want to add new
> custom Linux sections. In order to make this generally
> useful we need to ensure all architectures can make use of
> core section helpers but that they can also override should
> this be needed. Instead of relying on section.h this adds
> a sections-core.h since this will be targetted to be safe
> to be used on asm code, linker scripts and C code.
> 
> v5:
> 
> o Huge documentation revamp based on a careful review of the ELF
>   specifications. Includes documentation now also about usage of
>   two dots (..) when prefixing ELF program specific sections.
> 
> o Replace macros for sections names in favor of just using
>   the section names explicitly in the linker script. This is
>   perhaps more work to grep but this is what folks seem to
>   currently prefer.
> 
> o Fix .text and .rodata documentation to explain memory protection
>   strategies which architectures can embrace upon initialization
>   (documents CONFIG_DEBUG_RODATA and mark_rodata_ro())
> 
> o Skip the 'Linux section ordering' documentation section, we'll instead
>   add this on subsequent patch which will expand on it considerably
> 
> o Dropped tree on MAINTAINERS -- as per discussions with Arnd, hpa and
>   Josh, its easier to just let changes for sections go in through the
>   respective tree that needs the changes.
> 
> o Fix typos on documentation
> 
> o Dropped SECTION_ALL(), __SECTION_CORE(), SECTION_CORE_ALL() macros
>   since we are favoring using explicit section names. These are
>   useless if we are being explicit.
> 
> o Drop LINUX_SECTION_SIZE(), LINUX_SECTION_EMPTY() in favor of having
>   section ranges and linker tables define their own, to avoid confusion
>   and make code more readable.
> 
> o Add __define_initcall() documentation and a small section describing
>   our current initcall levels. This should help also clarify what was
>   meant about keeping backward compatiblity.
> 
> v4:
> 
> o Port to shiny new sphinx documentation format

This looks like a 4th patch ontop of the unifying documentation one.

> 
> o fix a unicore32 build, turns out this actually fixes unicore32
>   defconfig builds which were failing for a long while. unicore32
>   does not seem to grok well the type passed on a section declaration,
>   this ignores it.
> 
> o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
>   this was causing final linker issues with blackfin -- this is
>   a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
>   being metatag. metatag is not supported on 0-day so I cannot confirm
>   compilation there.

...

> +++ b/Documentation/sections/background.rst
> @@ -0,0 +1,105 @@
> +===========
> +ELF section background
> +===========
> +
> +About
> +==> +
> +The purpose of this chapter is to help those not familiar with ELF to brush up
> +the latest ELF specifications in order to help understand how Linux uses and
> +defines its own ELF sections.
> +
> +Standardized ELF
> +========
> +
> +The first publication documenting ELF was UNIX System Laboratories' (USL)
> +*System V Release 4 Application Binary Interface* (`SRV4 ABI`_) specification.
> +Originally ELF was only a small part of the SRV4 ABI, with time however new
> +specifications only put focus on ELF, such was the case of the *TIS Portable
> +Formats Specification version 1.2* (`TIS 1.2`_). As of TIS 1.2, ELF was
> +supplemented with processor specific ELF addendums, available on the *Linux
> +Foundation referenced specification page* (`LF ref page`_). The latest ELF
> +specification is the *System V Application Binary Interface - DRAFT - 24 April
> +2001* (`gabi4`_).
> +
> +.. _SRV4 ABI: http://www.sco.com/developers/devspecs/gabi41.pdf
> +.. _TIS 1.2: https://refspecs.linuxbase.org/elf/elf.pdf
> +.. _LF ref page: https://refspecs.linuxbase.org/
> +.. _gabi4: https://refspecs.linuxbase.org/elf/gabi4+/contents.html
> +

A pointer to the wikipedia page would suffice instead of us repeating
ELF history here.

> +ELF views on Linux
> +=========
> +
> +There are two views which can be used for inspecting data in an ELF file, a
> +Linking view, and an Execution view. A Section Header Table enables one to
> +describe an object using the Linking view while a Program Header Table enables
> +one to describe an object using the Execution view. The views are not mutually
> +exclusive. For intance, vmlinux can be viewed under both views, ``readelf -S

s/intance/instance/

> +vmlinux`` for the Linking view, and ``readelf -l vmlinux`` for the Execution
> +view.  In Linux only the vmlinux file will have an Execution view, even modules
> +lack an Execution view given that vmlinux is the only file that describes how
> +the the kernel runs from the start.  All other Linux kernel object files have

s/the //

> +an available Linking view.

s/n available// - "have a Linking view" is fine.

> +
> +Under the Linking view, the Section Header Table describes all available
> +sections. The Section Header Table is an array of ELF section header data
> +structures. If on a 32-bit system this is ``struct elf32_shd``, if on a 64-bit
> +this is ``struct elf64_shdr``.

"If on ... if on" doesn't work as a sentence.

> Sections are only visible on object files that

s/on/in/

> +have a Linking view, since all Linux kernel files have Linking view, all kernel
> +objects have ELF sections.

Btw, that last sentence is kinda funny and not really needed. Or do you
wanna say that everything-code is in a section?

> +
> +Limitations on ELF sections

ELF sections limitations

> +=============> +
> +We provide a summary on the limitations of ELF sections.

Kill that sentence.

> Refer to the public
> +ELF specifications for details. Note that 64-bit limitations may depend
> +on processor specific section attributes to be used, refer to your processsor

"processsor" - the 's' button stuck? :-)

> +specification if unsure.

Better yet, kill that whole paragraph.

> +
> +Its worth ellaborating on the limitations on the name of an ELF section:

"elaborating"

> +ELF section names are stored as strings as per the ELF specification, and
> +as can be expected, these don't have explicit limitations. The implicit
> +limitation then depends on the size of an ELF object file and ELF section.
> +
> +If using really large kernels or objects with large amounts of sections one
> +would still need to be sure that ELF loader in charge of loading the Linux
> +kernel is properly updated to handle coping with the latest ELF extensions.
> +
> +   .. flat-table:: Limitations on ELF Sections
> +
> +      * - Section attribute
> +        - 32-bit
> +        - 64-bit
> +
> +      * - ELF section name
> +        - Size of an ELF section
> +        - Size of an ELF section
> +
> +      * - Size of an ELF section
> +        - 4 GiB
> +        - 16 EiB
> +
> +      * - Max number of sections in an object file
> +        - 4 GiEntries (4294967296)
> +        - 16 EiEntries (18446744073709551616)
> +
> +Program specific ELF sections

Program-specific

> +==============> +
> +The ELF specification allows for a section type to be specified as
> +*Program specific section*, defined as ``SHT_PROGBITS``. This sections type

								 section

> +enables programs to customize sections for their own use. In assembly this
									^
									is

> +specified ``@progbits`` on most architectures, on ARM this is ``%progbits``.
	     ^		  ^

	     with the	  flag				s/this is/it is called/

> +
> +``SHT_PROGBITS`` is used by Linux for defining and using Linux ELF sections.
> +
> +Special ELF Sections
> +==========
> +
> +The ELF specification defines *Special ELF Sections* on chapter 4 (`gabi4
> +ch4`_). These are defined as sections which hold program and control
> +information. Of these sections, a few have the section type as
> +``SHT_PROGBITS``. This enables Linux to *further customize* use of the section
> +beyond what the ELF specification suggests.
> +
> +.. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
> diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
> new file mode 100644
> index 000000000000..faa1c57595e1
> --- /dev/null
> +++ b/Documentation/sections/conf.py
> @@ -0,0 +1,4 @@
> +# -*- coding: utf-8; mode: python -*-
> +
> +project = 'Linux Kernel ELF sections'
> +html_search_language = 'en'
> diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
> new file mode 100644
> index 000000000000..f37511ef05e7
> --- /dev/null
> +++ b/Documentation/sections/index.rst
> @@ -0,0 +1,17 @@
> +============> +Linux Kernel ELF sections
> +============> +
> +This book documents the different ELF sections used on the Linux kernel.

							in

> +We start off by providing references to how ELF was standardized, references
> +to the standards on ELF sections, review limitations of ELF sections, and
> +finally how Linux uses ELF sections in the Linux kernel. Certain important
> +Linux ELF sections are documented carefully: we describe the goal of the
> +ELF section, and address concurrency considerations when applicable. A few
> +common a set of Linux helpers for ELF sections are also documented.

s/few common a //

> +
> +.. toctree::
> +   :maxdepth: 4
> +
> +   background
> +   section-core

...

> diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
> new file mode 100644
> index 000000000000..0b9c68429a1a
> --- /dev/null
> +++ b/arch/unicore32/include/asm/section-core.h
> @@ -0,0 +1,19 @@
> +#ifndef __UNICORE_SECTION_CORE_ASM_H__
> +#define __UNICORE_SECTION_CORE_ASM_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/.

Isn't all kernel code GPLv2?

> + */
> +
> +/* Unicore32 has known to not work properly with the type set, so ignore it */
> +
> +#define __set_section_core_type(___section, ___core, ___name,		\
> +				___level, ___flags, ___type)		\
> +	.section ___section..___core.___name.___level, ___flags
> +
> +#include <asm-generic/section-core.h>
> +
> +#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
> diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
> index 2b892e2313a9..af975f21eeee 100644
> --- a/arch/x86/include/asm/Kbuild
> +++ b/arch/x86/include/asm/Kbuild
> @@ -12,3 +12,4 @@ generic-y += dma-contiguous.h
>  generic-y += early_ioremap.h
>  generic-y += mcs_spinlock.h
>  generic-y += mm-arch-hooks.h
> +generic-y += section-core.h
> diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
> index b7fbaa56b51a..7879c31e66a7 100644
> --- a/arch/xtensa/include/asm/Kbuild
> +++ b/arch/xtensa/include/asm/Kbuild
> @@ -32,3 +32,4 @@ generic-y += topology.h
>  generic-y += trace_clock.h
>  generic-y += word-at-a-time.h
>  generic-y += xor.h
> +generic-y += section-core.h
> diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
> new file mode 100644
> index 000000000000..bb16befc4251
> --- /dev/null
> +++ b/include/asm-generic/section-core.h
> @@ -0,0 +1,307 @@
> +#ifndef _ASM_GENERIC_SECTION_CORE_H_
> +#define _ASM_GENERIC_SECTION_CORE_H_
> +/*
> + * Linux section core definitions
> + *
> + * 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/.

Ditto.

> + */
> +
> +/**
> + * DOC: Linux ELF program specific sections
> + *
> + * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and definition
							     ^^^^^^^^^^^^^^^^^^^^^^^^

							     needs rewording

> of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
> + * sections. This chaper is dedicated to documenting Linux program specific

"chapter"

Please spellcheck the whole patchset before next submission.

> + * sections and helpers available to make use of these easier to implement and
> + * use.

Huh, come again? This sentence is funny.

> + *
> + * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
> + */
> +
> +/**
> + * DOC: Linux linker script
> + *
> + * Linux uses a custom linker script to build the vmlinux binary, it uses it to
> + * strategically place and define Linux ELF sections.  Each architecture needs
> + * to implement its own linker script, it is expected to reside in

			      ... script which is expected ...

> + * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
> + * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
> + * as well as some helpers documented in this chapter.
> + *
> + * In assembly it is common practice to use dots (``.``) in labels to avoid
> + * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
> + * name but not a C symbol. Historically then, two dots are used (``..``)
> + * have been used in linker scripts when adding program specific sections

are used .. have been used?

> + * when there are concerns to avoid clashes with compiler generated sections.

This last sentence needs simplifying.

> + */
> +
> +/**
> + * DOC: Memory protection
> + *
> + * Linux allows architectures which support memory protection features to
> + * take advantage of them by letting architectures define and enable
> + * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.

Simplify: "Architectures with memory protection features can define and
enable CONFIG_DEBUG_RODATA... "

> + * mark_rodata_ro() can be used for instance to mark specific sections as
				  , for instance, 


> + * read-only or non-executable.
> + *
> + * Linux typically follows a convention to have the .rodata ELF section follow
> + * after the .text ELF section, it does this to help architectures which
				 . It does this...

> + * support memory protection to mark both .text and .rodata as read-only in
> + * one shot.
> + *
> + * For more details refer to mark_rodata_ro().
> + */
> +
> +/**
> + * DOC: .rodata
> + *
> + * ELF section used for data which must be protected from write access.
> + */
> +
> +/**
> + * DOC: .text
> + *
> + * ELF section name used for code (functions) used during regular
> + * kernel run time.
> + */
> +
> +/**
> + * DOC: .data
> + *
> + * ELF section used for read-write data.
> + */
> +
> +/**
> + * DOC: Linux init sections
> + *
> + * These sections are used for code and data structures used during boot or
> + * module initialization. On architectures that support it (x86, x86_64), all
> + * this code is freed up by the kernel right before the fist userspace init
> + * process is called when built-in to the kernel, and if modular it is freed
> + * after module initialization. Since the code is freed so early, in theory
> + * there should be no races against freeing this code with other CPUs. Init
> + * section code and data structures should never be exported with
> + * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
> + * after bootup.
> + */
> +
> +/**
> + * DOC: .init.text
> + *
> + * ELF section for code (functions) used only during boot or driver
> + * initialization.
> + *
> + */
> +
> +/**
> + * DOC: .init.data
> + *
> + * ELF section used for data structures used only during boot or driver
> + * initialization.
> + */
> +
> +/**
> + * DOC: .init.rodata
> + *
> + * ELF section used for read-only code (functions) used only during boot
> + * or driver initialization.
> + */
> +
> +/**
> + * DOC: .initcall
> + *
> + * ELF section used for subsystem init calls. There are init levels
> + * representing different functionality in the kernel. For more details
> + * refer to __define_initcall().
> + */
> +
> +/**
> + * DOC: Linux exit sections
> + *
> + * These sections are used to declare a functions and data structures which

s/a //

> + * are only required on exit, the function or data structure will be dropped
> + * if the code declaring this section is not compiled as a module on
> + * architectures that support this (x86, x86_64). There is no special case
> + * handling for this code when built-in to the kernel.
> + */
> +
> +/**
> + * DOC: .exit.text
> + *
> + * ELF section used to for code (functions) used only during module unload.
> + */
> +
> +/**
> + * DOC: .exit.data
> + *
> + * ELF section used to for data structures used only during module
> + * unload.
> + */
> +
> +/**
> + * DOC: .exitcall.exit
> + *
> + * ELF section used for exit routines, order is important and maintained by
> + * link order.
> + */
> +
> +/**
> + * DOC: Linux references to init sections
> + *
> + * These sections are used to teach modpost to not warn about possible
> + * misuses of init section code from other sections. If you use this
> + * your use case should document why you are certain such use of init
> + * sectioned code is valid. For more details refer to ``include/linux/init.h``
> + * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
> + */
> +
> +/**
> + * DOC: .ref.text
> + *
> + * ELF section used to annotate code (functions) which has been vetteed as

vetted?

> + * valid for its reference or use of other code (functions) or data structures
> + * which are part of the init sections.
> + */
> +
> +/**
> + * DOC: .ref.data
> + *
> + * ELF section used for data structures which have been vetteed for its

ditto.

> + * reference or use of other code (functions) or data structures part of the
> + * init sections.
> + */
> +
> +/**
> + * DOC: .ref.rodata
> + *
> + * ELF section used to annotate const code (functions) const data structures
> + * which has been vetteed for its reference or use of other code (functions)

ditto.

> + * or data structures part of the init sections.
> + */
> +
> +/* Can be used on foo.S for instance */

What does that comment mean?

> +#ifndef __set_section_core_type
> +# define __set_section_core_type(___section, ___core, ___name,		\
> +				 ___level, ___flags, ___type)		\
> +	.section ___section..___core.___name.___level, ___flags, ___type

Are you sure we need 4 levels of hierarchy?

If so, we should document what all those section, core, name and level
mean and how the whole sections hierarchy is supposed to look like.

> +#endif
> +
> +#ifndef __set_section_core
> +# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
> +	.section ___section..___core.___name.___level, ___flags
> +#endif
> +
> +#ifndef __push_section_core
> +# define __push_section_core(__section, __core, __name, __level, __flags) \
> +	.pushsection __section..__core.__name.__level, __flags
> +#endif
> +
> +#ifdef __KERNEL__
> +#include <linux/stringify.h>
> +#endif
> +
> +#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
> +
> +# ifndef LINKER_SCRIPT
> +
> +#  ifndef push_section_core
> +#   define push_section_core(__section, __core, __name, __level, __flags) \
> +	 __push_section_core(__section, __core, __name,			  \
> +			     __level, __stringify(__flags))
> +#  endif
> +
> +#  ifndef set_section_core
> +#   define set_section_core(__section, __core, __name,			\
> +			    __level, __flags)				\
> +	__set_section_core(__section, __core, __name,			\
> +			   __level, __stringify(__flags))
> +#  endif
> +
> +#  ifndef set_section_core_type
> +#   define set_section_core_type(__section, __core, __name,		\
> +				 __level, __flags, __type)		\
> +	__set_section_core_type(__section, __core, __name, __level,	\
> +				__stringify(__flags), __type)
> +#  endif
> +
> +# endif /* LINKER_SCRIPT */
> +#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
> +
> +/*
> + * As per gcc's documentation a common asm separator is a new line followed
> + * by tab [0], it however seems possible to also just use a newline as its

		. It, however, seems ...

> + * the most commonly empirically observed semantic and folks seem to agree
> + * this even works on S390. In case your architecture disagrees you may
> + * override this and define your own and keep the rest of the macros.
> + *
> + * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
> + */
> +# ifndef ASM_CMD_SEP
> +#  define ASM_CMD_SEP	"\n"
> +# endif
> +
> +# ifndef set_section_core
> +#  define set_section_core(__section, __core, __name, __level, __flags)	\
> +	__stringify(__set_section_core_type(__section, __core, __name,	\
> +					    __level, __stringify(__flags))) \
> +	ASM_CMD_SEP
> +# endif
> +
> +/*
> + * Some architectures (arm, and avr32 are two examples on kprobes) seem
> + * currently explicitly specify the type [0] -- this can be any of the
> + * optional constants on ELF:
> + *
> + * @progbits - section contains data
> + * @nobits - section does not contain data (i.e., section only occupies space)
> + * @note - section contains data which is used by things other than the program
> + * @init_array - section contains an array of pointers to init functions
> + * @fini_array - section contains an array of pointers to finish functions
> + * @preinit_array - section contains an array of pointers to pre-init functions
> + *
> + * ARM requires % instead of @.
> + *
> + * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
> + * defaults are as follows:
> + *
> + * section .text    progbits  alloc   exec    nowrite  align\x16
> + * section .rodata  progbits  alloc   noexec  nowrite  align=4
> + * section .lrodata progbits  alloc   noexec  nowrite  align=4
> + * section .data    progbits  alloc   noexec  write    align=4
> + * section .ldata   progbits  alloc   noexec  write    align=4
> + * section .bss     nobits    alloc   noexec  write    align=4
> + * section .lbss    nobits    alloc   noexec  write    align=4
> + * section .tdata   progbits  alloc   noexec  write    align=4    tls
> + * section .tbss    nobits    alloc   noexec  write    align=4    tls
> + * section .comment progbits  noalloc noexec  nowrite  align=1
> + * section other    progbits  alloc   noexec  nowrite  align=1
> + *
> + * gas should have sensible defaults for architectures...
> + *
> + * [0] http://www.nasm.us/doc/nasmdoc7.html
> + */
> +# ifndef set_section_core_type
> +#  define set_section_core_type(__section, __core, __name, __level,	\
> +				__flags, __type)			\
> +	__stringify(__set_section_core_type(__section, __core,		\
> +					    __name, __level,		\
> +					    __stringify(__flags),	\
> +					    __type))			\
> +	ASM_CMD_SEP
> +# endif
> +
> +# ifndef push_section_core
> +#  define push_section_core(__section, __core, __name,			\
> +			    __level, __flags)				\
> +	__stringify(__push_section_core(__section, __core,		\
> +					__name,	__level,		\
> +					__stringify(__flags)))		\
> +	ASM_CMD_SEP
> +# endif
> +
> +#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
> +#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
> diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
> index 4df64a1fc09e..b145ae8d9cbe 100644
> --- a/include/asm-generic/sections.h
> +++ b/include/asm-generic/sections.h
> @@ -1,6 +1,8 @@
>  #ifndef _ASM_GENERIC_SECTIONS_H_
>  #define _ASM_GENERIC_SECTIONS_H_
>  
> +#include <asm/section-core.h>
> +
>  /* References to section boundaries */
>  
>  #include <linux/compiler.h>
> diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
> index 0968d13b3885..483f60c451f9 100644
> --- a/include/asm-generic/vmlinux.lds.h
> +++ b/include/asm-generic/vmlinux.lds.h
> @@ -55,6 +55,7 @@
>  #endif
>  
>  #include <linux/export.h>
> +#include <asm/section-core.h>
>  
>  /* Align . to a 8 byte boundary equals to maximum function alignment. */
>  #define ALIGN_FUNCTION()  . = ALIGN(8)
> diff --git a/include/linux/init.h b/include/linux/init.h
> index 885c3e6d0f9d..116e3262332a 100644
> --- a/include/linux/init.h
> +++ b/include/linux/init.h
> @@ -130,6 +130,24 @@ int __init init_rootfs(void);
>  extern bool rodata_enabled;
>  #endif
>  #ifdef CONFIG_DEBUG_RODATA
> +/**
> + * mark_rodata_ro - implemement memory protection for ELF sections
> + *
> + * Architectures which support memory protection define a kernel configuration
> + * entry for CONFIG_DEBUG_RODATA,

That's just too many words for nothing. You can just as well say:

"Architectures which support memory protection enable CONFIG_DEBUG_RODATA and
implement mark_rodata_ro()."

> enable it in and implement mark_rodata_ro().
> + * mark_rodata_ro() should strive to adjust the .rodata and .text ELF sections
> + * with read-only memory protection to prevent modifications of these sections

"mark_rodata_ro() marks .rodata and .text section read-only..."

Simple.

> + * after bootup. It can also try to use memory protection to prevent execution
> + * on the .rodata ELF section.
> + *
> + * In order to help architectures set both .text and .rodata as read-only with
> + * memory protections in one shot Linux has typically followed the convention
> + * to have the .rodata ELF section follow the .text ELF section on the vmlinux

								   in

> + * linker script.
> + *
> + * Linux calls mark_rodata_ro() after freeing .init code and prior to calling
> + * the first init userspace process.

"first init userspace process" either say "prior to calling init" or
"prior to calling the first userspace process" but both is jambalayed
into something confusing.

> + */
>  void mark_rodata_ro(void);
>  #endif
>  
> @@ -140,25 +158,70 @@ extern bool initcall_debug;
>  #endif
>    
>  #ifndef MODULE
> +/**
> + * DOC: Initcall levels
> + *
> + * When Linux boots the kernel do_initcalls() iterates over each Linux

When Linux boots the kernel?!? You're joking, right?

Just do "During boot, do_initcalls() ..."

> + * initialization level ID and calls all routines embedded on each level ID.
> + * Prior to v2.5.2.3 Linux had only one init level onto which all init
> + * functions folded onto using __initcall(). After v2.5.2.4 Linux split up
> + * initcalls into 7 separate initcall subsection levels, each level describing
> + * different functionality part of the kernel (commit `9d6ba121b7e17085`_
> + * (v2.5.2.3 -> v2.5.2.4)). In order to remain backward compatible __initcall()
> + * calls were left mapped to device_initcall().

And why do we need all that git archeology here?

> + * Each init level consists of a dedicated ELF section, init functions are
> + * associated to an init level by linking it into the respective level's
		 with

> + * ELF section.
> + *
> + * Lower order init levels run prior to higher order init levels. Ordering
> + * inside each initcall level is determined by respective link order.

Those last two sentences are enough.

> + *
> + * .. _9d6ba121b7e17085: https://git.kernel.org/cgit/linux/kernel/git/history/history.git/commit/?id6ba121b7e17085c95139233686b27a4d4c650e

That's one ugly footnote. Also, the git commit id suffices, you don't
need the URL.

> + */
>  
>  #ifndef __ASSEMBLY__
>  
> -/*
> - * initcalls are now grouped by functionality into separate
> - * subsections. Ordering inside the subsections is determined
> - * by link order. 
> - * For backwards compatibility, initcall() puts the call in 
> - * the device init subsection.
> +/**
> + * __define_initcall - wrapper for definiting init levels
		       ()

also s/definiting/defining/

Also, this is not what __define_initcall() does. It is not defining init levels.

>   *
> - * The `id' arg to __define_initcall() is needed so that multiple initcalls
> - * can point at the same handler without causing duplicate-symbol build errors.
> + * @fn: init routine
> + * @id: init level
>   *
> - * Initcalls are run by placing pointers in initcall sections that the
> - * kernel iterates at runtime. The linker can do dead code / data elimination
> - * and remove that completely, so the initcall sections have to be marked
> - * as KEEP() in the linker script.
> + * Defines a kernel initialization level. A respective linker script entry
> + * is required to ensure the init level is accounted for and to ensure symbols
> + * exist for iterating over all functions in the init level. A init level
								An

> + * represents a series of functionality in the kernel.

That sounds yucky.

An init level is a bunch of functions which are called after init_level
- 1 and before init_level + 1.

> + *
> + * Ordering within an initialization level is determined by link order, so
> + * for instance if a Makefile had::
> + *
> + *	obj-y += foo.o
> + *	obj-y += bar.o
> + *
> + * And foo.c::
> + *
> + *	subsys_initcall(foo_init);
> + *
> + * And bar.c had::
> + *
> + *	subsys_initcall(bar_init);
> + *
> + * foo_init() would be called prior to bar_init().
> + *
> + * Note that @id in __define_initcall() also enables multiple initcalls
> + * to be created using the same handler for different init levels without
> + * causing duplicate-symbol build errors.
> + *
> + * Initcalls are run by placing start symbols to initcall levels inside ELF
> + * sections, the kernel in turn uses these symbols to iterate over each init
> + * level at runtime with do_initcall_level(). The end of each init level is
> + * marked by the subsequent's symbol's start address until we reach the symbol
> + * ``__initcall_end``.

Needlessly complex, simplify.

> The linker can do dead code / data elimination and each
> + * init level start symbol could be removed completely in this process, to
									 . To   <-- new sentence

> + * avoid this each init level start symbols must be marked as 'KEEP()' in the
> + * linker script to avoid any linker optimization heuristic on initcalls.
>   */
> -
>  #define __define_initcall(fn, id) \
>  	static initcall_t __initcall_##fn##id __used \
>  	__attribute__((__section__(".initcall" #id ".init"))) = fn;
> diff --git a/include/linux/sections.h b/include/linux/sections.h
> new file mode 100644
> index 000000000000..6771c727bcd1
> --- /dev/null
> +++ b/include/linux/sections.h
> @@ -0,0 +1,87 @@
> +#ifndef _LINUX_SECTIONS_H
> +#define _LINUX_SECTIONS_H
> +/*
> + * Linux de-facto sections

Useless.

> + *
> + * 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>
> +#include <linux/export.h>
> +
> +#ifndef __ASSEMBLY__
> +
> +/**
> + * DOC: Introduction
> + *
> + * Linux defines a set of common helpers which can be used to against its use
						      ^^^^^^^^^^^^^^^^^^^^^^^^^^

??

> + * of standard or custom Linux sections, this section is dedicated to these

this section is talking about sections, that's too much.

> + * helpers.
> + */
> +
> +/**
> + * LINUX_SECTION_ALIGNMENT - get section alignment
> + *
> + * @name: section name
> + *
> + * Gives you the alignment for the section.
> + */
> +#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))

Eeww, too long and it is a getter but doesn't have "GET" in its name.

How about GET_SECTION_ALIGN() ?

And what's with the "LINUX_" prefix - that's like useless use of screen
real estate.

> +
> +/**
> + * LINUX_SECTION_START - get address of start of section

GET_SECTION_START()	-  get address of section start

> + *
> + * @name: section name
> + *
> + * This gives you the start address of the section.
> + * This should give you the address of the first entry.

Huh?

> + *
> + */
> +#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)

Ditto.

> +
> +/**
> + * LINUX_SECTION_END - get address of end of the section
> + *
> + * @name: section name
> + *
> + * This gives you the end address of the section.
> + * This should give you the address of the end of the
> + * section. This will match the start address if the
> + * section is empty.
> + */
> +#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
> +
> +/**
> + * DECLARE_LINUX_SECTION - Declares a custom Linux section

DECLARE_SECTION() is perfectly fine IMO.

> + *
> + * @type: type of custom Linux section
> + * @name: custom section name
> + *
> + * Declares a read-write custom Linux section
> + */
> +#define DECLARE_LINUX_SECTION(type, name)				\
> +	 extern type VMLINUX_SYMBOL(name)[], \
> +		     VMLINUX_SYMBOL(name##__end)[]
> +
> +/**
> + * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section

DECLARE_SECTION_RO()

> + *
> + * @type: type of custom Linux section
> + * @name: custom section name
> + *
> + * Declares a read-only custom Linux section
> + */
> +#define DECLARE_LINUX_SECTION_RO(type, name)				\
> +	 extern const type VMLINUX_SYMBOL(name)[],			\
> +			   VMLINUX_SYMBOL(name##__end)[]
> +
> +#define __SECTION_CORE(section, core, name, level)			\
> +	#section ".." #core "." #name "." #level
> +
> +#endif /* __ASSEMBLY__ */
> +
> +#endif /* _LINUX_SECTIONS_H */
> -- 

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.
--
To unsubscribe from this list: send the line "unsubscribe sparclinux" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v6 01/14] generic-sections: add section core helpers
@ 2017-01-16 14:46           ` Borislav Petkov
  0 siblings, 0 replies; 480+ messages in thread
From: Borislav Petkov @ 2017-01-16 14:46 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, gregkh, rusty, gnomes, alan, dwmw2,
	arnd, ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="windows-1252", Size: 34723 bytes --]

On Mon, Jan 09, 2017 at 06:58:19AM -0800, Luis R. Rodriguez wrote:
> Linux makes extensive use of custom ELF header sections,
> documentation for these are well scatterred. Unify this

			  is

> documentation in a central place and provide helpers to
> build custom Linux sections.

This patch contains at least three logical changes and needs splitting:

* unify documentation
* adding helpers
* MAINTAINERS addition

Documentation and MAINTAINERS changes should go last in the patchset.

Accordingly, the huuge commit message below should be spread around
those three patches.

> 
> This also generalizes sections code to enable avoiding
> modifying the linker scripts when we want to add new
> custom Linux sections. In order to make this generally
> useful we need to ensure all architectures can make use of
> core section helpers but that they can also override should
> this be needed. Instead of relying on section.h this adds
> a sections-core.h since this will be targetted to be safe
> to be used on asm code, linker scripts and C code.
> 
> v5:
> 
> o Huge documentation revamp based on a careful review of the ELF
>   specifications. Includes documentation now also about usage of
>   two dots (..) when prefixing ELF program specific sections.
> 
> o Replace macros for sections names in favor of just using
>   the section names explicitly in the linker script. This is
>   perhaps more work to grep but this is what folks seem to
>   currently prefer.
> 
> o Fix .text and .rodata documentation to explain memory protection
>   strategies which architectures can embrace upon initialization
>   (documents CONFIG_DEBUG_RODATA and mark_rodata_ro())
> 
> o Skip the 'Linux section ordering' documentation section, we'll instead
>   add this on subsequent patch which will expand on it considerably
> 
> o Dropped tree on MAINTAINERS -- as per discussions with Arnd, hpa and
>   Josh, its easier to just let changes for sections go in through the
>   respective tree that needs the changes.
> 
> o Fix typos on documentation
> 
> o Dropped SECTION_ALL(), __SECTION_CORE(), SECTION_CORE_ALL() macros
>   since we are favoring using explicit section names. These are
>   useless if we are being explicit.
> 
> o Drop LINUX_SECTION_SIZE(), LINUX_SECTION_EMPTY() in favor of having
>   section ranges and linker tables define their own, to avoid confusion
>   and make code more readable.
> 
> o Add __define_initcall() documentation and a small section describing
>   our current initcall levels. This should help also clarify what was
>   meant about keeping backward compatiblity.
> 
> v4:
> 
> o Port to shiny new sphinx documentation format

This looks like a 4th patch ontop of the unifying documentation one.

> 
> o fix a unicore32 build, turns out this actually fixes unicore32
>   defconfig builds which were failing for a long while. unicore32
>   does not seem to grok well the type passed on a section declaration,
>   this ignores it.
> 
> o Use VMLINUX_SYMBOL() in more user symbols (extern C code), not doing
>   this was causing final linker issues with blackfin -- this is
>   a CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX=y architecture. The other one
>   being metatag. metatag is not supported on 0-day so I cannot confirm
>   compilation there.

...

> +++ b/Documentation/sections/background.rst
> @@ -0,0 +1,105 @@
> +===========
> +ELF section background
> +===========
> +
> +About
> +==> +
> +The purpose of this chapter is to help those not familiar with ELF to brush up
> +the latest ELF specifications in order to help understand how Linux uses and
> +defines its own ELF sections.
> +
> +Standardized ELF
> +========
> +
> +The first publication documenting ELF was UNIX System Laboratories' (USL)
> +*System V Release 4 Application Binary Interface* (`SRV4 ABI`_) specification.
> +Originally ELF was only a small part of the SRV4 ABI, with time however new
> +specifications only put focus on ELF, such was the case of the *TIS Portable
> +Formats Specification version 1.2* (`TIS 1.2`_). As of TIS 1.2, ELF was
> +supplemented with processor specific ELF addendums, available on the *Linux
> +Foundation referenced specification page* (`LF ref page`_). The latest ELF
> +specification is the *System V Application Binary Interface - DRAFT - 24 April
> +2001* (`gabi4`_).
> +
> +.. _SRV4 ABI: http://www.sco.com/developers/devspecs/gabi41.pdf
> +.. _TIS 1.2: https://refspecs.linuxbase.org/elf/elf.pdf
> +.. _LF ref page: https://refspecs.linuxbase.org/
> +.. _gabi4: https://refspecs.linuxbase.org/elf/gabi4+/contents.html
> +

A pointer to the wikipedia page would suffice instead of us repeating
ELF history here.

> +ELF views on Linux
> +=========
> +
> +There are two views which can be used for inspecting data in an ELF file, a
> +Linking view, and an Execution view. A Section Header Table enables one to
> +describe an object using the Linking view while a Program Header Table enables
> +one to describe an object using the Execution view. The views are not mutually
> +exclusive. For intance, vmlinux can be viewed under both views, ``readelf -S

s/intance/instance/

> +vmlinux`` for the Linking view, and ``readelf -l vmlinux`` for the Execution
> +view.  In Linux only the vmlinux file will have an Execution view, even modules
> +lack an Execution view given that vmlinux is the only file that describes how
> +the the kernel runs from the start.  All other Linux kernel object files have

s/the //

> +an available Linking view.

s/n available// - "have a Linking view" is fine.

> +
> +Under the Linking view, the Section Header Table describes all available
> +sections. The Section Header Table is an array of ELF section header data
> +structures. If on a 32-bit system this is ``struct elf32_shd``, if on a 64-bit
> +this is ``struct elf64_shdr``.

"If on ... if on" doesn't work as a sentence.

> Sections are only visible on object files that

s/on/in/

> +have a Linking view, since all Linux kernel files have Linking view, all kernel
> +objects have ELF sections.

Btw, that last sentence is kinda funny and not really needed. Or do you
wanna say that everything-code is in a section?

> +
> +Limitations on ELF sections

ELF sections limitations

> +=============> +
> +We provide a summary on the limitations of ELF sections.

Kill that sentence.

> Refer to the public
> +ELF specifications for details. Note that 64-bit limitations may depend
> +on processor specific section attributes to be used, refer to your processsor

"processsor" - the 's' button stuck? :-)

> +specification if unsure.

Better yet, kill that whole paragraph.

> +
> +Its worth ellaborating on the limitations on the name of an ELF section:

"elaborating"

> +ELF section names are stored as strings as per the ELF specification, and
> +as can be expected, these don't have explicit limitations. The implicit
> +limitation then depends on the size of an ELF object file and ELF section.
> +
> +If using really large kernels or objects with large amounts of sections one
> +would still need to be sure that ELF loader in charge of loading the Linux
> +kernel is properly updated to handle coping with the latest ELF extensions.
> +
> +   .. flat-table:: Limitations on ELF Sections
> +
> +      * - Section attribute
> +        - 32-bit
> +        - 64-bit
> +
> +      * - ELF section name
> +        - Size of an ELF section
> +        - Size of an ELF section
> +
> +      * - Size of an ELF section
> +        - 4 GiB
> +        - 16 EiB
> +
> +      * - Max number of sections in an object file
> +        - 4 GiEntries (4294967296)
> +        - 16 EiEntries (18446744073709551616)
> +
> +Program specific ELF sections

Program-specific

> +==============> +
> +The ELF specification allows for a section type to be specified as
> +*Program specific section*, defined as ``SHT_PROGBITS``. This sections type

								 section

> +enables programs to customize sections for their own use. In assembly this
									^
									is

> +specified ``@progbits`` on most architectures, on ARM this is ``%progbits``.
	     ^		  ^

	     with the	  flag				s/this is/it is called/

> +
> +``SHT_PROGBITS`` is used by Linux for defining and using Linux ELF sections.
> +
> +Special ELF Sections
> +==========
> +
> +The ELF specification defines *Special ELF Sections* on chapter 4 (`gabi4
> +ch4`_). These are defined as sections which hold program and control
> +information. Of these sections, a few have the section type as
> +``SHT_PROGBITS``. This enables Linux to *further customize* use of the section
> +beyond what the ELF specification suggests.
> +
> +.. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
> diff --git a/Documentation/sections/conf.py b/Documentation/sections/conf.py
> new file mode 100644
> index 000000000000..faa1c57595e1
> --- /dev/null
> +++ b/Documentation/sections/conf.py
> @@ -0,0 +1,4 @@
> +# -*- coding: utf-8; mode: python -*-
> +
> +project = 'Linux Kernel ELF sections'
> +html_search_language = 'en'
> diff --git a/Documentation/sections/index.rst b/Documentation/sections/index.rst
> new file mode 100644
> index 000000000000..f37511ef05e7
> --- /dev/null
> +++ b/Documentation/sections/index.rst
> @@ -0,0 +1,17 @@
> +============> +Linux Kernel ELF sections
> +============> +
> +This book documents the different ELF sections used on the Linux kernel.

							in

> +We start off by providing references to how ELF was standardized, references
> +to the standards on ELF sections, review limitations of ELF sections, and
> +finally how Linux uses ELF sections in the Linux kernel. Certain important
> +Linux ELF sections are documented carefully: we describe the goal of the
> +ELF section, and address concurrency considerations when applicable. A few
> +common a set of Linux helpers for ELF sections are also documented.

s/few common a //

> +
> +.. toctree::
> +   :maxdepth: 4
> +
> +   background
> +   section-core

...

> diff --git a/arch/unicore32/include/asm/section-core.h b/arch/unicore32/include/asm/section-core.h
> new file mode 100644
> index 000000000000..0b9c68429a1a
> --- /dev/null
> +++ b/arch/unicore32/include/asm/section-core.h
> @@ -0,0 +1,19 @@
> +#ifndef __UNICORE_SECTION_CORE_ASM_H__
> +#define __UNICORE_SECTION_CORE_ASM_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/.

Isn't all kernel code GPLv2?

> + */
> +
> +/* Unicore32 has known to not work properly with the type set, so ignore it */
> +
> +#define __set_section_core_type(___section, ___core, ___name,		\
> +				___level, ___flags, ___type)		\
> +	.section ___section..___core.___name.___level, ___flags
> +
> +#include <asm-generic/section-core.h>
> +
> +#endif /* __UNICORE_SECTION_CORE_ASM_H__ */
> diff --git a/arch/x86/include/asm/Kbuild b/arch/x86/include/asm/Kbuild
> index 2b892e2313a9..af975f21eeee 100644
> --- a/arch/x86/include/asm/Kbuild
> +++ b/arch/x86/include/asm/Kbuild
> @@ -12,3 +12,4 @@ generic-y += dma-contiguous.h
>  generic-y += early_ioremap.h
>  generic-y += mcs_spinlock.h
>  generic-y += mm-arch-hooks.h
> +generic-y += section-core.h
> diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
> index b7fbaa56b51a..7879c31e66a7 100644
> --- a/arch/xtensa/include/asm/Kbuild
> +++ b/arch/xtensa/include/asm/Kbuild
> @@ -32,3 +32,4 @@ generic-y += topology.h
>  generic-y += trace_clock.h
>  generic-y += word-at-a-time.h
>  generic-y += xor.h
> +generic-y += section-core.h
> diff --git a/include/asm-generic/section-core.h b/include/asm-generic/section-core.h
> new file mode 100644
> index 000000000000..bb16befc4251
> --- /dev/null
> +++ b/include/asm-generic/section-core.h
> @@ -0,0 +1,307 @@
> +#ifndef _ASM_GENERIC_SECTION_CORE_H_
> +#define _ASM_GENERIC_SECTION_CORE_H_
> +/*
> + * Linux section core definitions
> + *
> + * 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/.

Ditto.

> + */
> +
> +/**
> + * DOC: Linux ELF program specific sections
> + *
> + * Linux makes extensive use of ``SHT_PROGBITS`` to both extend use and definition
							     ^^^^^^^^^^^^^^^^^^^^^^^^

							     needs rewording

> of *Special ELF Sections* (`gabi4 ch4`_) and to define its own
> + * sections. This chaper is dedicated to documenting Linux program specific

"chapter"

Please spellcheck the whole patchset before next submission.

> + * sections and helpers available to make use of these easier to implement and
> + * use.

Huh, come again? This sentence is funny.

> + *
> + * .. _gabi4 ch4: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#special_sections
> + */
> +
> +/**
> + * DOC: Linux linker script
> + *
> + * Linux uses a custom linker script to build the vmlinux binary, it uses it to
> + * strategically place and define Linux ELF sections.  Each architecture needs
> + * to implement its own linker script, it is expected to reside in

			      ... script which is expected ...

> + * ``arch/$(ARCH)/kernel/vmlinux.lds.S``.  Architecture Linux linker scripts in
> + * turn include and use definitions from ``include/asm-generic/vmlinux.lds.h``,
> + * as well as some helpers documented in this chapter.
> + *
> + * In assembly it is common practice to use dots (``.``) in labels to avoid
> + * clashes with C symbols. Similarly, a dot (``.``) can be part of a section
> + * name but not a C symbol. Historically then, two dots are used (``..``)
> + * have been used in linker scripts when adding program specific sections

are used .. have been used?

> + * when there are concerns to avoid clashes with compiler generated sections.

This last sentence needs simplifying.

> + */
> +
> +/**
> + * DOC: Memory protection
> + *
> + * Linux allows architectures which support memory protection features to
> + * take advantage of them by letting architectures define and enable
> + * ``CONFIG_DEBUG_RODATA`` and implement a mark_rodata_ro() call.

Simplify: "Architectures with memory protection features can define and
enable CONFIG_DEBUG_RODATA... "

> + * mark_rodata_ro() can be used for instance to mark specific sections as
				  , for instance, 


> + * read-only or non-executable.
> + *
> + * Linux typically follows a convention to have the .rodata ELF section follow
> + * after the .text ELF section, it does this to help architectures which
				 . It does this...

> + * support memory protection to mark both .text and .rodata as read-only in
> + * one shot.
> + *
> + * For more details refer to mark_rodata_ro().
> + */
> +
> +/**
> + * DOC: .rodata
> + *
> + * ELF section used for data which must be protected from write access.
> + */
> +
> +/**
> + * DOC: .text
> + *
> + * ELF section name used for code (functions) used during regular
> + * kernel run time.
> + */
> +
> +/**
> + * DOC: .data
> + *
> + * ELF section used for read-write data.
> + */
> +
> +/**
> + * DOC: Linux init sections
> + *
> + * These sections are used for code and data structures used during boot or
> + * module initialization. On architectures that support it (x86, x86_64), all
> + * this code is freed up by the kernel right before the fist userspace init
> + * process is called when built-in to the kernel, and if modular it is freed
> + * after module initialization. Since the code is freed so early, in theory
> + * there should be no races against freeing this code with other CPUs. Init
> + * section code and data structures should never be exported with
> + * EXPORT_SYMBOL*() as the code will quickly become unavailable to the kernel
> + * after bootup.
> + */
> +
> +/**
> + * DOC: .init.text
> + *
> + * ELF section for code (functions) used only during boot or driver
> + * initialization.
> + *
> + */
> +
> +/**
> + * DOC: .init.data
> + *
> + * ELF section used for data structures used only during boot or driver
> + * initialization.
> + */
> +
> +/**
> + * DOC: .init.rodata
> + *
> + * ELF section used for read-only code (functions) used only during boot
> + * or driver initialization.
> + */
> +
> +/**
> + * DOC: .initcall
> + *
> + * ELF section used for subsystem init calls. There are init levels
> + * representing different functionality in the kernel. For more details
> + * refer to __define_initcall().
> + */
> +
> +/**
> + * DOC: Linux exit sections
> + *
> + * These sections are used to declare a functions and data structures which

s/a //

> + * are only required on exit, the function or data structure will be dropped
> + * if the code declaring this section is not compiled as a module on
> + * architectures that support this (x86, x86_64). There is no special case
> + * handling for this code when built-in to the kernel.
> + */
> +
> +/**
> + * DOC: .exit.text
> + *
> + * ELF section used to for code (functions) used only during module unload.
> + */
> +
> +/**
> + * DOC: .exit.data
> + *
> + * ELF section used to for data structures used only during module
> + * unload.
> + */
> +
> +/**
> + * DOC: .exitcall.exit
> + *
> + * ELF section used for exit routines, order is important and maintained by
> + * link order.
> + */
> +
> +/**
> + * DOC: Linux references to init sections
> + *
> + * These sections are used to teach modpost to not warn about possible
> + * misuses of init section code from other sections. If you use this
> + * your use case should document why you are certain such use of init
> + * sectioned code is valid. For more details refer to ``include/linux/init.h``
> + * ``__ref``, ``__refdata``, and ``__refconst`` documentation.
> + */
> +
> +/**
> + * DOC: .ref.text
> + *
> + * ELF section used to annotate code (functions) which has been vetteed as

vetted?

> + * valid for its reference or use of other code (functions) or data structures
> + * which are part of the init sections.
> + */
> +
> +/**
> + * DOC: .ref.data
> + *
> + * ELF section used for data structures which have been vetteed for its

ditto.

> + * reference or use of other code (functions) or data structures part of the
> + * init sections.
> + */
> +
> +/**
> + * DOC: .ref.rodata
> + *
> + * ELF section used to annotate const code (functions) const data structures
> + * which has been vetteed for its reference or use of other code (functions)

ditto.

> + * or data structures part of the init sections.
> + */
> +
> +/* Can be used on foo.S for instance */

What does that comment mean?

> +#ifndef __set_section_core_type
> +# define __set_section_core_type(___section, ___core, ___name,		\
> +				 ___level, ___flags, ___type)		\
> +	.section ___section..___core.___name.___level, ___flags, ___type

Are you sure we need 4 levels of hierarchy?

If so, we should document what all those section, core, name and level
mean and how the whole sections hierarchy is supposed to look like.

> +#endif
> +
> +#ifndef __set_section_core
> +# define __set_section_core(___section, ___core, ___name, ___level, ___flags) \
> +	.section ___section..___core.___name.___level, ___flags
> +#endif
> +
> +#ifndef __push_section_core
> +# define __push_section_core(__section, __core, __name, __level, __flags) \
> +	.pushsection __section..__core.__name.__level, __flags
> +#endif
> +
> +#ifdef __KERNEL__
> +#include <linux/stringify.h>
> +#endif
> +
> +#if defined(__ASSEMBLER__) || defined(__ASSEMBLY__)
> +
> +# ifndef LINKER_SCRIPT
> +
> +#  ifndef push_section_core
> +#   define push_section_core(__section, __core, __name, __level, __flags) \
> +	 __push_section_core(__section, __core, __name,			  \
> +			     __level, __stringify(__flags))
> +#  endif
> +
> +#  ifndef set_section_core
> +#   define set_section_core(__section, __core, __name,			\
> +			    __level, __flags)				\
> +	__set_section_core(__section, __core, __name,			\
> +			   __level, __stringify(__flags))
> +#  endif
> +
> +#  ifndef set_section_core_type
> +#   define set_section_core_type(__section, __core, __name,		\
> +				 __level, __flags, __type)		\
> +	__set_section_core_type(__section, __core, __name, __level,	\
> +				__stringify(__flags), __type)
> +#  endif
> +
> +# endif /* LINKER_SCRIPT */
> +#else /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
> +
> +/*
> + * As per gcc's documentation a common asm separator is a new line followed
> + * by tab [0], it however seems possible to also just use a newline as its

		. It, however, seems ...

> + * the most commonly empirically observed semantic and folks seem to agree
> + * this even works on S390. In case your architecture disagrees you may
> + * override this and define your own and keep the rest of the macros.
> + *
> + * [0] https://gcc.gnu.org/onlinedocs/gcc/Basic-Asm.html#Basic-Asm
> + */
> +# ifndef ASM_CMD_SEP
> +#  define ASM_CMD_SEP	"\n"
> +# endif
> +
> +# ifndef set_section_core
> +#  define set_section_core(__section, __core, __name, __level, __flags)	\
> +	__stringify(__set_section_core_type(__section, __core, __name,	\
> +					    __level, __stringify(__flags))) \
> +	ASM_CMD_SEP
> +# endif
> +
> +/*
> + * Some architectures (arm, and avr32 are two examples on kprobes) seem
> + * currently explicitly specify the type [0] -- this can be any of the
> + * optional constants on ELF:
> + *
> + * @progbits - section contains data
> + * @nobits - section does not contain data (i.e., section only occupies space)
> + * @note - section contains data which is used by things other than the program
> + * @init_array - section contains an array of pointers to init functions
> + * @fini_array - section contains an array of pointers to finish functions
> + * @preinit_array - section contains an array of pointers to pre-init functions
> + *
> + * ARM requires % instead of @.
> + *
> + * At least as per nasm (x86/x86_64 only), in the absence of qualifiers the
> + * defaults are as follows:
> + *
> + * section .text    progbits  alloc   exec    nowrite  align\x16
> + * section .rodata  progbits  alloc   noexec  nowrite  align=4
> + * section .lrodata progbits  alloc   noexec  nowrite  align=4
> + * section .data    progbits  alloc   noexec  write    align=4
> + * section .ldata   progbits  alloc   noexec  write    align=4
> + * section .bss     nobits    alloc   noexec  write    align=4
> + * section .lbss    nobits    alloc   noexec  write    align=4
> + * section .tdata   progbits  alloc   noexec  write    align=4    tls
> + * section .tbss    nobits    alloc   noexec  write    align=4    tls
> + * section .comment progbits  noalloc noexec  nowrite  align=1
> + * section other    progbits  alloc   noexec  nowrite  align=1
> + *
> + * gas should have sensible defaults for architectures...
> + *
> + * [0] http://www.nasm.us/doc/nasmdoc7.html
> + */
> +# ifndef set_section_core_type
> +#  define set_section_core_type(__section, __core, __name, __level,	\
> +				__flags, __type)			\
> +	__stringify(__set_section_core_type(__section, __core,		\
> +					    __name, __level,		\
> +					    __stringify(__flags),	\
> +					    __type))			\
> +	ASM_CMD_SEP
> +# endif
> +
> +# ifndef push_section_core
> +#  define push_section_core(__section, __core, __name,			\
> +			    __level, __flags)				\
> +	__stringify(__push_section_core(__section, __core,		\
> +					__name,	__level,		\
> +					__stringify(__flags)))		\
> +	ASM_CMD_SEP
> +# endif
> +
> +#endif /* defined(__ASSEMBLER__) || defined(__ASSEMBLY__) */
> +#endif /* _ASM_GENERIC_SECTION_CORE_H_ */
> diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h
> index 4df64a1fc09e..b145ae8d9cbe 100644
> --- a/include/asm-generic/sections.h
> +++ b/include/asm-generic/sections.h
> @@ -1,6 +1,8 @@
>  #ifndef _ASM_GENERIC_SECTIONS_H_
>  #define _ASM_GENERIC_SECTIONS_H_
>  
> +#include <asm/section-core.h>
> +
>  /* References to section boundaries */
>  
>  #include <linux/compiler.h>
> diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
> index 0968d13b3885..483f60c451f9 100644
> --- a/include/asm-generic/vmlinux.lds.h
> +++ b/include/asm-generic/vmlinux.lds.h
> @@ -55,6 +55,7 @@
>  #endif
>  
>  #include <linux/export.h>
> +#include <asm/section-core.h>
>  
>  /* Align . to a 8 byte boundary equals to maximum function alignment. */
>  #define ALIGN_FUNCTION()  . = ALIGN(8)
> diff --git a/include/linux/init.h b/include/linux/init.h
> index 885c3e6d0f9d..116e3262332a 100644
> --- a/include/linux/init.h
> +++ b/include/linux/init.h
> @@ -130,6 +130,24 @@ int __init init_rootfs(void);
>  extern bool rodata_enabled;
>  #endif
>  #ifdef CONFIG_DEBUG_RODATA
> +/**
> + * mark_rodata_ro - implemement memory protection for ELF sections
> + *
> + * Architectures which support memory protection define a kernel configuration
> + * entry for CONFIG_DEBUG_RODATA,

That's just too many words for nothing. You can just as well say:

"Architectures which support memory protection enable CONFIG_DEBUG_RODATA and
implement mark_rodata_ro()."

> enable it in and implement mark_rodata_ro().
> + * mark_rodata_ro() should strive to adjust the .rodata and .text ELF sections
> + * with read-only memory protection to prevent modifications of these sections

"mark_rodata_ro() marks .rodata and .text section read-only..."

Simple.

> + * after bootup. It can also try to use memory protection to prevent execution
> + * on the .rodata ELF section.
> + *
> + * In order to help architectures set both .text and .rodata as read-only with
> + * memory protections in one shot Linux has typically followed the convention
> + * to have the .rodata ELF section follow the .text ELF section on the vmlinux

								   in

> + * linker script.
> + *
> + * Linux calls mark_rodata_ro() after freeing .init code and prior to calling
> + * the first init userspace process.

"first init userspace process" either say "prior to calling init" or
"prior to calling the first userspace process" but both is jambalayed
into something confusing.

> + */
>  void mark_rodata_ro(void);
>  #endif
>  
> @@ -140,25 +158,70 @@ extern bool initcall_debug;
>  #endif
>    
>  #ifndef MODULE
> +/**
> + * DOC: Initcall levels
> + *
> + * When Linux boots the kernel do_initcalls() iterates over each Linux

When Linux boots the kernel?!? You're joking, right?

Just do "During boot, do_initcalls() ..."

> + * initialization level ID and calls all routines embedded on each level ID.
> + * Prior to v2.5.2.3 Linux had only one init level onto which all init
> + * functions folded onto using __initcall(). After v2.5.2.4 Linux split up
> + * initcalls into 7 separate initcall subsection levels, each level describing
> + * different functionality part of the kernel (commit `9d6ba121b7e17085`_
> + * (v2.5.2.3 -> v2.5.2.4)). In order to remain backward compatible __initcall()
> + * calls were left mapped to device_initcall().

And why do we need all that git archeology here?

> + * Each init level consists of a dedicated ELF section, init functions are
> + * associated to an init level by linking it into the respective level's
		 with

> + * ELF section.
> + *
> + * Lower order init levels run prior to higher order init levels. Ordering
> + * inside each initcall level is determined by respective link order.

Those last two sentences are enough.

> + *
> + * .. _9d6ba121b7e17085: https://git.kernel.org/cgit/linux/kernel/git/history/history.git/commit/?id6ba121b7e17085c95139233686b27a4d4c650e

That's one ugly footnote. Also, the git commit id suffices, you don't
need the URL.

> + */
>  
>  #ifndef __ASSEMBLY__
>  
> -/*
> - * initcalls are now grouped by functionality into separate
> - * subsections. Ordering inside the subsections is determined
> - * by link order. 
> - * For backwards compatibility, initcall() puts the call in 
> - * the device init subsection.
> +/**
> + * __define_initcall - wrapper for definiting init levels
		       ()

also s/definiting/defining/

Also, this is not what __define_initcall() does. It is not defining init levels.

>   *
> - * The `id' arg to __define_initcall() is needed so that multiple initcalls
> - * can point at the same handler without causing duplicate-symbol build errors.
> + * @fn: init routine
> + * @id: init level
>   *
> - * Initcalls are run by placing pointers in initcall sections that the
> - * kernel iterates at runtime. The linker can do dead code / data elimination
> - * and remove that completely, so the initcall sections have to be marked
> - * as KEEP() in the linker script.
> + * Defines a kernel initialization level. A respective linker script entry
> + * is required to ensure the init level is accounted for and to ensure symbols
> + * exist for iterating over all functions in the init level. A init level
								An

> + * represents a series of functionality in the kernel.

That sounds yucky.

An init level is a bunch of functions which are called after init_level
- 1 and before init_level + 1.

> + *
> + * Ordering within an initialization level is determined by link order, so
> + * for instance if a Makefile had::
> + *
> + *	obj-y += foo.o
> + *	obj-y += bar.o
> + *
> + * And foo.c::
> + *
> + *	subsys_initcall(foo_init);
> + *
> + * And bar.c had::
> + *
> + *	subsys_initcall(bar_init);
> + *
> + * foo_init() would be called prior to bar_init().
> + *
> + * Note that @id in __define_initcall() also enables multiple initcalls
> + * to be created using the same handler for different init levels without
> + * causing duplicate-symbol build errors.
> + *
> + * Initcalls are run by placing start symbols to initcall levels inside ELF
> + * sections, the kernel in turn uses these symbols to iterate over each init
> + * level at runtime with do_initcall_level(). The end of each init level is
> + * marked by the subsequent's symbol's start address until we reach the symbol
> + * ``__initcall_end``.

Needlessly complex, simplify.

> The linker can do dead code / data elimination and each
> + * init level start symbol could be removed completely in this process, to
									 . To   <-- new sentence

> + * avoid this each init level start symbols must be marked as 'KEEP()' in the
> + * linker script to avoid any linker optimization heuristic on initcalls.
>   */
> -
>  #define __define_initcall(fn, id) \
>  	static initcall_t __initcall_##fn##id __used \
>  	__attribute__((__section__(".initcall" #id ".init"))) = fn;
> diff --git a/include/linux/sections.h b/include/linux/sections.h
> new file mode 100644
> index 000000000000..6771c727bcd1
> --- /dev/null
> +++ b/include/linux/sections.h
> @@ -0,0 +1,87 @@
> +#ifndef _LINUX_SECTIONS_H
> +#define _LINUX_SECTIONS_H
> +/*
> + * Linux de-facto sections

Useless.

> + *
> + * 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>
> +#include <linux/export.h>
> +
> +#ifndef __ASSEMBLY__
> +
> +/**
> + * DOC: Introduction
> + *
> + * Linux defines a set of common helpers which can be used to against its use
						      ^^^^^^^^^^^^^^^^^^^^^^^^^^

??

> + * of standard or custom Linux sections, this section is dedicated to these

this section is talking about sections, that's too much.

> + * helpers.
> + */
> +
> +/**
> + * LINUX_SECTION_ALIGNMENT - get section alignment
> + *
> + * @name: section name
> + *
> + * Gives you the alignment for the section.
> + */
> +#define LINUX_SECTION_ALIGNMENT(name)	__alignof__(*VMLINUX_SYMBOL(name))

Eeww, too long and it is a getter but doesn't have "GET" in its name.

How about GET_SECTION_ALIGN() ?

And what's with the "LINUX_" prefix - that's like useless use of screen
real estate.

> +
> +/**
> + * LINUX_SECTION_START - get address of start of section

GET_SECTION_START()	-  get address of section start

> + *
> + * @name: section name
> + *
> + * This gives you the start address of the section.
> + * This should give you the address of the first entry.

Huh?

> + *
> + */
> +#define LINUX_SECTION_START(name)	VMLINUX_SYMBOL(name)

Ditto.

> +
> +/**
> + * LINUX_SECTION_END - get address of end of the section
> + *
> + * @name: section name
> + *
> + * This gives you the end address of the section.
> + * This should give you the address of the end of the
> + * section. This will match the start address if the
> + * section is empty.
> + */
> +#define LINUX_SECTION_END(name)	VMLINUX_SYMBOL(name##__end)
> +
> +/**
> + * DECLARE_LINUX_SECTION - Declares a custom Linux section

DECLARE_SECTION() is perfectly fine IMO.

> + *
> + * @type: type of custom Linux section
> + * @name: custom section name
> + *
> + * Declares a read-write custom Linux section
> + */
> +#define DECLARE_LINUX_SECTION(type, name)				\
> +	 extern type VMLINUX_SYMBOL(name)[], \
> +		     VMLINUX_SYMBOL(name##__end)[]
> +
> +/**
> + * DECLARE_LINUX_SECTION_RO - Declares a read-only custom Linux section

DECLARE_SECTION_RO()

> + *
> + * @type: type of custom Linux section
> + * @name: custom section name
> + *
> + * Declares a read-only custom Linux section
> + */
> +#define DECLARE_LINUX_SECTION_RO(type, name)				\
> +	 extern const type VMLINUX_SYMBOL(name)[],			\
> +			   VMLINUX_SYMBOL(name##__end)[]
> +
> +#define __SECTION_CORE(section, core, name, level)			\
> +	#section ".." #core "." #name "." #level
> +
> +#endif /* __ASSEMBLY__ */
> +
> +#endif /* _LINUX_SECTIONS_H */
> -- 

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 02/14] xtensa: skip adding literal when SORT() is used
  2017-01-15 21:10           ` Luis R. Rodriguez
  (?)
@ 2017-01-18 11:29             ` Borislav Petkov
  -1 siblings, 0 replies; 480+ messages in thread
From: Borislav Petkov @ 2017-01-18 11:29 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: gnomes, dalias, linux-ia64, jkosina, benh, ming.lei,
	heiko.carstens, platform-driver-x86, James.Bottomley,
	paul.gortmaker, paulus, mpe, hpa, masami.hiramatsu.pt, wangnan0,
	mchehab, linux-arch, markus.heiser, sparclinux, xen-devel, linux,
	linux-sh, will.deacon, korea.drzix, x86, anil.s.keshavamurthy,
	fontana, mingo, dsahern, linux-arm-kernel, catalin.marinas,
	dvhart, dwmw2, linux, david.vrabel, linux-xte

On Sun, Jan 15, 2017 at 01:10:45PM -0800, Luis R. Rodriguez wrote:
> When SORT(foo.*) is used the current sed replacements add
> SORT(foo.literal foo.*), this breaks linking. Avoid adding
> literals for SORT globs, if needed, these need to be added
> manually.

Please rewrite this commit message by breaking into separate sentences,
adding punctuation, etc.

Also, "the current sed replacements add" sounds really strange and makes
me wonder what do you mean. What are "sed replacements"? I think you
mean the "sed regex adds" from looking at the diff.

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 02/14] xtensa: skip adding literal when SORT() is used
@ 2017-01-18 11:29             ` Borislav Petkov
  0 siblings, 0 replies; 480+ messages in thread
From: Borislav Petkov @ 2017-01-18 11:29 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: gnomes, dalias, linux-ia64, jkosina, benh, ming.lei,
	heiko.carstens, platform-driver-x86, James.Bottomley,
	paul.gortmaker, paulus, mpe, hpa, masami.hiramatsu.pt, wangnan0,
	mchehab, linux-arch, markus.heiser, sparclinux, xen-devel, linux,
	linux-sh, will.deacon, korea.drzix, x86, anil.s.keshavamurthy,
	fontana, mingo, dsahern, linux-arm-kernel, catalin.marinas,
	dvhart, dwmw2, linux, david.vrabel, linux-xte

On Sun, Jan 15, 2017 at 01:10:45PM -0800, Luis R. Rodriguez wrote:
> When SORT(foo.*) is used the current sed replacements add
> SORT(foo.literal foo.*), this breaks linking. Avoid adding
> literals for SORT globs, if needed, these need to be added
> manually.

Please rewrite this commit message by breaking into separate sentences,
adding punctuation, etc.

Also, "the current sed replacements add" sounds really strange and makes
me wonder what do you mean. What are "sed replacements"? I think you
mean the "sed regex adds" from looking at the diff.

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 02/14] xtensa: skip adding literal when SORT() is used
@ 2017-01-18 11:29             ` Borislav Petkov
  0 siblings, 0 replies; 480+ messages in thread
From: Borislav Petkov @ 2017-01-18 11:29 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, gregkh, rusty, gnomes, alan, dwmw2,
	arnd, ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley

On Sun, Jan 15, 2017 at 01:10:45PM -0800, Luis R. Rodriguez wrote:
> When SORT(foo.*) is used the current sed replacements add
> SORT(foo.literal foo.*), this breaks linking. Avoid adding
> literals for SORT globs, if needed, these need to be added
> manually.

Please rewrite this commit message by breaking into separate sentences,
adding punctuation, etc.

Also, "the current sed replacements add" sounds really strange and makes
me wonder what do you mean. What are "sed replacements"? I think you
mean the "sed regex adds" from looking at the diff.

-- 
Regards/Gruss,
    Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nürnberg)
-- 

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 1/6] tools: add a userspace tools bug.h
  2017-01-15 21:12             ` Luis R. Rodriguez
  (?)
@ 2017-01-19 11:01               ` Greg KH
  -1 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:01 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Sun, Jan 15, 2017 at 01:12:10PM -0800, Luis R. Rodriguez wrote:
> This will be used later by the userspace linker-tables sandbox.

What is that?

> As a convenience, include bug.h on kernel.h -- this is not done
> on upstream kernel.h, however most header files do include bug.h
> eventually, if we were to only add the ones that need it we'd
> need to copy a lot of headers to tools for the only purpose of
> includeing bug.h.

I can't parse this sentance at all, please simplify or clarify or
something so that I understand what is going on here.

> This simplifies that.

What is "that"?  You can't do that for such a complex previous sentence.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 1/6] tools: add a userspace tools bug.h
@ 2017-01-19 11:01               ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:01 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Sun, Jan 15, 2017 at 01:12:10PM -0800, Luis R. Rodriguez wrote:
> This will be used later by the userspace linker-tables sandbox.

What is that?

> As a convenience, include bug.h on kernel.h -- this is not done
> on upstream kernel.h, however most header files do include bug.h
> eventually, if we were to only add the ones that need it we'd
> need to copy a lot of headers to tools for the only purpose of
> includeing bug.h.

I can't parse this sentance at all, please simplify or clarify or
something so that I understand what is going on here.

> This simplifies that.

What is "that"?  You can't do that for such a complex previous sentence.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 1/6] tools: add a userspace tools bug.h
@ 2017-01-19 11:01               ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:01 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley

On Sun, Jan 15, 2017 at 01:12:10PM -0800, Luis R. Rodriguez wrote:
> This will be used later by the userspace linker-tables sandbox.

What is that?

> As a convenience, include bug.h on kernel.h -- this is not done
> on upstream kernel.h, however most header files do include bug.h
> eventually, if we were to only add the ones that need it we'd
> need to copy a lot of headers to tools for the only purpose of
> includeing bug.h.

I can't parse this sentance at all, please simplify or clarify or
something so that I understand what is going on here.

> This simplifies that.

What is "that"?  You can't do that for such a complex previous sentence.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 2/6] tools: add init.h for tools
  2017-01-15 21:12             ` Luis R. Rodriguez
  (?)
@ 2017-01-19 11:02               ` Greg KH
  -1 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:02 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: gnomes, dalias, linux-ia64, jkosina, benh, ming.lei,
	heiko.carstens, platform-driver-x86, James.Bottomley,
	paul.gortmaker, paulus, mpe, hpa, masami.hiramatsu.pt, wangnan0,
	mchehab, linux-arch, markus.heiser, sparclinux, xen-devel, linux,
	linux-sh, will.deacon, korea.drzix, x86, anil.s.keshavamurthy,
	fontana, mingo, dsahern, linux-arm-kernel, catalin.marinas,
	dvhart, bp, linux, david.vrabel, linux-xtensa

On Sun, Jan 15, 2017 at 01:12:11PM -0800, Luis R. Rodriguez wrote:
> Start off with just __ref -- we enalbe you to override, if you do
> that then you can define your own.

I have no idea what this means, do you?

> The way you'd use this, if you
> do override, is define your own __ref and then use include_next.

Huh?

Again, please be more specific or clear or something, I have no idea
again what this patch is for.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 2/6] tools: add init.h for tools
@ 2017-01-19 11:02               ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:02 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: gnomes, dalias, linux-ia64, jkosina, benh, ming.lei,
	heiko.carstens, platform-driver-x86, James.Bottomley,
	paul.gortmaker, paulus, mpe, hpa, masami.hiramatsu.pt, wangnan0,
	mchehab, linux-arch, markus.heiser, sparclinux, xen-devel, linux,
	linux-sh, will.deacon, korea.drzix, x86, anil.s.keshavamurthy,
	fontana, mingo, dsahern, linux-arm-kernel, catalin.marinas,
	dvhart, bp, linux, david.vrabel, linux-xtensa

On Sun, Jan 15, 2017 at 01:12:11PM -0800, Luis R. Rodriguez wrote:
> Start off with just __ref -- we enalbe you to override, if you do
> that then you can define your own.

I have no idea what this means, do you?

> The way you'd use this, if you
> do override, is define your own __ref and then use include_next.

Huh?

Again, please be more specific or clear or something, I have no idea
again what this patch is for.

thanks,

greg k-h

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 2/6] tools: add init.h for tools
@ 2017-01-19 11:02               ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:02 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley

On Sun, Jan 15, 2017 at 01:12:11PM -0800, Luis R. Rodriguez wrote:
> Start off with just __ref -- we enalbe you to override, if you do
> that then you can define your own.

I have no idea what this means, do you?

> The way you'd use this, if you
> do override, is define your own __ref and then use include_next.

Huh?

Again, please be more specific or clear or something, I have no idea
again what this patch is for.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 3/6] tools: add __used and enable to override
  2017-01-15 21:12             ` Luis R. Rodriguez
  (?)
@ 2017-01-19 11:02               ` Greg KH
  -1 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:02 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Sun, Jan 15, 2017 at 01:12:12PM -0800, Luis R. Rodriguez wrote:
> This adds __used, to be used later in the userspace linker-tables
> sandbox. If any userspace applicaiton wants to override they can
> add their own definition and then use include_next.

I think you need a spell checker :(


^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 3/6] tools: add __used and enable to override
@ 2017-01-19 11:02               ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:02 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Sun, Jan 15, 2017 at 01:12:12PM -0800, Luis R. Rodriguez wrote:
> This adds __used, to be used later in the userspace linker-tables
> sandbox. If any userspace applicaiton wants to override they can
> add their own definition and then use include_next.

I think you need a spell checker :(


^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 3/6] tools: add __used and enable to override
@ 2017-01-19 11:02               ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:02 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley

On Sun, Jan 15, 2017 at 01:12:12PM -0800, Luis R. Rodriguez wrote:
> This adds __used, to be used later in the userspace linker-tables
> sandbox. If any userspace applicaiton wants to override they can
> add their own definition and then use include_next.

I think you need a spell checker :(


^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 4/6] tools: expand export.h with VMLINUX_SYMBOL()
  2017-01-15 21:12             ` Luis R. Rodriguez
  (?)
@ 2017-01-19 11:03               ` Greg KH
  -1 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:03 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Sun, Jan 15, 2017 at 01:12:13PM -0800, Luis R. Rodriguez wrote:
> This will be used later by the linker-table userspace sandbox.

That does not explan what this is, why it is needed, or anything at all
:(


^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 4/6] tools: expand export.h with VMLINUX_SYMBOL()
@ 2017-01-19 11:03               ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:03 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Sun, Jan 15, 2017 at 01:12:13PM -0800, Luis R. Rodriguez wrote:
> This will be used later by the linker-table userspace sandbox.

That does not explan what this is, why it is needed, or anything at all
:(


^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 4/6] tools: expand export.h with VMLINUX_SYMBOL()
@ 2017-01-19 11:03               ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:03 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley

On Sun, Jan 15, 2017 at 01:12:13PM -0800, Luis R. Rodriguez wrote:
> This will be used later by the linker-table userspace sandbox.

That does not explan what this is, why it is needed, or anything at all
:(


^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 4/6] tools: expand export.h with VMLINUX_SYMBOL()
  2017-01-15 21:12             ` Luis R. Rodriguez
  (?)
@ 2017-01-19 11:04               ` Greg KH
  -1 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:04 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Sun, Jan 15, 2017 at 01:12:13PM -0800, Luis R. Rodriguez wrote:
> This will be used later by the linker-table userspace sandbox.
> 
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  tools/include/linux/export.h | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/tools/include/linux/export.h b/tools/include/linux/export.h
> index d07e586b9ba0..cb7d6b490e08 100644
> --- a/tools/include/linux/export.h
> +++ b/tools/include/linux/export.h
> @@ -1,6 +1,28 @@
>  #ifndef _TOOLS_LINUX_EXPORT_H_
>  #define _TOOLS_LINUX_EXPORT_H_
>  
> +/*
> + * Export symbols from the kernel to modules.  Forked from module.h
> + * to reduce the amount of pointless cruft we feed to gcc when only
> + * exporting a simple symbol or two.

You copied it, yet did not remove it from the original?

> + *
> + * Try not to add #includes here.  It slows compilation and makes kernel
> + * hackers place grumpy comments in header files.

Define "slows" please.  I doubt it is measurable, and so, why even
mention it here?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 4/6] tools: expand export.h with VMLINUX_SYMBOL()
@ 2017-01-19 11:04               ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:04 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Sun, Jan 15, 2017 at 01:12:13PM -0800, Luis R. Rodriguez wrote:
> This will be used later by the linker-table userspace sandbox.
> 
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  tools/include/linux/export.h | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/tools/include/linux/export.h b/tools/include/linux/export.h
> index d07e586b9ba0..cb7d6b490e08 100644
> --- a/tools/include/linux/export.h
> +++ b/tools/include/linux/export.h
> @@ -1,6 +1,28 @@
>  #ifndef _TOOLS_LINUX_EXPORT_H_
>  #define _TOOLS_LINUX_EXPORT_H_
>  
> +/*
> + * Export symbols from the kernel to modules.  Forked from module.h
> + * to reduce the amount of pointless cruft we feed to gcc when only
> + * exporting a simple symbol or two.

You copied it, yet did not remove it from the original?

> + *
> + * Try not to add #includes here.  It slows compilation and makes kernel
> + * hackers place grumpy comments in header files.

Define "slows" please.  I doubt it is measurable, and so, why even
mention it here?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 4/6] tools: expand export.h with VMLINUX_SYMBOL()
@ 2017-01-19 11:04               ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:04 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley

On Sun, Jan 15, 2017 at 01:12:13PM -0800, Luis R. Rodriguez wrote:
> This will be used later by the linker-table userspace sandbox.
> 
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  tools/include/linux/export.h | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/tools/include/linux/export.h b/tools/include/linux/export.h
> index d07e586b9ba0..cb7d6b490e08 100644
> --- a/tools/include/linux/export.h
> +++ b/tools/include/linux/export.h
> @@ -1,6 +1,28 @@
>  #ifndef _TOOLS_LINUX_EXPORT_H_
>  #define _TOOLS_LINUX_EXPORT_H_
>  
> +/*
> + * Export symbols from the kernel to modules.  Forked from module.h
> + * to reduce the amount of pointless cruft we feed to gcc when only
> + * exporting a simple symbol or two.

You copied it, yet did not remove it from the original?

> + *
> + * Try not to add #includes here.  It slows compilation and makes kernel
> + * hackers place grumpy comments in header files.

Define "slows" please.  I doubt it is measurable, and so, why even
mention it here?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 5/6] tools: add __section() to compiler.h
  2017-01-15 21:12             ` Luis R. Rodriguez
  (?)
@ 2017-01-19 11:04               ` Greg KH
  -1 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:04 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Sun, Jan 15, 2017 at 01:12:14PM -0800, Luis R. Rodriguez wrote:
> This will be used later by the userspace linker table.

same comment as the last time you used this sentence as a changelog
text...

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 5/6] tools: add __section() to compiler.h
@ 2017-01-19 11:04               ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:04 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Sun, Jan 15, 2017 at 01:12:14PM -0800, Luis R. Rodriguez wrote:
> This will be used later by the userspace linker table.

same comment as the last time you used this sentence as a changelog
text...

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 5/6] tools: add __section() to compiler.h
@ 2017-01-19 11:04               ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:04 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley

On Sun, Jan 15, 2017 at 01:12:14PM -0800, Luis R. Rodriguez wrote:
> This will be used later by the userspace linker table.

same comment as the last time you used this sentence as a changelog
text...

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 6/6] tools: add userspace linker table sandbox
  2017-01-15 21:12             ` Luis R. Rodriguez
  (?)
@ 2017-01-19 11:07             ` Greg KH
  -1 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:07 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: gnomes, dalias, linux-ia64, jkosina, benh, ming.lei,
	heiko.carstens, platform-driver-x86, James.Bottomley,
	paul.gortmaker, paulus, mpe, hpa, masami.hiramatsu.pt, wangnan0,
	mchehab, linux-arch, markus.heiser, sparclinux, xen-devel, linux,
	linux-sh, will.deacon, korea.drzix, x86, anil.s.keshavamurthy,
	fontana, mingo, dsahern, linux-arm-kernel, catalin.marinas,
	dvhart, bp, linux, david.vrabel, linux-xtensa

On Sun, Jan 15, 2017 at 01:12:15PM -0800, Luis R. Rodriguez wrote:
> Add a userspace sandbox to allow easy experimentation and
> test extensions with linker tables, section ranges and the
> new section core definitions.
> 
> The userspace sandbox tries to mimic the Linux kernel development
> flow as much as possible, it however relies on and uses libc. Support
> is currently only provided to x86_64.

Why is x86_64 a requirement?

> 
> Demo run:
> 
> cd tools/linker-tables
> make clean; make;
> ./demo
> Initializing x86 bare metal world
> x86-init: Number of init entries: 8
> Initializing memory ...
> Completed initializing memory !
> Initializing pci ...
> PCI fixup size: 1
> Demo: Using LINKTABLE_FOR_EACH
> foo_fixup
> Demo: Using LINKTABLE_RUN_ALL
> foo_fixup
> Completed initializing pci !
> Number of init entries: 1
> Initializing kprobes ...
> == OK: test_kprobe_0001 within range!
> == OK: test_kprobe_0002 not in range as expected!
> Completed initializing kprobes !
> Initializing kasan ...
> Early init for Kasan...
> Completed initializing kasan !
> Initializing beta ...
> Completed initializing beta !
> Initializing alpha ...
> Completed initializing alpha !
> Booting bare metal
> Calling start_kernel()...
> ACME: Initializing ...
> ACME: Finished init ... !
> Synthetics: synth_init_or(2) returns: 0xDEADBEEF
> Synthetics: ps_shr(0xDEADBEEF, get_demo_shr) returns: 0x0000DEAD

Why isn't this tied into the kernel testing framework?

thanks,

greg k-h

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 01/14] generic-sections: add section core helpers
  2017-01-15 21:10           ` Luis R. Rodriguez
  (?)
@ 2017-01-19 11:09             ` Greg KH
  -1 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:09 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Sun, Jan 15, 2017 at 01:10:44PM -0800, Luis R. Rodriguez wrote:
> Linux makes extensive use of custom ELF header sections,
> documentation for these are well scattered. Unify this
> documentation in a central place and provide helpers to
> build custom Linux sections.
> 
> This also generalizes sections code to enable avoiding

When you say "also" in a changelog, that's a huge flag you need to split
this up.  There's no reason the documentation for elf header sections
has to be in the same patch as code.  Please break it up.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 01/14] generic-sections: add section core helpers
@ 2017-01-19 11:09             ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:09 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Sun, Jan 15, 2017 at 01:10:44PM -0800, Luis R. Rodriguez wrote:
> Linux makes extensive use of custom ELF header sections,
> documentation for these are well scattered. Unify this
> documentation in a central place and provide helpers to
> build custom Linux sections.
> 
> This also generalizes sections code to enable avoiding

When you say "also" in a changelog, that's a huge flag you need to split
this up.  There's no reason the documentation for elf header sections
has to be in the same patch as code.  Please break it up.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 01/14] generic-sections: add section core helpers
@ 2017-01-19 11:09             ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:09 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley

On Sun, Jan 15, 2017 at 01:10:44PM -0800, Luis R. Rodriguez wrote:
> Linux makes extensive use of custom ELF header sections,
> documentation for these are well scattered. Unify this
> documentation in a central place and provide helpers to
> build custom Linux sections.
> 
> This also generalizes sections code to enable avoiding

When you say "also" in a changelog, that's a huge flag you need to split
this up.  There's no reason the documentation for elf header sections
has to be in the same patch as code.  Please break it up.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 03/14] ranges.h: add helpers to build and identify Linux section ranges
  2017-01-15 21:10           ` Luis R. Rodriguez
  (?)
@ 2017-01-19 11:11             ` Greg KH
  -1 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:11 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Sun, Jan 15, 2017 at 01:10:46PM -0800, Luis R. Rodriguez wrote:
> Section ranges are on one of the types of custom sections
> types used in Linux.

Argh, come on, proof-read your changelog text please!

> This provides a series of helpers for
> defining them and using them. Most importantly this also
> enables us to avoid modifying the linker script when we
> add a new section range.

Also pick a line width and stick to it!

> It turns out a lot of custom sections are actually section ranges,
> and these are typically spelled out in their architecture specific
> asm/sections.h file -- we enable architectures to override what asm
> is used for section ranges but start by default trusting the
> asm-generic version all around.
> 
> Although typically you will not want to have section ranges ordered
> we must use SORT() on vmlinux.lds.S for section ranges to enable us
> to extend a section range without modifying the linker script. To
> accomplish this we use a special order string for the first element of a
> section range -- the empty string "" (refer to __SECTION_RANGE_BEGIN()),
> then "~" for the last element (refer to __SECTION_RANGE_BEGIN()). If
> you use the "any" order for elements in between and use SORT() you end
> up keeping any added element in between and a reference to the
> beginning and end of the section range without requiring custom linker
> script modifications. Specific order annotations are also supported
> to help construct synthetic functions, a demo for which will be provided
> later.

Again, split your documentation from your coding changes to make it
easier to review one or the other.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 03/14] ranges.h: add helpers to build and identify Linux section ranges
@ 2017-01-19 11:11             ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:11 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Sun, Jan 15, 2017 at 01:10:46PM -0800, Luis R. Rodriguez wrote:
> Section ranges are on one of the types of custom sections
> types used in Linux.

Argh, come on, proof-read your changelog text please!

> This provides a series of helpers for
> defining them and using them. Most importantly this also
> enables us to avoid modifying the linker script when we
> add a new section range.

Also pick a line width and stick to it!

> It turns out a lot of custom sections are actually section ranges,
> and these are typically spelled out in their architecture specific
> asm/sections.h file -- we enable architectures to override what asm
> is used for section ranges but start by default trusting the
> asm-generic version all around.
> 
> Although typically you will not want to have section ranges ordered
> we must use SORT() on vmlinux.lds.S for section ranges to enable us
> to extend a section range without modifying the linker script. To
> accomplish this we use a special order string for the first element of a
> section range -- the empty string "" (refer to __SECTION_RANGE_BEGIN()),
> then "~" for the last element (refer to __SECTION_RANGE_BEGIN()). If
> you use the "any" order for elements in between and use SORT() you end
> up keeping any added element in between and a reference to the
> beginning and end of the section range without requiring custom linker
> script modifications. Specific order annotations are also supported
> to help construct synthetic functions, a demo for which will be provided
> later.

Again, split your documentation from your coding changes to make it
easier to review one or the other.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 03/14] ranges.h: add helpers to build and identify Linux section ranges
@ 2017-01-19 11:11             ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:11 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley

On Sun, Jan 15, 2017 at 01:10:46PM -0800, Luis R. Rodriguez wrote:
> Section ranges are on one of the types of custom sections
> types used in Linux.

Argh, come on, proof-read your changelog text please!

> This provides a series of helpers for
> defining them and using them. Most importantly this also
> enables us to avoid modifying the linker script when we
> add a new section range.

Also pick a line width and stick to it!

> It turns out a lot of custom sections are actually section ranges,
> and these are typically spelled out in their architecture specific
> asm/sections.h file -- we enable architectures to override what asm
> is used for section ranges but start by default trusting the
> asm-generic version all around.
> 
> Although typically you will not want to have section ranges ordered
> we must use SORT() on vmlinux.lds.S for section ranges to enable us
> to extend a section range without modifying the linker script. To
> accomplish this we use a special order string for the first element of a
> section range -- the empty string "" (refer to __SECTION_RANGE_BEGIN()),
> then "~" for the last element (refer to __SECTION_RANGE_BEGIN()). If
> you use the "any" order for elements in between and use SORT() you end
> up keeping any added element in between and a reference to the
> beginning and end of the section range without requiring custom linker
> script modifications. Specific order annotations are also supported
> to help construct synthetic functions, a demo for which will be provided
> later.

Again, split your documentation from your coding changes to make it
easier to review one or the other.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 04/14] tables.h: add linker table support
  2017-01-15 21:10           ` Luis R. Rodriguez
  (?)
@ 2017-01-19 11:13             ` Greg KH
  -1 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:13 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Sun, Jan 15, 2017 at 01:10:47PM -0800, Luis R. Rodriguez wrote:
> 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.

Ok, I understand that, but then you say:

> The same philosophy is borrowed, extended and further simplified:

This line made no sense :(

> 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.

I have no idea why this is needed, nor what it means.  I fail to
understand the bit-rot reference.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 04/14] tables.h: add linker table support
@ 2017-01-19 11:13             ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:13 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Sun, Jan 15, 2017 at 01:10:47PM -0800, Luis R. Rodriguez wrote:
> 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.

Ok, I understand that, but then you say:

> The same philosophy is borrowed, extended and further simplified:

This line made no sense :(

> 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.

I have no idea why this is needed, nor what it means.  I fail to
understand the bit-rot reference.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 04/14] tables.h: add linker table support
@ 2017-01-19 11:13             ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:13 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley

On Sun, Jan 15, 2017 at 01:10:47PM -0800, Luis R. Rodriguez wrote:
> 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.

Ok, I understand that, but then you say:

> The same philosophy is borrowed, extended and further simplified:

This line made no sense :(

> 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.

I have no idea why this is needed, nor what it means.  I fail to
understand the bit-rot reference.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 05/14] kbuild: enable option to force compile force-obj-y and force-lib-y
  2017-01-15 21:10           ` Luis R. Rodriguez
  (?)
@ 2017-01-19 11:18             ` Greg KH
  -1 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:18 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Sun, Jan 15, 2017 at 01:10:48PM -0800, Luis R. Rodriguez wrote:
> Linux provides a rich array of features, enabling each feature
> however increases the size of the kernel and there are many
> features which users often want disabled. The traditional
> solution to this problem is for each feature to have its own
> Kconfig symbol, followed by a series of #ifdef statements
> in C code and header files, allowing the feature to be compiled
> only when desirable. As the variability of Linux increases build
> tests can and are often done with random kernel configurations,
> allyesconfig, and allmodconfig to help find code issues. This
> however doesn't catch all errors and as a consequence code that
> is typically not enabled often can suffer from bit-rot over time.

Really?  How do you know this, our test-build infrastructure is really
good, what has rotted with it?

And again, pick a column width and stick with it in the whole
changelog...

> An alternative approach for subsystems, which refer to as the 'build-all
> link-selectively philosophy' is to keep the Kconfig symbols, replace
> the #ifdef approach by having each feature implemented it its own C file,
> and force compilation for all features to avoid the code bit-rot problem.
> With this strategy only features that are enabled via Kconfig get
> linked into the kernel, so the forced compilation has no size impact
> on the kernel. The practice of having each feature implemented in its own
> C file is already prevalent in many subsystems, however #ifdefs are still
> typically required during feature initialization. For instance in:
> 
>   #ifdef CONFIG_FOO
>   foo_init();
>   #endif

That's horrid kernel code, and shouldn't be an example of anything other
than what NOT to do.  You know better than this, put the #ifdef in a .h
file.

> We cannot remove the #ifdef and leave foo_init() as we'd either
> need to always enable the feature or add a respective #ifdef in a
> foo.h which makes foo_init() do nothing when CONFIG_FOO is disabled.

Yes, and what's wrong with that?

> Linker tables enable lifting the requirement to use of #ifdefs during
> initialization. With linker tables initialization sequences can instead
> be aggregated into a custom ELF section at link time, during run time
> the table can be iterated over and each init sequence enabled can be
> called. A feature's init routine is only added to a table when its
> respective Kconfig symbols has been enabled and therefore linked in.
> Linker tables enable subsystems to completely do away with #ifdefs if
> one is comfortable in accepting all subsystem's feature's structural
> size implications.
> 
> Subsystems which want to follow the 'build-all link-selectively
> philosophy' still need a way to easily express and annotate that they
> wish for all code to always be compiled to help avoid code bit rot,
> as such two new targets force-obj-y and force-lib-y are provided to
> help with this. Its not fair to require everyone to force compilation
> of all features of a subsystem though, so as a compromise, the new
> targets only force compilation when CONFIG_BUILD_AVOID_BITROT is
> enabled.

You do know about COMPILE_TEST, right?  What's wrong with that?  Why not
use that as-is today and not add a new configuration option?

> Only built-in features are supported at the moment. Module support
> is expected to be added after a generic solution to add linker
> tables to modules more easily is developed.

Ok, you are talking about majorly changing how the kernel build system
works.  What do the kbuild developers/maintainers say about this?



> 
> v4: this patch was added to this series, it was split off from the
>     linker tables addition due to the confusion over the code bit
>     rot alternatives that are possible with linker tables.
> 
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  Documentation/kbuild/makefiles.txt       | 36 ++++++++++++++++
>  Documentation/sections/linker-tables.rst | 15 +++++++
>  include/linux/tables.h                   | 71 ++++++++++++++++++++++++++++++++
>  init/Kconfig                             | 22 ++++++++++
>  scripts/Makefile.build                   |  7 ++--
>  scripts/Makefile.clean                   |  2 +
>  scripts/Makefile.lib                     | 11 +++++
>  7 files changed, 161 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
> index 9b9c4797fc55..1af275cd4879 100644
> --- a/Documentation/kbuild/makefiles.txt
> +++ b/Documentation/kbuild/makefiles.txt
> @@ -1090,6 +1090,42 @@ When kbuild executes, the following steps are followed (roughly):
>  	In this example, extra-y is used to list object files that
>  	shall be built, but shall not be linked as part of built-in.o.
>  
> +    force-obj-y force-lib-y
> +
> +	When CONFIG_BUILD_AVOID_BITROT is enabled using these targets for your
> +	kconfig symbols forces compilation of the associated objects if the
> +	kconfig's symbol's dependencies are met, the objects however are only
> +	linked into to the kernel if and only if the kconfig symbol was
> +	enabled. If CONFIG_BUILD_AVOID_BITROT is disabled the force-obj-y and
> +	force-lib-y targets are functionally equilvalent to obj-y and lib-y
> +	respectively.
> +
> +	Using force-obj-y and force-lib-y are part of a code architecture and
> +	build philosophy further enabled by linker tables, for more details
> +	refer to the documention in include/linux/tables.h, refer to the
> +	sections:
> +
> +		o The code bit-rot problem
> +		o The build-all selective-link philosophy
> +		o Avoiding the code bit-rot problem with linker tables
> +		o Linker table module support
> +
> +	Modules support is expected to be enhanced in the future, so for now
> +	only built-in features are supported.
> +
> +	Example use:
> +
> +		force-obj-$(CONFIG_FEATURE_FOO) += foo.o
> +
> +	An alternative to using force-obj-y, is to use extra-y followed by the
> +	respective obj-y:
> +
> +		extra-y += foo.o
> +		obj-$(CONFIG_FEATURE_FOO) += foo.o
> +
> +	Using force-obj-y and force-lib-y can be used to help annotate the
> +	targets follow the 'build-all selective-link philosophy' further
> +	enabled by linker tables.
>  
>  --- 6.7 Commands useful for building a boot image
>  
> diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
> index 780a292d2d00..bc2d9f46cde6 100644
> --- a/Documentation/sections/linker-tables.rst
> +++ b/Documentation/sections/linker-tables.rst
> @@ -30,6 +30,21 @@ How linker tables simplify initialization code
>  .. kernel-doc:: include/linux/tables.h
>     :doc: How linker tables simplify initialization code
>  
> +The code bit-rot problem
> +------------------------
> +.. kernel-doc:: include/linux/tables.h
> +   :doc: The code bit-rot problem
> +
> +The build-all selective-link philosophy
> +---------------------------------------
> +.. kernel-doc:: include/linux/tables.h
> +   :doc: The build-all selective-link philosophy
> +
> +Avoiding the code bit-rot problem with linker tables
> +----------------------------------------------------
> +.. kernel-doc:: include/linux/tables.h
> +   :doc: Avoiding the code bit-rot problem with linker tables
> +
>  Using linker tables in Linux
>  ==============
>  
> diff --git a/include/linux/tables.h b/include/linux/tables.h
> index 82da59c4266d..f295fbe74734 100644
> --- a/include/linux/tables.h
> +++ b/include/linux/tables.h
> @@ -169,6 +169,77 @@
>   */
>  
>  /**
> + * DOC: The code bit-rot problem
> + *
> + * Linux provides a rich array of features, enabling each feature
> + * however increases the size of the kernel and there are many
> + * features which users often want disabled. The traditional
> + * solution to this problem is for each feature to have its own
> + * Kconfig symbol, followed by a series of #ifdef statements
> + * in C code and header files, allowing the feature to be compiled
> + * only when desirable. As the variability of Linux increases build
> + * tests can and are often done with random kernel configurations,
> + * allyesconfig, and allmodconfig to help find code issues. This
> + * however doesn't catch all errors and as a consequence code that
> + * is typically not enabled often can suffer from bit-rot over time.
> + */
> +
> +/**
> + * DOC: The build-all selective-link philosophy
> + *
> + * A code architecture philosophy to help avoid code bit-rot consists
> + * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
> + * by instead having each feature implemented it its own C file, and force
> + * compilation for all features. Only features that are enabled get linked in,
> + * the forced compilation therefore has no size impact on the final result of
> + * the kernel. The practice of having each feature implemented in its own C
> + * file is already prevalent in many subsystems, however #ifdefs are still
> + * typically required during feature initialization. For instance in::
> + *
> + *	#ifdef CONFIG_FOO
> + *	foo_init();
> + *	#endif
> + *
> + * We cannot remove the #ifdef and leave foo_init() as we'd either
> + * need to always enable the feature or add a respective #ifdef in a
> + * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
> + */
> +
> +/**
> + * DOC: Avoiding the code bit-rot problem with linker tables
> + *
> + * Linker tables can be used to further help avoid the code bit-rot problem
> + * when embracing the 'build-all selective-link philosophy' by lifting the
> + * requirement to use of #ifdefs during initialization. With linker tables
> + * initialization sequences can be aggregated into a custom ELF section at
> + * link time, during run time the table can be iterated over and each init
> + * sequence enabled can be called. A feature's init routine is only added to a
> + * table when its respective Kconfig symbols has been enabled and therefore
> + * linked in. Linker tables enable subsystems to completely do away with
> + * #ifdefs if one is comfortable in accepting all subsystem's feature's
> + * structural size implications.
> + *
> + * To further help with this the Linux build system supports two special
> + * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
> + * follow the 'build-all selective-link philosophy' can use these targets for a
> + * feature's kconfig symbol. Using these targets will always require
> + * compilation of the kconfig's objects if the kconfig symbol's dependencies
> + * are met but only link the objects into the kernel, and therefore enable the
> + * feature, if and only if the kconfig symbol has been enabled.
> + *
> + * Not all users or build systems may want to opt-in to compile all objects
> + * following the 'build-all selective-link philosophy', as such the targets
> + * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
> + * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
> + * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
> + * ``obj-y`` and ``lib-y`` respectively.
> + *
> + * Example use::
> + *
> + *	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
> + */
> +
> +/**
>   * DOC: Linker table module support
>   *
>   * Modules can use linker tables, however the linker table definition
> diff --git a/init/Kconfig b/init/Kconfig
> index 536c2a00d972..6272f4fdcc86 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -63,6 +63,28 @@ config CROSS_COMPILE
>  	  need to set this unless you want the configured kernel build
>  	  directory to select the cross-compiler automatically.
>  
> +config BUILD_AVOID_BITROT
> +	bool "Enable force building of force-obj-y and force-lib-y"
> +	default n
> +	help
> +	  When enabled objects under the force-obj-y and force-lib-y targets
> +	  using a Kconfig symbol will be forced to compile if the Kconfig
> +	  symbol's dependencies are met but only linked into the kernel if
> +	  the Kconfig symbol is enabled. If a Kconfig symbol on a force-obj-y
> +	  or force-lib-y target is disabled, it will be compiled but not linked
> +	  into the kernel.
> +
> +	  The force-obj-y and force-lib-y targets can be used by subsystems
> +	  which wish to want to follow the 'build-all selective-link philosophy'
> +	  documented under include/linux/tables.h.
> +
> +	  Say Y if you have a decent build machine and would like to help test
> +	  building code for more subsystems. Say N if you do you not have a
> +	  good build machine or only want to compile what you've enabled for
> +	  your kernel.
> +
> +	  Enabling this option never increases the size of your kernel.
> +
>  config COMPILE_TEST
>  	bool "Compile also drivers which will not load"
>  	depends on !UML

Pleaase use COMPILE_TEST here, we've already marked almost all drivers
with it today.  We also have really good build tools, including cross
compilers that you can use to test-build stuff on all different arches
if you feel you are somehow not building things you need to test-build.

I fail to see how this is going to do anything different from what we
have today, so why add it and have to maintain it?  Have you enabled it
on subsystems that currently do not get properly build tested and found
any issues?  What subsystems were they and why are they not in our
current build tests?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 05/14] kbuild: enable option to force compile force-obj-y and force-lib-y
@ 2017-01-19 11:18             ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:18 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Sun, Jan 15, 2017 at 01:10:48PM -0800, Luis R. Rodriguez wrote:
> Linux provides a rich array of features, enabling each feature
> however increases the size of the kernel and there are many
> features which users often want disabled. The traditional
> solution to this problem is for each feature to have its own
> Kconfig symbol, followed by a series of #ifdef statements
> in C code and header files, allowing the feature to be compiled
> only when desirable. As the variability of Linux increases build
> tests can and are often done with random kernel configurations,
> allyesconfig, and allmodconfig to help find code issues. This
> however doesn't catch all errors and as a consequence code that
> is typically not enabled often can suffer from bit-rot over time.

Really?  How do you know this, our test-build infrastructure is really
good, what has rotted with it?

And again, pick a column width and stick with it in the whole
changelog...

> An alternative approach for subsystems, which refer to as the 'build-all
> link-selectively philosophy' is to keep the Kconfig symbols, replace
> the #ifdef approach by having each feature implemented it its own C file,
> and force compilation for all features to avoid the code bit-rot problem.
> With this strategy only features that are enabled via Kconfig get
> linked into the kernel, so the forced compilation has no size impact
> on the kernel. The practice of having each feature implemented in its own
> C file is already prevalent in many subsystems, however #ifdefs are still
> typically required during feature initialization. For instance in:
> 
>   #ifdef CONFIG_FOO
>   foo_init();
>   #endif

That's horrid kernel code, and shouldn't be an example of anything other
than what NOT to do.  You know better than this, put the #ifdef in a .h
file.

> We cannot remove the #ifdef and leave foo_init() as we'd either
> need to always enable the feature or add a respective #ifdef in a
> foo.h which makes foo_init() do nothing when CONFIG_FOO is disabled.

Yes, and what's wrong with that?

> Linker tables enable lifting the requirement to use of #ifdefs during
> initialization. With linker tables initialization sequences can instead
> be aggregated into a custom ELF section at link time, during run time
> the table can be iterated over and each init sequence enabled can be
> called. A feature's init routine is only added to a table when its
> respective Kconfig symbols has been enabled and therefore linked in.
> Linker tables enable subsystems to completely do away with #ifdefs if
> one is comfortable in accepting all subsystem's feature's structural
> size implications.
> 
> Subsystems which want to follow the 'build-all link-selectively
> philosophy' still need a way to easily express and annotate that they
> wish for all code to always be compiled to help avoid code bit rot,
> as such two new targets force-obj-y and force-lib-y are provided to
> help with this. Its not fair to require everyone to force compilation
> of all features of a subsystem though, so as a compromise, the new
> targets only force compilation when CONFIG_BUILD_AVOID_BITROT is
> enabled.

You do know about COMPILE_TEST, right?  What's wrong with that?  Why not
use that as-is today and not add a new configuration option?

> Only built-in features are supported at the moment. Module support
> is expected to be added after a generic solution to add linker
> tables to modules more easily is developed.

Ok, you are talking about majorly changing how the kernel build system
works.  What do the kbuild developers/maintainers say about this?



> 
> v4: this patch was added to this series, it was split off from the
>     linker tables addition due to the confusion over the code bit
>     rot alternatives that are possible with linker tables.
> 
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  Documentation/kbuild/makefiles.txt       | 36 ++++++++++++++++
>  Documentation/sections/linker-tables.rst | 15 +++++++
>  include/linux/tables.h                   | 71 ++++++++++++++++++++++++++++++++
>  init/Kconfig                             | 22 ++++++++++
>  scripts/Makefile.build                   |  7 ++--
>  scripts/Makefile.clean                   |  2 +
>  scripts/Makefile.lib                     | 11 +++++
>  7 files changed, 161 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
> index 9b9c4797fc55..1af275cd4879 100644
> --- a/Documentation/kbuild/makefiles.txt
> +++ b/Documentation/kbuild/makefiles.txt
> @@ -1090,6 +1090,42 @@ When kbuild executes, the following steps are followed (roughly):
>  	In this example, extra-y is used to list object files that
>  	shall be built, but shall not be linked as part of built-in.o.
>  
> +    force-obj-y force-lib-y
> +
> +	When CONFIG_BUILD_AVOID_BITROT is enabled using these targets for your
> +	kconfig symbols forces compilation of the associated objects if the
> +	kconfig's symbol's dependencies are met, the objects however are only
> +	linked into to the kernel if and only if the kconfig symbol was
> +	enabled. If CONFIG_BUILD_AVOID_BITROT is disabled the force-obj-y and
> +	force-lib-y targets are functionally equilvalent to obj-y and lib-y
> +	respectively.
> +
> +	Using force-obj-y and force-lib-y are part of a code architecture and
> +	build philosophy further enabled by linker tables, for more details
> +	refer to the documention in include/linux/tables.h, refer to the
> +	sections:
> +
> +		o The code bit-rot problem
> +		o The build-all selective-link philosophy
> +		o Avoiding the code bit-rot problem with linker tables
> +		o Linker table module support
> +
> +	Modules support is expected to be enhanced in the future, so for now
> +	only built-in features are supported.
> +
> +	Example use:
> +
> +		force-obj-$(CONFIG_FEATURE_FOO) += foo.o
> +
> +	An alternative to using force-obj-y, is to use extra-y followed by the
> +	respective obj-y:
> +
> +		extra-y += foo.o
> +		obj-$(CONFIG_FEATURE_FOO) += foo.o
> +
> +	Using force-obj-y and force-lib-y can be used to help annotate the
> +	targets follow the 'build-all selective-link philosophy' further
> +	enabled by linker tables.
>  
>  --- 6.7 Commands useful for building a boot image
>  
> diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
> index 780a292d2d00..bc2d9f46cde6 100644
> --- a/Documentation/sections/linker-tables.rst
> +++ b/Documentation/sections/linker-tables.rst
> @@ -30,6 +30,21 @@ How linker tables simplify initialization code
>  .. kernel-doc:: include/linux/tables.h
>     :doc: How linker tables simplify initialization code
>  
> +The code bit-rot problem
> +------------------------
> +.. kernel-doc:: include/linux/tables.h
> +   :doc: The code bit-rot problem
> +
> +The build-all selective-link philosophy
> +---------------------------------------
> +.. kernel-doc:: include/linux/tables.h
> +   :doc: The build-all selective-link philosophy
> +
> +Avoiding the code bit-rot problem with linker tables
> +----------------------------------------------------
> +.. kernel-doc:: include/linux/tables.h
> +   :doc: Avoiding the code bit-rot problem with linker tables
> +
>  Using linker tables in Linux
>  ============================
>  
> diff --git a/include/linux/tables.h b/include/linux/tables.h
> index 82da59c4266d..f295fbe74734 100644
> --- a/include/linux/tables.h
> +++ b/include/linux/tables.h
> @@ -169,6 +169,77 @@
>   */
>  
>  /**
> + * DOC: The code bit-rot problem
> + *
> + * Linux provides a rich array of features, enabling each feature
> + * however increases the size of the kernel and there are many
> + * features which users often want disabled. The traditional
> + * solution to this problem is for each feature to have its own
> + * Kconfig symbol, followed by a series of #ifdef statements
> + * in C code and header files, allowing the feature to be compiled
> + * only when desirable. As the variability of Linux increases build
> + * tests can and are often done with random kernel configurations,
> + * allyesconfig, and allmodconfig to help find code issues. This
> + * however doesn't catch all errors and as a consequence code that
> + * is typically not enabled often can suffer from bit-rot over time.
> + */
> +
> +/**
> + * DOC: The build-all selective-link philosophy
> + *
> + * A code architecture philosophy to help avoid code bit-rot consists
> + * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
> + * by instead having each feature implemented it its own C file, and force
> + * compilation for all features. Only features that are enabled get linked in,
> + * the forced compilation therefore has no size impact on the final result of
> + * the kernel. The practice of having each feature implemented in its own C
> + * file is already prevalent in many subsystems, however #ifdefs are still
> + * typically required during feature initialization. For instance in::
> + *
> + *	#ifdef CONFIG_FOO
> + *	foo_init();
> + *	#endif
> + *
> + * We cannot remove the #ifdef and leave foo_init() as we'd either
> + * need to always enable the feature or add a respective #ifdef in a
> + * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
> + */
> +
> +/**
> + * DOC: Avoiding the code bit-rot problem with linker tables
> + *
> + * Linker tables can be used to further help avoid the code bit-rot problem
> + * when embracing the 'build-all selective-link philosophy' by lifting the
> + * requirement to use of #ifdefs during initialization. With linker tables
> + * initialization sequences can be aggregated into a custom ELF section at
> + * link time, during run time the table can be iterated over and each init
> + * sequence enabled can be called. A feature's init routine is only added to a
> + * table when its respective Kconfig symbols has been enabled and therefore
> + * linked in. Linker tables enable subsystems to completely do away with
> + * #ifdefs if one is comfortable in accepting all subsystem's feature's
> + * structural size implications.
> + *
> + * To further help with this the Linux build system supports two special
> + * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
> + * follow the 'build-all selective-link philosophy' can use these targets for a
> + * feature's kconfig symbol. Using these targets will always require
> + * compilation of the kconfig's objects if the kconfig symbol's dependencies
> + * are met but only link the objects into the kernel, and therefore enable the
> + * feature, if and only if the kconfig symbol has been enabled.
> + *
> + * Not all users or build systems may want to opt-in to compile all objects
> + * following the 'build-all selective-link philosophy', as such the targets
> + * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
> + * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
> + * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
> + * ``obj-y`` and ``lib-y`` respectively.
> + *
> + * Example use::
> + *
> + *	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
> + */
> +
> +/**
>   * DOC: Linker table module support
>   *
>   * Modules can use linker tables, however the linker table definition
> diff --git a/init/Kconfig b/init/Kconfig
> index 536c2a00d972..6272f4fdcc86 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -63,6 +63,28 @@ config CROSS_COMPILE
>  	  need to set this unless you want the configured kernel build
>  	  directory to select the cross-compiler automatically.
>  
> +config BUILD_AVOID_BITROT
> +	bool "Enable force building of force-obj-y and force-lib-y"
> +	default n
> +	help
> +	  When enabled objects under the force-obj-y and force-lib-y targets
> +	  using a Kconfig symbol will be forced to compile if the Kconfig
> +	  symbol's dependencies are met but only linked into the kernel if
> +	  the Kconfig symbol is enabled. If a Kconfig symbol on a force-obj-y
> +	  or force-lib-y target is disabled, it will be compiled but not linked
> +	  into the kernel.
> +
> +	  The force-obj-y and force-lib-y targets can be used by subsystems
> +	  which wish to want to follow the 'build-all selective-link philosophy'
> +	  documented under include/linux/tables.h.
> +
> +	  Say Y if you have a decent build machine and would like to help test
> +	  building code for more subsystems. Say N if you do you not have a
> +	  good build machine or only want to compile what you've enabled for
> +	  your kernel.
> +
> +	  Enabling this option never increases the size of your kernel.
> +
>  config COMPILE_TEST
>  	bool "Compile also drivers which will not load"
>  	depends on !UML

Pleaase use COMPILE_TEST here, we've already marked almost all drivers
with it today.  We also have really good build tools, including cross
compilers that you can use to test-build stuff on all different arches
if you feel you are somehow not building things you need to test-build.

I fail to see how this is going to do anything different from what we
have today, so why add it and have to maintain it?  Have you enabled it
on subsystems that currently do not get properly build tested and found
any issues?  What subsystems were they and why are they not in our
current build tests?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 05/14] kbuild: enable option to force compile force-obj-y and force-lib-y
@ 2017-01-19 11:18             ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:18 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley

On Sun, Jan 15, 2017 at 01:10:48PM -0800, Luis R. Rodriguez wrote:
> Linux provides a rich array of features, enabling each feature
> however increases the size of the kernel and there are many
> features which users often want disabled. The traditional
> solution to this problem is for each feature to have its own
> Kconfig symbol, followed by a series of #ifdef statements
> in C code and header files, allowing the feature to be compiled
> only when desirable. As the variability of Linux increases build
> tests can and are often done with random kernel configurations,
> allyesconfig, and allmodconfig to help find code issues. This
> however doesn't catch all errors and as a consequence code that
> is typically not enabled often can suffer from bit-rot over time.

Really?  How do you know this, our test-build infrastructure is really
good, what has rotted with it?

And again, pick a column width and stick with it in the whole
changelog...

> An alternative approach for subsystems, which refer to as the 'build-all
> link-selectively philosophy' is to keep the Kconfig symbols, replace
> the #ifdef approach by having each feature implemented it its own C file,
> and force compilation for all features to avoid the code bit-rot problem.
> With this strategy only features that are enabled via Kconfig get
> linked into the kernel, so the forced compilation has no size impact
> on the kernel. The practice of having each feature implemented in its own
> C file is already prevalent in many subsystems, however #ifdefs are still
> typically required during feature initialization. For instance in:
> 
>   #ifdef CONFIG_FOO
>   foo_init();
>   #endif

That's horrid kernel code, and shouldn't be an example of anything other
than what NOT to do.  You know better than this, put the #ifdef in a .h
file.

> We cannot remove the #ifdef and leave foo_init() as we'd either
> need to always enable the feature or add a respective #ifdef in a
> foo.h which makes foo_init() do nothing when CONFIG_FOO is disabled.

Yes, and what's wrong with that?

> Linker tables enable lifting the requirement to use of #ifdefs during
> initialization. With linker tables initialization sequences can instead
> be aggregated into a custom ELF section at link time, during run time
> the table can be iterated over and each init sequence enabled can be
> called. A feature's init routine is only added to a table when its
> respective Kconfig symbols has been enabled and therefore linked in.
> Linker tables enable subsystems to completely do away with #ifdefs if
> one is comfortable in accepting all subsystem's feature's structural
> size implications.
> 
> Subsystems which want to follow the 'build-all link-selectively
> philosophy' still need a way to easily express and annotate that they
> wish for all code to always be compiled to help avoid code bit rot,
> as such two new targets force-obj-y and force-lib-y are provided to
> help with this. Its not fair to require everyone to force compilation
> of all features of a subsystem though, so as a compromise, the new
> targets only force compilation when CONFIG_BUILD_AVOID_BITROT is
> enabled.

You do know about COMPILE_TEST, right?  What's wrong with that?  Why not
use that as-is today and not add a new configuration option?

> Only built-in features are supported at the moment. Module support
> is expected to be added after a generic solution to add linker
> tables to modules more easily is developed.

Ok, you are talking about majorly changing how the kernel build system
works.  What do the kbuild developers/maintainers say about this?



> 
> v4: this patch was added to this series, it was split off from the
>     linker tables addition due to the confusion over the code bit
>     rot alternatives that are possible with linker tables.
> 
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  Documentation/kbuild/makefiles.txt       | 36 ++++++++++++++++
>  Documentation/sections/linker-tables.rst | 15 +++++++
>  include/linux/tables.h                   | 71 ++++++++++++++++++++++++++++++++
>  init/Kconfig                             | 22 ++++++++++
>  scripts/Makefile.build                   |  7 ++--
>  scripts/Makefile.clean                   |  2 +
>  scripts/Makefile.lib                     | 11 +++++
>  7 files changed, 161 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
> index 9b9c4797fc55..1af275cd4879 100644
> --- a/Documentation/kbuild/makefiles.txt
> +++ b/Documentation/kbuild/makefiles.txt
> @@ -1090,6 +1090,42 @@ When kbuild executes, the following steps are followed (roughly):
>  	In this example, extra-y is used to list object files that
>  	shall be built, but shall not be linked as part of built-in.o.
>  
> +    force-obj-y force-lib-y
> +
> +	When CONFIG_BUILD_AVOID_BITROT is enabled using these targets for your
> +	kconfig symbols forces compilation of the associated objects if the
> +	kconfig's symbol's dependencies are met, the objects however are only
> +	linked into to the kernel if and only if the kconfig symbol was
> +	enabled. If CONFIG_BUILD_AVOID_BITROT is disabled the force-obj-y and
> +	force-lib-y targets are functionally equilvalent to obj-y and lib-y
> +	respectively.
> +
> +	Using force-obj-y and force-lib-y are part of a code architecture and
> +	build philosophy further enabled by linker tables, for more details
> +	refer to the documention in include/linux/tables.h, refer to the
> +	sections:
> +
> +		o The code bit-rot problem
> +		o The build-all selective-link philosophy
> +		o Avoiding the code bit-rot problem with linker tables
> +		o Linker table module support
> +
> +	Modules support is expected to be enhanced in the future, so for now
> +	only built-in features are supported.
> +
> +	Example use:
> +
> +		force-obj-$(CONFIG_FEATURE_FOO) += foo.o
> +
> +	An alternative to using force-obj-y, is to use extra-y followed by the
> +	respective obj-y:
> +
> +		extra-y += foo.o
> +		obj-$(CONFIG_FEATURE_FOO) += foo.o
> +
> +	Using force-obj-y and force-lib-y can be used to help annotate the
> +	targets follow the 'build-all selective-link philosophy' further
> +	enabled by linker tables.
>  
>  --- 6.7 Commands useful for building a boot image
>  
> diff --git a/Documentation/sections/linker-tables.rst b/Documentation/sections/linker-tables.rst
> index 780a292d2d00..bc2d9f46cde6 100644
> --- a/Documentation/sections/linker-tables.rst
> +++ b/Documentation/sections/linker-tables.rst
> @@ -30,6 +30,21 @@ How linker tables simplify initialization code
>  .. kernel-doc:: include/linux/tables.h
>     :doc: How linker tables simplify initialization code
>  
> +The code bit-rot problem
> +------------------------
> +.. kernel-doc:: include/linux/tables.h
> +   :doc: The code bit-rot problem
> +
> +The build-all selective-link philosophy
> +---------------------------------------
> +.. kernel-doc:: include/linux/tables.h
> +   :doc: The build-all selective-link philosophy
> +
> +Avoiding the code bit-rot problem with linker tables
> +----------------------------------------------------
> +.. kernel-doc:: include/linux/tables.h
> +   :doc: Avoiding the code bit-rot problem with linker tables
> +
>  Using linker tables in Linux
>  ============================
>  
> diff --git a/include/linux/tables.h b/include/linux/tables.h
> index 82da59c4266d..f295fbe74734 100644
> --- a/include/linux/tables.h
> +++ b/include/linux/tables.h
> @@ -169,6 +169,77 @@
>   */
>  
>  /**
> + * DOC: The code bit-rot problem
> + *
> + * Linux provides a rich array of features, enabling each feature
> + * however increases the size of the kernel and there are many
> + * features which users often want disabled. The traditional
> + * solution to this problem is for each feature to have its own
> + * Kconfig symbol, followed by a series of #ifdef statements
> + * in C code and header files, allowing the feature to be compiled
> + * only when desirable. As the variability of Linux increases build
> + * tests can and are often done with random kernel configurations,
> + * allyesconfig, and allmodconfig to help find code issues. This
> + * however doesn't catch all errors and as a consequence code that
> + * is typically not enabled often can suffer from bit-rot over time.
> + */
> +
> +/**
> + * DOC: The build-all selective-link philosophy
> + *
> + * A code architecture philosophy to help avoid code bit-rot consists
> + * of using Kconfig symbols for each subsystem feature, replace all #ifdefs
> + * by instead having each feature implemented it its own C file, and force
> + * compilation for all features. Only features that are enabled get linked in,
> + * the forced compilation therefore has no size impact on the final result of
> + * the kernel. The practice of having each feature implemented in its own C
> + * file is already prevalent in many subsystems, however #ifdefs are still
> + * typically required during feature initialization. For instance in::
> + *
> + *	#ifdef CONFIG_FOO
> + *	foo_init();
> + *	#endif
> + *
> + * We cannot remove the #ifdef and leave foo_init() as we'd either
> + * need to always enable the feature or add a respective #ifdef in a
> + * foo.h which makes foo_init() do nothing when ``CONFIG_FOO`` is disabled.
> + */
> +
> +/**
> + * DOC: Avoiding the code bit-rot problem with linker tables
> + *
> + * Linker tables can be used to further help avoid the code bit-rot problem
> + * when embracing the 'build-all selective-link philosophy' by lifting the
> + * requirement to use of #ifdefs during initialization. With linker tables
> + * initialization sequences can be aggregated into a custom ELF section at
> + * link time, during run time the table can be iterated over and each init
> + * sequence enabled can be called. A feature's init routine is only added to a
> + * table when its respective Kconfig symbols has been enabled and therefore
> + * linked in. Linker tables enable subsystems to completely do away with
> + * #ifdefs if one is comfortable in accepting all subsystem's feature's
> + * structural size implications.
> + *
> + * To further help with this the Linux build system supports two special
> + * targets, ``force-obj-y`` and ``force-lib-y``. A subsystem which wants to
> + * follow the 'build-all selective-link philosophy' can use these targets for a
> + * feature's kconfig symbol. Using these targets will always require
> + * compilation of the kconfig's objects if the kconfig symbol's dependencies
> + * are met but only link the objects into the kernel, and therefore enable the
> + * feature, if and only if the kconfig symbol has been enabled.
> + *
> + * Not all users or build systems may want to opt-in to compile all objects
> + * following the 'build-all selective-link philosophy', as such the targets
> + * ``force-obj-y`` and ``force-lib-y`` only force compilation when the kconfig
> + * symbol ``CONFIG_BUILD_AVOID_BITROT`` has been enabled. Disabling this feature
> + * makes ``force-obj-y`` and ``force-lib-y`` functionally equivalent to
> + * ``obj-y`` and ``lib-y`` respectively.
> + *
> + * Example use::
> + *
> + *	force-obj-$(CONFIG_FEATURE_FOO) += foo.o
> + */
> +
> +/**
>   * DOC: Linker table module support
>   *
>   * Modules can use linker tables, however the linker table definition
> diff --git a/init/Kconfig b/init/Kconfig
> index 536c2a00d972..6272f4fdcc86 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -63,6 +63,28 @@ config CROSS_COMPILE
>  	  need to set this unless you want the configured kernel build
>  	  directory to select the cross-compiler automatically.
>  
> +config BUILD_AVOID_BITROT
> +	bool "Enable force building of force-obj-y and force-lib-y"
> +	default n
> +	help
> +	  When enabled objects under the force-obj-y and force-lib-y targets
> +	  using a Kconfig symbol will be forced to compile if the Kconfig
> +	  symbol's dependencies are met but only linked into the kernel if
> +	  the Kconfig symbol is enabled. If a Kconfig symbol on a force-obj-y
> +	  or force-lib-y target is disabled, it will be compiled but not linked
> +	  into the kernel.
> +
> +	  The force-obj-y and force-lib-y targets can be used by subsystems
> +	  which wish to want to follow the 'build-all selective-link philosophy'
> +	  documented under include/linux/tables.h.
> +
> +	  Say Y if you have a decent build machine and would like to help test
> +	  building code for more subsystems. Say N if you do you not have a
> +	  good build machine or only want to compile what you've enabled for
> +	  your kernel.
> +
> +	  Enabling this option never increases the size of your kernel.
> +
>  config COMPILE_TEST
>  	bool "Compile also drivers which will not load"
>  	depends on !UML

Pleaase use COMPILE_TEST here, we've already marked almost all drivers
with it today.  We also have really good build tools, including cross
compilers that you can use to test-build stuff on all different arches
if you feel you are somehow not building things you need to test-build.

I fail to see how this is going to do anything different from what we
have today, so why add it and have to maintain it?  Have you enabled it
on subsystems that currently do not get properly build tested and found
any issues?  What subsystems were they and why are they not in our
current build tests?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 06/14] firmware/Makefile: force recompilation if makefile changes
  2017-01-15 21:10           ` Luis R. Rodriguez
  (?)
@ 2017-01-19 11:19             ` Greg KH
  -1 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:19 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Sun, Jan 15, 2017 at 01:10:49PM -0800, Luis R. Rodriguez wrote:
> If you modify the target asm we currently do not force the
> recompilation of the firmware files. The target asm is in
> the firmware/Makefile, peg this file as a dependency to
> require re-compilation of firmware targets when the asm
> changes.
> 
> v3: introduced in this series
> 
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  firmware/Makefile | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/firmware/Makefile b/firmware/Makefile
> index e297e1b52636..fa3e81c2a97b 100644
> --- a/firmware/Makefile
> +++ b/firmware/Makefile
> @@ -176,7 +176,8 @@ quiet_cmd_fwbin = MK_FW   $@
>  wordsize_deps := $(wildcard include/config/64bit.h include/config/32bit.h \
>  		include/config/ppc32.h include/config/ppc64.h \
>  		include/config/superh32.h include/config/superh64.h \
> -		include/config/x86_32.h include/config/x86_64.h)
> +		include/config/x86_32.h include/config/x86_64.h \
> +		firmware/Makefile)
>  
>  $(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)): %: $(wordsize_deps)
>  	$(call cmd,fwbin,$(patsubst %.gen.S,%,$@))

I don't understand why this patch is in this series :(

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 06/14] firmware/Makefile: force recompilation if makefile changes
@ 2017-01-19 11:19             ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:19 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Sun, Jan 15, 2017 at 01:10:49PM -0800, Luis R. Rodriguez wrote:
> If you modify the target asm we currently do not force the
> recompilation of the firmware files. The target asm is in
> the firmware/Makefile, peg this file as a dependency to
> require re-compilation of firmware targets when the asm
> changes.
> 
> v3: introduced in this series
> 
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  firmware/Makefile | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/firmware/Makefile b/firmware/Makefile
> index e297e1b52636..fa3e81c2a97b 100644
> --- a/firmware/Makefile
> +++ b/firmware/Makefile
> @@ -176,7 +176,8 @@ quiet_cmd_fwbin = MK_FW   $@
>  wordsize_deps := $(wildcard include/config/64bit.h include/config/32bit.h \
>  		include/config/ppc32.h include/config/ppc64.h \
>  		include/config/superh32.h include/config/superh64.h \
> -		include/config/x86_32.h include/config/x86_64.h)
> +		include/config/x86_32.h include/config/x86_64.h \
> +		firmware/Makefile)
>  
>  $(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)): %: $(wordsize_deps)
>  	$(call cmd,fwbin,$(patsubst %.gen.S,%,$@))

I don't understand why this patch is in this series :(

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 06/14] firmware/Makefile: force recompilation if makefile changes
@ 2017-01-19 11:19             ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:19 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley

On Sun, Jan 15, 2017 at 01:10:49PM -0800, Luis R. Rodriguez wrote:
> If you modify the target asm we currently do not force the
> recompilation of the firmware files. The target asm is in
> the firmware/Makefile, peg this file as a dependency to
> require re-compilation of firmware targets when the asm
> changes.
> 
> v3: introduced in this series
> 
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  firmware/Makefile | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/firmware/Makefile b/firmware/Makefile
> index e297e1b52636..fa3e81c2a97b 100644
> --- a/firmware/Makefile
> +++ b/firmware/Makefile
> @@ -176,7 +176,8 @@ quiet_cmd_fwbin = MK_FW   $@
>  wordsize_deps := $(wildcard include/config/64bit.h include/config/32bit.h \
>  		include/config/ppc32.h include/config/ppc64.h \
>  		include/config/superh32.h include/config/superh64.h \
> -		include/config/x86_32.h include/config/x86_64.h)
> +		include/config/x86_32.h include/config/x86_64.h \
> +		firmware/Makefile)
>  
>  $(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)): %: $(wordsize_deps)
>  	$(call cmd,fwbin,$(patsubst %.gen.S,%,$@))

I don't understand why this patch is in this series :(

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 08/14] jump_label: move guard #endif down where it belongs
  2017-01-15 21:10           ` Luis R. Rodriguez
  (?)
@ 2017-01-19 11:20             ` Greg KH
  -1 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:20 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Sun, Jan 15, 2017 at 01:10:51PM -0800, Luis R. Rodriguez wrote:
> The ending header guard is misplaced. This has no
> functional change, this is just an eye-sore.
> 
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  include/linux/jump_label.h | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
> index a0547c571800..b63d6b7b0db0 100644
> --- a/include/linux/jump_label.h
> +++ b/include/linux/jump_label.h
> @@ -402,6 +402,6 @@ extern bool ____wrong_branch_error(void);
>  #define static_branch_enable(x)		static_key_enable(&(x)->key)
>  #define static_branch_disable(x)	static_key_disable(&(x)->key)
>  
> -#endif	/* _LINUX_JUMP_LABEL_H */
> -
>  #endif /* __ASSEMBLY__ */
> +
> +#endif	/* _LINUX_JUMP_LABEL_H */
> -- 
> 2.11.0

Why is this in this patch series?

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 08/14] jump_label: move guard #endif down where it belongs
@ 2017-01-19 11:20             ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:20 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30

On Sun, Jan 15, 2017 at 01:10:51PM -0800, Luis R. Rodriguez wrote:
> The ending header guard is misplaced. This has no
> functional change, this is just an eye-sore.
> 
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  include/linux/jump_label.h | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
> index a0547c571800..b63d6b7b0db0 100644
> --- a/include/linux/jump_label.h
> +++ b/include/linux/jump_label.h
> @@ -402,6 +402,6 @@ extern bool ____wrong_branch_error(void);
>  #define static_branch_enable(x)		static_key_enable(&(x)->key)
>  #define static_branch_disable(x)	static_key_disable(&(x)->key)
>  
> -#endif	/* _LINUX_JUMP_LABEL_H */
> -
>  #endif /* __ASSEMBLY__ */
> +
> +#endif	/* _LINUX_JUMP_LABEL_H */
> -- 
> 2.11.0

Why is this in this patch series?

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 08/14] jump_label: move guard #endif down where it belongs
@ 2017-01-19 11:20             ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:20 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley

On Sun, Jan 15, 2017 at 01:10:51PM -0800, Luis R. Rodriguez wrote:
> The ending header guard is misplaced. This has no
> functional change, this is just an eye-sore.
> 
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  include/linux/jump_label.h | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
> index a0547c571800..b63d6b7b0db0 100644
> --- a/include/linux/jump_label.h
> +++ b/include/linux/jump_label.h
> @@ -402,6 +402,6 @@ extern bool ____wrong_branch_error(void);
>  #define static_branch_enable(x)		static_key_enable(&(x)->key)
>  #define static_branch_disable(x)	static_key_disable(&(x)->key)
>  
> -#endif	/* _LINUX_JUMP_LABEL_H */
> -
>  #endif /* __ASSEMBLY__ */
> +
> +#endif	/* _LINUX_JUMP_LABEL_H */
> -- 
> 2.11.0

Why is this in this patch series?

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 09/14] jump_label: port __jump_table to linker tables
  2017-01-15 21:10           ` Luis R. Rodriguez
  (?)
@ 2017-01-19 11:24             ` Greg KH
  -1 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:24 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: gnomes, dalias, linux-ia64, jkosina, benh, ming.lei,
	heiko.carstens, platform-driver-x86, James.Bottomley,
	paul.gortmaker, paulus, mpe, hpa, masami.hiramatsu.pt, wangnan0,
	mchehab, linux-arch, markus.heiser, sparclinux, xen-devel, linux,
	linux-sh, will.deacon, korea.drzix, x86, anil.s.keshavamurthy,
	fontana, mingo, dsahern, linux-arm-kernel, catalin.marinas,
	dvhart, bp, linux, david.vrabel, linux-xtensa

On Sun, Jan 15, 2017 at 01:10:52PM -0800, Luis R. Rodriguez wrote:
> Move the __jump_table from the a custom section solution
> to a generic solution, this avoiding extra vmlinux.lds.h
> customizations.
> 
> This also demos the use of the .data linker table and of
> the shared asm call push_section_tbl().
> 
> Built-in kernel functionality was tested with CONFIG_STATIC_KEYS_SELFTEST.
> Moduler  kernel functionality was tested with CONFIG_TEST_STATIC_KEYS.
> Both work as expected.
> 
> Since __jump_table sections are also supported per
> module this also required expanding module-common.lds.S
> to capture and fold all .data.tlb.__jump_table.* onto
> the the section __jump_table -- in this case for modules
> need to keep a reference in place, given the alternative
> is to use DEFINE_LINKTABLE(struct jump_entry, __jump_table)
> per module -- and later through macro hacks instantiate
> the jump entries per module upon init. This is doable but
> we'd loose out on the sorting of the table using the
> linker, to sort we'd always still need to expand the
> module common linker script. An alternative mechanism
> is possible which would make these custom module sections
> extensions dynamic without requiring manual changes, this
> however is best done later through a separate evolution
> once linker tables are in place.
> 
> A careful reviewer may note that some architectures use
> "\n\t" to separate asm code, while others just use a new line.
> Upon review last time it was deemed reasonable to for all
> architectures to just use "\n", this is defined as ASM_CMD_SEP,
> and if an architecture needs to override they can do so on their
> architecture sections.h prior to including asm-generic/sections.h
> 
> v6: rename table macro as suggested by Andy Shevchenko
> 
> v5:
> 
> o Use ..tbl instead of .tbl as suggested by Nicholas Piggin.
>   This is the typical way to avoid clash with compiler generated
>   section.
> 
> o Replace section macros with section names
> 
> o Use LINKTABLE_START() and LINKTABLE_END()
> 
> o fixed tile jump label port -- tile got jump label support as of
>   commit 65a792e84f25d1 ("tile/jump_label: add jump label support
>   for TILE-Gx"), as such we just needed to adjust the asm to account
>   for the new linker table API use. This commit was merged as of v4.5-rc1.
> 
> v4:
> 
> o Some architectures allow linker scripts to follow including header
>   files, some others do not, so if you need a helper on a linker script
>   you need to explicitly include it. So for instance although
>   scripts/module-common.lds.S includes <asm/tables.h> and this file
>   includes <asm/section-core.h>, you still need to explicitly
>   include it on the linker script. This issue is present on ARM.
> 
> o as per Josh Poimboeuf open code the section table name instead
>   of including the kernel section headers, the simplicity and
>   independence from the kernel is preferred.
> 
> v3:
> 
> o More elaborate tests performed
> o first modular support use case, module tested was
>   CONFIG_TEST_STATIC_KEYS (lib/test_static_keys.ko), this
>   required us to extend module-common.lds.S
> o use generic push_section_tbl_any() for all architectures
> o Makes use of ASM_CMD_SEP to enable architectures to override later
>   if needed
> o guard tables.h inclusion and table definition with __KERNEL__
> 
> v2: introduced in this series
> 
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  arch/arm/include/asm/jump_label.h     |  6 ++++--
>  arch/arm64/include/asm/jump_label.h   |  6 ++++--
>  arch/mips/include/asm/jump_label.h    |  6 ++++--
>  arch/powerpc/include/asm/jump_label.h |  8 +++++---
>  arch/s390/include/asm/jump_label.h    |  6 ++++--
>  arch/sparc/include/asm/jump_label.h   |  6 ++++--
>  arch/tile/include/asm/jump_label.h    |  5 +++--
>  arch/x86/include/asm/jump_label.h     | 10 ++++++----
>  include/asm-generic/vmlinux.lds.h     |  5 -----
>  include/linux/jump_label.h            |  4 ++--
>  kernel/jump_label.c                   | 17 ++++++++++-------
>  scripts/module-common.lds             |  1 +
>  tools/objtool/special.c               |  2 +-
>  13 files changed, 48 insertions(+), 34 deletions(-)

meta-comment.  This new infrastructure doesn't seem to save any code
when you need to have a new "link table".  Yes, the macros seem a bit
nicer, but it feels like unneeded churn.  I haven't seen any patches in
this series that makes me go "oh yeah, now I see why he did this work,
it's so much simpler and easy to understand now!"

What am I missing?  What wonderful new things are going to happen, or
where is the code savings going to come from with this series to justify
all of the work to create and review this?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 09/14] jump_label: port __jump_table to linker tables
@ 2017-01-19 11:24             ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:24 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: gnomes, dalias, linux-ia64, jkosina, benh, ming.lei,
	heiko.carstens, platform-driver-x86, James.Bottomley,
	paul.gortmaker, paulus, mpe, hpa, masami.hiramatsu.pt, wangnan0,
	mchehab, linux-arch, markus.heiser, sparclinux, xen-devel, linux,
	linux-sh, will.deacon, korea.drzix, x86, anil.s.keshavamurthy,
	fontana, mingo, dsahern, linux-arm-kernel, catalin.marinas,
	dvhart, bp, linux, david.vrabel, linux-xtensa

On Sun, Jan 15, 2017 at 01:10:52PM -0800, Luis R. Rodriguez wrote:
> Move the __jump_table from the a custom section solution
> to a generic solution, this avoiding extra vmlinux.lds.h
> customizations.
> 
> This also demos the use of the .data linker table and of
> the shared asm call push_section_tbl().
> 
> Built-in kernel functionality was tested with CONFIG_STATIC_KEYS_SELFTEST.
> Moduler  kernel functionality was tested with CONFIG_TEST_STATIC_KEYS.
> Both work as expected.
> 
> Since __jump_table sections are also supported per
> module this also required expanding module-common.lds.S
> to capture and fold all .data.tlb.__jump_table.* onto
> the the section __jump_table -- in this case for modules
> need to keep a reference in place, given the alternative
> is to use DEFINE_LINKTABLE(struct jump_entry, __jump_table)
> per module -- and later through macro hacks instantiate
> the jump entries per module upon init. This is doable but
> we'd loose out on the sorting of the table using the
> linker, to sort we'd always still need to expand the
> module common linker script. An alternative mechanism
> is possible which would make these custom module sections
> extensions dynamic without requiring manual changes, this
> however is best done later through a separate evolution
> once linker tables are in place.
> 
> A careful reviewer may note that some architectures use
> "\n\t" to separate asm code, while others just use a new line.
> Upon review last time it was deemed reasonable to for all
> architectures to just use "\n", this is defined as ASM_CMD_SEP,
> and if an architecture needs to override they can do so on their
> architecture sections.h prior to including asm-generic/sections.h
> 
> v6: rename table macro as suggested by Andy Shevchenko
> 
> v5:
> 
> o Use ..tbl instead of .tbl as suggested by Nicholas Piggin.
>   This is the typical way to avoid clash with compiler generated
>   section.
> 
> o Replace section macros with section names
> 
> o Use LINKTABLE_START() and LINKTABLE_END()
> 
> o fixed tile jump label port -- tile got jump label support as of
>   commit 65a792e84f25d1 ("tile/jump_label: add jump label support
>   for TILE-Gx"), as such we just needed to adjust the asm to account
>   for the new linker table API use. This commit was merged as of v4.5-rc1.
> 
> v4:
> 
> o Some architectures allow linker scripts to follow including header
>   files, some others do not, so if you need a helper on a linker script
>   you need to explicitly include it. So for instance although
>   scripts/module-common.lds.S includes <asm/tables.h> and this file
>   includes <asm/section-core.h>, you still need to explicitly
>   include it on the linker script. This issue is present on ARM.
> 
> o as per Josh Poimboeuf open code the section table name instead
>   of including the kernel section headers, the simplicity and
>   independence from the kernel is preferred.
> 
> v3:
> 
> o More elaborate tests performed
> o first modular support use case, module tested was
>   CONFIG_TEST_STATIC_KEYS (lib/test_static_keys.ko), this
>   required us to extend module-common.lds.S
> o use generic push_section_tbl_any() for all architectures
> o Makes use of ASM_CMD_SEP to enable architectures to override later
>   if needed
> o guard tables.h inclusion and table definition with __KERNEL__
> 
> v2: introduced in this series
> 
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  arch/arm/include/asm/jump_label.h     |  6 ++++--
>  arch/arm64/include/asm/jump_label.h   |  6 ++++--
>  arch/mips/include/asm/jump_label.h    |  6 ++++--
>  arch/powerpc/include/asm/jump_label.h |  8 +++++---
>  arch/s390/include/asm/jump_label.h    |  6 ++++--
>  arch/sparc/include/asm/jump_label.h   |  6 ++++--
>  arch/tile/include/asm/jump_label.h    |  5 +++--
>  arch/x86/include/asm/jump_label.h     | 10 ++++++----
>  include/asm-generic/vmlinux.lds.h     |  5 -----
>  include/linux/jump_label.h            |  4 ++--
>  kernel/jump_label.c                   | 17 ++++++++++-------
>  scripts/module-common.lds             |  1 +
>  tools/objtool/special.c               |  2 +-
>  13 files changed, 48 insertions(+), 34 deletions(-)

meta-comment.  This new infrastructure doesn't seem to save any code
when you need to have a new "link table".  Yes, the macros seem a bit
nicer, but it feels like unneeded churn.  I haven't seen any patches in
this series that makes me go "oh yeah, now I see why he did this work,
it's so much simpler and easy to understand now!"

What am I missing?  What wonderful new things are going to happen, or
where is the code savings going to come from with this series to justify
all of the work to create and review this?

thanks,

greg k-h

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 09/14] jump_label: port __jump_table to linker tables
@ 2017-01-19 11:24             ` Greg KH
  0 siblings, 0 replies; 480+ messages in thread
From: Greg KH @ 2017-01-19 11:24 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: bp, bp, hpa, acme, tglx, mingo, jpoimboe, npiggin, mhiramat,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, dalias, linux, x86, luto,
	keescook, linux, torvalds, rusty, gnomes, alan, dwmw2, arnd,
	ming.lei, linux-arch, benh, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, adrian.hunter, dsahern, namhyung,
	wangnan0, dmitry.torokhov, joro, paulus, mpe, James.Bottomley

On Sun, Jan 15, 2017 at 01:10:52PM -0800, Luis R. Rodriguez wrote:
> Move the __jump_table from the a custom section solution
> to a generic solution, this avoiding extra vmlinux.lds.h
> customizations.
> 
> This also demos the use of the .data linker table and of
> the shared asm call push_section_tbl().
> 
> Built-in kernel functionality was tested with CONFIG_STATIC_KEYS_SELFTEST.
> Moduler  kernel functionality was tested with CONFIG_TEST_STATIC_KEYS.
> Both work as expected.
> 
> Since __jump_table sections are also supported per
> module this also required expanding module-common.lds.S
> to capture and fold all .data.tlb.__jump_table.* onto
> the the section __jump_table -- in this case for modules
> need to keep a reference in place, given the alternative
> is to use DEFINE_LINKTABLE(struct jump_entry, __jump_table)
> per module -- and later through macro hacks instantiate
> the jump entries per module upon init. This is doable but
> we'd loose out on the sorting of the table using the
> linker, to sort we'd always still need to expand the
> module common linker script. An alternative mechanism
> is possible which would make these custom module sections
> extensions dynamic without requiring manual changes, this
> however is best done later through a separate evolution
> once linker tables are in place.
> 
> A careful reviewer may note that some architectures use
> "\n\t" to separate asm code, while others just use a new line.
> Upon review last time it was deemed reasonable to for all
> architectures to just use "\n", this is defined as ASM_CMD_SEP,
> and if an architecture needs to override they can do so on their
> architecture sections.h prior to including asm-generic/sections.h
> 
> v6: rename table macro as suggested by Andy Shevchenko
> 
> v5:
> 
> o Use ..tbl instead of .tbl as suggested by Nicholas Piggin.
>   This is the typical way to avoid clash with compiler generated
>   section.
> 
> o Replace section macros with section names
> 
> o Use LINKTABLE_START() and LINKTABLE_END()
> 
> o fixed tile jump label port -- tile got jump label support as of
>   commit 65a792e84f25d1 ("tile/jump_label: add jump label support
>   for TILE-Gx"), as such we just needed to adjust the asm to account
>   for the new linker table API use. This commit was merged as of v4.5-rc1.
> 
> v4:
> 
> o Some architectures allow linker scripts to follow including header
>   files, some others do not, so if you need a helper on a linker script
>   you need to explicitly include it. So for instance although
>   scripts/module-common.lds.S includes <asm/tables.h> and this file
>   includes <asm/section-core.h>, you still need to explicitly
>   include it on the linker script. This issue is present on ARM.
> 
> o as per Josh Poimboeuf open code the section table name instead
>   of including the kernel section headers, the simplicity and
>   independence from the kernel is preferred.
> 
> v3:
> 
> o More elaborate tests performed
> o first modular support use case, module tested was
>   CONFIG_TEST_STATIC_KEYS (lib/test_static_keys.ko), this
>   required us to extend module-common.lds.S
> o use generic push_section_tbl_any() for all architectures
> o Makes use of ASM_CMD_SEP to enable architectures to override later
>   if needed
> o guard tables.h inclusion and table definition with __KERNEL__
> 
> v2: introduced in this series
> 
> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> ---
>  arch/arm/include/asm/jump_label.h     |  6 ++++--
>  arch/arm64/include/asm/jump_label.h   |  6 ++++--
>  arch/mips/include/asm/jump_label.h    |  6 ++++--
>  arch/powerpc/include/asm/jump_label.h |  8 +++++---
>  arch/s390/include/asm/jump_label.h    |  6 ++++--
>  arch/sparc/include/asm/jump_label.h   |  6 ++++--
>  arch/tile/include/asm/jump_label.h    |  5 +++--
>  arch/x86/include/asm/jump_label.h     | 10 ++++++----
>  include/asm-generic/vmlinux.lds.h     |  5 -----
>  include/linux/jump_label.h            |  4 ++--
>  kernel/jump_label.c                   | 17 ++++++++++-------
>  scripts/module-common.lds             |  1 +
>  tools/objtool/special.c               |  2 +-
>  13 files changed, 48 insertions(+), 34 deletions(-)

meta-comment.  This new infrastructure doesn't seem to save any code
when you need to have a new "link table".  Yes, the macros seem a bit
nicer, but it feels like unneeded churn.  I haven't seen any patches in
this series that makes me go "oh yeah, now I see why he did this work,
it's so much simpler and easy to understand now!"

What am I missing?  What wonderful new things are going to happen, or
where is the code savings going to come from with this series to justify
all of the work to create and review this?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v7 06/14] firmware/Makefile: force recompilation if makefile changes
  2017-01-19 11:19             ` Greg KH
  (?)
  (?)
@ 2017-01-23 16:12             ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-01-23 16:12 UTC (permalink / raw)
  To: Greg KH
  Cc: gnomes, dalias, linux-ia64, jkosina, benh, ming.lei,
	heiko.carstens, platform-driver-x86, James.Bottomley,
	paul.gortmaker, paulus, mpe, hpa, masami.hiramatsu.pt, wangnan0,
	mchehab, linux-arch, markus.heiser, sparclinux, xen-devel, linux,
	linux-sh, will.deacon, korea.drzix, x86, anil.s.keshavamurthy,
	fontana, mingo, dsahern, linux-arm-kernel, catalin.marinas,
	dvhart, bp, linux, david.vrabel, linux-xtensa

On Thu, Jan 19, 2017 at 12:19:15PM +0100, Greg KH wrote:
> On Sun, Jan 15, 2017 at 01:10:49PM -0800, Luis R. Rodriguez wrote:
> > If you modify the target asm we currently do not force the
> > recompilation of the firmware files. The target asm is in
> > the firmware/Makefile, peg this file as a dependency to
> > require re-compilation of firmware targets when the asm
> > changes.
> > 
> > v3: introduced in this series
> > 
> > Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
> > ---
> >  firmware/Makefile | 3 ++-
> >  1 file changed, 2 insertions(+), 1 deletion(-)
> > 
> > diff --git a/firmware/Makefile b/firmware/Makefile
> > index e297e1b52636..fa3e81c2a97b 100644
> > --- a/firmware/Makefile
> > +++ b/firmware/Makefile
> > @@ -176,7 +176,8 @@ quiet_cmd_fwbin = MK_FW   $@
> >  wordsize_deps := $(wildcard include/config/64bit.h include/config/32bit.h \
> >  		include/config/ppc32.h include/config/ppc64.h \
> >  		include/config/superh32.h include/config/superh64.h \
> > -		include/config/x86_32.h include/config/x86_64.h)
> > +		include/config/x86_32.h include/config/x86_64.h \
> > +		firmware/Makefile)
> >  
> >  $(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)): %: $(wordsize_deps)
> >  	$(call cmd,fwbin,$(patsubst %.gen.S,%,$@))
> 
> I don't understand why this patch is in this series :(

I've taken it out and it has now been routed via kbuild folks as you
requested.

Thanks!

  Luis

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

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 14/16] kprobes: move kprobe declarations to asm-generic/kprobes.h
  2016-08-29 14:04           ` Masami Hiramatsu
  (?)
@ 2017-02-01 20:02             ` Luis R. Rodriguez
  -1 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-02-01 20:02 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: Luis R. Rodriguez, hpa, tglx, mingo, jpoimboe, bp, linux,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross

On Mon, Aug 29, 2016 at 11:04:18PM +0900, Masami Hiramatsu wrote:
> On Tue, 23 Aug 2016 18:31:05 +0200
> "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> 
> > On Tue, Aug 23, 2016 at 12:11:40AM +0900, Masami Hiramatsu wrote:
> > > On Fri, 19 Aug 2016 14:34:12 -0700
> > > mcgrof@kernel.org wrote:
> > > 
> > > > From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> > > > 
> > > > Often all is needed is these small helpers, instead of compiler.h
> > > > or a full kprobes.h. This is important for asm helpers, in fact even
> > > > some asm/kprobes.h make use of these helpers... instead just keep a
> > > > generic asm file with helpers useful for asm code with the least amount
> > > > of clutter as possible.
> > > > 
> > > > Likewise we need now to also address what to do about this file for both
> > > > when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
> > > > for when architectures have CONFIG_HAVE_KPROBES but have disabled
> > > > CONFIG_KPROBES.
> > > > 
> > > > Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
> > > > this means most architecture code cannot include asm/kprobes.h safely.
> > > > Correct this and add guards for architectures missing them. Additionally
> > > > provide architectures that not have kprobes support with the default
> > > > asm-generic solution. This lets us force asm/kprobes.h on the header
> > > > include/linux/kprobes.h always, but most importantly we can now safely
> > > > include just asm/kprobes.h on architecture code without bringing
> > > > the full kitchen sink of header files.
> > > > 
> > > > Two architectures already provided a guard against CONFIG_KPROBES on
> > > > its kprobes.h: sh, arch. The rest of the architectures needed gaurds
> > > > added. We avoid including any not-needed headers on asm/kprobes.h
> > > > unless kprobes have been enabled.
> > > > 
> > > > In a subsequent atomic change we can try now to remove compiler.h from
> > > > include/linux/kprobes.h.
> > > 
> > > Hmm, this looks a bit overkill... I rather like move it into linux/table.h.
> > 
> > That's the thing, we can't reasonably expect every table to add an entry into
> > table.h, this should be up to each user. Moving it to tables.h just prolongs
> > what needs to be done. In this case the change is justifiable given kprobe
> > annotations are required for some architectures early in architecture code, and
> > including compiler.h on early architecture code blows up. There is no easy fix
> > to this, and this this was *actually* the cleanest solution I could devise
> > without much changes.
> 
> Aah, I misread your patch, it is asm-generic/kprobes.h, not asm/kprobes.h.
> I think it is OK now.
> 
> Acked-by: Masami Hiramatsu <mhiramat@kernel.org>

I'm going to send this patch out separately shortly as its independent.

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 14/16] kprobes: move kprobe declarations to asm-generic/kprobes.h
@ 2017-02-01 20:02             ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-02-01 20:02 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: Luis R. Rodriguez, hpa, tglx, mingo, jpoimboe, bp, linux,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross

On Mon, Aug 29, 2016 at 11:04:18PM +0900, Masami Hiramatsu wrote:
> On Tue, 23 Aug 2016 18:31:05 +0200
> "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> 
> > On Tue, Aug 23, 2016 at 12:11:40AM +0900, Masami Hiramatsu wrote:
> > > On Fri, 19 Aug 2016 14:34:12 -0700
> > > mcgrof@kernel.org wrote:
> > > 
> > > > From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> > > > 
> > > > Often all is needed is these small helpers, instead of compiler.h
> > > > or a full kprobes.h. This is important for asm helpers, in fact even
> > > > some asm/kprobes.h make use of these helpers... instead just keep a
> > > > generic asm file with helpers useful for asm code with the least amount
> > > > of clutter as possible.
> > > > 
> > > > Likewise we need now to also address what to do about this file for both
> > > > when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
> > > > for when architectures have CONFIG_HAVE_KPROBES but have disabled
> > > > CONFIG_KPROBES.
> > > > 
> > > > Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
> > > > this means most architecture code cannot include asm/kprobes.h safely.
> > > > Correct this and add guards for architectures missing them. Additionally
> > > > provide architectures that not have kprobes support with the default
> > > > asm-generic solution. This lets us force asm/kprobes.h on the header
> > > > include/linux/kprobes.h always, but most importantly we can now safely
> > > > include just asm/kprobes.h on architecture code without bringing
> > > > the full kitchen sink of header files.
> > > > 
> > > > Two architectures already provided a guard against CONFIG_KPROBES on
> > > > its kprobes.h: sh, arch. The rest of the architectures needed gaurds
> > > > added. We avoid including any not-needed headers on asm/kprobes.h
> > > > unless kprobes have been enabled.
> > > > 
> > > > In a subsequent atomic change we can try now to remove compiler.h from
> > > > include/linux/kprobes.h.
> > > 
> > > Hmm, this looks a bit overkill... I rather like move it into linux/table.h.
> > 
> > That's the thing, we can't reasonably expect every table to add an entry into
> > table.h, this should be up to each user. Moving it to tables.h just prolongs
> > what needs to be done. In this case the change is justifiable given kprobe
> > annotations are required for some architectures early in architecture code, and
> > including compiler.h on early architecture code blows up. There is no easy fix
> > to this, and this this was *actually* the cleanest solution I could devise
> > without much changes.
> 
> Aah, I misread your patch, it is asm-generic/kprobes.h, not asm/kprobes.h.
> I think it is OK now.
> 
> Acked-by: Masami Hiramatsu <mhiramat@kernel.org>

I'm going to send this patch out separately shortly as its independent.

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

* Re: [PATCH v4 14/16] kprobes: move kprobe declarations to asm-generic/kprobes.h
@ 2017-02-01 20:02             ` Luis R. Rodriguez
  0 siblings, 0 replies; 480+ messages in thread
From: Luis R. Rodriguez @ 2017-02-01 20:02 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: Luis R. Rodriguez, hpa, tglx, mingo, jpoimboe, bp, linux,
	masami.hiramatsu.pt, jbaron, heiko.carstens, ananth,
	anil.s.keshavamurthy, davem, realmz6, x86, luto, keescook,
	torvalds, gregkh, rusty, gnomes, alan, dwmw2, arnd, ming.lei,
	linux-arch, benh, ananth, pebolle, fontana, david.vrabel,
	konrad.wilk, mcb30, jgross, andrew.cooper3, andriy.shevchenko,
	paul.gortmaker, xen-devel, ak, pali.rohar, dvhart,
	platform-driver-x86, mmarek, linux, jkosina, korea.drzix,
	linux-kbuild, tony.luck, akpm, linux-ia64, linux-arm-kernel,
	linux-sh, sparclinux, catalin.marinas, will.deacon, rostedt,
	jani.nikula, mchehab, markus.heiser, acme, jolsa, msalter, chris,
	jcmvbkbc, linux-xtensa, paulus, mpe, James.Bottomley

On Mon, Aug 29, 2016 at 11:04:18PM +0900, Masami Hiramatsu wrote:
> On Tue, 23 Aug 2016 18:31:05 +0200
> "Luis R. Rodriguez" <mcgrof@kernel.org> wrote:
> 
> > On Tue, Aug 23, 2016 at 12:11:40AM +0900, Masami Hiramatsu wrote:
> > > On Fri, 19 Aug 2016 14:34:12 -0700
> > > mcgrof@kernel.org wrote:
> > > 
> > > > From: "Luis R. Rodriguez" <mcgrof@kernel.org>
> > > > 
> > > > Often all is needed is these small helpers, instead of compiler.h
> > > > or a full kprobes.h. This is important for asm helpers, in fact even
> > > > some asm/kprobes.h make use of these helpers... instead just keep a
> > > > generic asm file with helpers useful for asm code with the least amount
> > > > of clutter as possible.
> > > > 
> > > > Likewise we need now to also address what to do about this file for both
> > > > when architectures have CONFIG_HAVE_KPROBES, and when they do not. Then
> > > > for when architectures have CONFIG_HAVE_KPROBES but have disabled
> > > > CONFIG_KPROBES.
> > > > 
> > > > Right now most asm/kprobes.h do not have guards against CONFIG_KPROBES,
> > > > this means most architecture code cannot include asm/kprobes.h safely.
> > > > Correct this and add guards for architectures missing them. Additionally
> > > > provide architectures that not have kprobes support with the default
> > > > asm-generic solution. This lets us force asm/kprobes.h on the header
> > > > include/linux/kprobes.h always, but most importantly we can now safely
> > > > include just asm/kprobes.h on architecture code without bringing
> > > > the full kitchen sink of header files.
> > > > 
> > > > Two architectures already provided a guard against CONFIG_KPROBES on
> > > > its kprobes.h: sh, arch. The rest of the architectures needed gaurds
> > > > added. We avoid including any not-needed headers on asm/kprobes.h
> > > > unless kprobes have been enabled.
> > > > 
> > > > In a subsequent atomic change we can try now to remove compiler.h from
> > > > include/linux/kprobes.h.
> > > 
> > > Hmm, this looks a bit overkill... I rather like move it into linux/table.h.
> > 
> > That's the thing, we can't reasonably expect every table to add an entry into
> > table.h, this should be up to each user. Moving it to tables.h just prolongs
> > what needs to be done. In this case the change is justifiable given kprobe
> > annotations are required for some architectures early in architecture code, and
> > including compiler.h on early architecture code blows up. There is no easy fix
> > to this, and this this was *actually* the cleanest solution I could devise
> > without much changes.
> 
> Aah, I misread your patch, it is asm-generic/kprobes.h, not asm/kprobes.h.
> I think it is OK now.
> 
> Acked-by: Masami Hiramatsu <mhiramat@kernel.org>

I'm going to send this patch out separately shortly as its independent.

  Luis

^ permalink raw reply	[flat|nested] 480+ messages in thread

end of thread, other threads:[~2017-02-01 20:02 UTC | newest]

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.