Message ID | 1471642385-5629-7-git-send-email-mcgrof@kernel.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
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
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
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 */