@@ -9,3 +9,4 @@ used throughout the kernel to help declare and define them.
:maxdepth: 4
section-core
+ ranges
new file mode 100644
@@ -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
@@ -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>
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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__.*|"
@@ -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
new file mode 100644
@@ -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_ */
@@ -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)
new file mode 100644
@@ -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 */