2014-07-12 14:44:17

by Mathias Krause

[permalink] [raw]
Subject: [PATCH v2 0/8] Mark literal strings in __init / __exit code

This is v2 of the patch series initially posted here:

https://lkml.org/lkml/2014/6/22/149

I've integrated Joe's idea of also providing printk_init() /
printk_exit() wrappers for code that cannot (or doesn't want to) be
converted to the pi_*() / pe_*() wrappers.

Patches 4 and 5 are cleanup patches I stumbled over while changing the
corresponding code to make use of the new pi_*() helpers.

This version addresses the symbol filtering issue, by filtering the
pseudo symbols in kallsyms (patch 8). This removes them even in the
KALLSYMS_ALL case.

I've changed a few more files, pushing up the memory moved from .rodata
to .init.rodata to ~3 kB. This should free up a page after init for
almost any x86 system.

Comments?


Mathias Krause (8):
init.h: Add __init_str / __exit_str macros
printk: Provide pi_<level> / pe_<level> macros for __init / __exit
code
x86, acpi: Mark __init strings as such
x86, mm: Make x86_init.memory_setup() return a const char *
x86, mm: early_panic() - pass on the message as string
x86, mm: e820 - mark __init strings as such
x86: setup - mark __init strings as such
kallsyms: exclude pseudo symbols for __init / __exit strings

arch/x86/include/asm/e820.h | 4 +-
arch/x86/include/asm/x86_init.h | 2 +-
arch/x86/kernel/acpi/boot.c | 162 ++++++++++++++++++---------------------
arch/x86/kernel/acpi/sleep.c | 17 ++--
arch/x86/kernel/e820.c | 95 +++++++++++------------
arch/x86/kernel/setup.c | 70 ++++++++---------
arch/x86/lguest/boot.c | 2 +-
arch/x86/xen/setup.c | 4 +-
arch/x86/xen/xen-ops.h | 4 +-
include/linux/init.h | 23 ++++++
include/linux/printk.h | 59 ++++++++++++++
scripts/kallsyms.c | 13 ++++
12 files changed, 267 insertions(+), 188 deletions(-)

--
1.7.10.4


2014-07-12 14:44:21

by Mathias Krause

[permalink] [raw]
Subject: [PATCH v2 1/8] init.h: Add __init_str / __exit_str macros

Add macros to be able to mark string literals used in __init / __exit
functions.

Signed-off-by: Mathias Krause <[email protected]>

---
v2: - use a better code example
---
include/linux/init.h | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)

diff --git a/include/linux/init.h b/include/linux/init.h
index 2df8e8dd10..2c1cf10bb7 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -35,6 +35,20 @@
* Don't forget to initialize data not at file scope, i.e. within a function,
* as gcc otherwise puts the data into the bss section and not into the init
* section.
+ *
+ * For strings used in __init / __exit functions the __init_str() /
+ * __exit_str() macros will take care of marking the strings accordingly so
+ * they can be freed, too. Otherwise the strings would resist in memory, even
+ * though they are no longer referenced.
+ *
+ * Use them like this:
+ *
+ * static int __init my_setup(char *arg)
+ * {
+ * if (!strcmp(arg, __init_str("disable")))
+ * enabled = false;
+ * }
+ * __setup("mydev=", my_setup);
*/

/* These are for everybody (although not all archs will actually
@@ -45,6 +59,12 @@
#define __exitdata __section(.exit.data)
#define __exit_call __used __section(.exitcall.exit)

+/* Those can be used to mark strings used in __init / __exit functions. */
+#define __init_str(str) __mark_str(str, __UNIQUE_ID(_init_str_), __initconst)
+#define __exit_str(str) __mark_str(str, __UNIQUE_ID(_exit_str_), __exitdata)
+#define __mark_str(str, var, __section) \
+ ({ static const char var[] __section __aligned(1) = str; var; })
+
/*
* Some architecture have tool chains which do not handle rodata attributes
* correctly. For those disable special sections for const, so that other
--
1.7.10.4

2014-07-12 14:44:35

by Mathias Krause

[permalink] [raw]
Subject: [PATCH v2 7/8] x86: setup - mark __init strings as such

Make use of the pi_<level>() helpers to mark the strings printed during
initialization for automatic release. Do so for the strings used in boot
parameters parsing as well, by using the __init_str() macro.

The debug messages have been converted to printk_init(KERN_DEBUG ...)
instead of pi_debug(...), though. They might have some value beyond
debugging. Moreover, this ensures we won't loose any message by this
conversion.

This moves ~0.5 kB from the .rodata section to .init.rodata, marking it
for release after initialization.

Signed-off-by: Mathias Krause <[email protected]>
---
arch/x86/kernel/setup.c | 70 +++++++++++++++++++++++------------------------
1 file changed, 34 insertions(+), 36 deletions(-)

diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 78a0e62989..d651640040 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -111,6 +111,8 @@
#include <asm/alternative.h>
#include <asm/prom.h>

+#define _(x) __init_str(x)
+
/*
* max_low_pfn_mapped: highest direct mapped pfn under 4GB
* max_pfn_mapped: highest direct mapped pfn over 4GB
@@ -331,7 +333,7 @@ static void __init relocate_initrd(void)
area_size, PAGE_SIZE);

if (!relocated_ramdisk)
- panic("Cannot find place for new RAMDISK of size %lld\n",
+ panic(_("Cannot find place for new RAMDISK of size %lld\n"),
ramdisk_size);

/* Note: this includes all the mem currently occupied by
@@ -339,8 +341,8 @@ static void __init relocate_initrd(void)
memblock_reserve(relocated_ramdisk, area_size);
initrd_start = relocated_ramdisk + PAGE_OFFSET;
initrd_end = initrd_start + ramdisk_size;
- printk(KERN_INFO "Allocated new RAMDISK: [mem %#010llx-%#010llx]\n",
- relocated_ramdisk, relocated_ramdisk + ramdisk_size - 1);
+ pi_info("Allocated new RAMDISK: [mem %#010llx-%#010llx]\n",
+ relocated_ramdisk, relocated_ramdisk + ramdisk_size - 1);

q = (char *)initrd_start;

@@ -361,8 +363,7 @@ static void __init relocate_initrd(void)

ramdisk_image = get_ramdisk_image();
ramdisk_size = get_ramdisk_size();
- printk(KERN_INFO "Move RAMDISK from [mem %#010llx-%#010llx] to"
- " [mem %#010llx-%#010llx]\n",
+ pi_info("Move RAMDISK from [mem %#010llx-%#010llx] to [mem %#010llx-%#010llx]\n",
ramdisk_image, ramdisk_image + ramdisk_size - 1,
relocated_ramdisk, relocated_ramdisk + ramdisk_size - 1);
}
@@ -396,12 +397,12 @@ static void __init reserve_initrd(void)

mapped_size = memblock_mem_size(max_pfn_mapped);
if (ramdisk_size >= (mapped_size>>1))
- panic("initrd too large to handle, "
- "disabling initrd (%lld needed, %lld available)\n",
- ramdisk_size, mapped_size>>1);
+ panic(_("initrd too large to handle, "
+ "disabling initrd (%lld needed, %lld available)\n"),
+ ramdisk_size, mapped_size>>1);

- printk(KERN_INFO "RAMDISK: [mem %#010llx-%#010llx]\n", ramdisk_image,
- ramdisk_end - 1);
+ pi_info("RAMDISK: [mem %#010llx-%#010llx]\n", ramdisk_image,
+ ramdisk_end - 1);

if (pfn_range_is_mapped(PFN_DOWN(ramdisk_image),
PFN_DOWN(ramdisk_end))) {
@@ -478,8 +479,8 @@ static void __init e820_reserve_setup_data(void)

sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
memcpy(&e820_saved, &e820, sizeof(struct e820map));
- printk(KERN_INFO "extended physical RAM map:\n");
- e820_print_map("reserve setup_data");
+ pi_info("extended physical RAM map:\n");
+ e820_print_map(_("reserve setup_data"));
}

static void __init memblock_x86_reserve_range_setup_data(void)
@@ -550,16 +551,16 @@ static void __init reserve_crashkernel_low(void)

if (!low_base) {
if (!auto_set)
- pr_info("crashkernel low reservation failed - No suitable area found.\n");
+ pi_info("crashkernel low reservation failed - No suitable area found.\n");

return;
}

memblock_reserve(low_base, low_size);
- pr_info("Reserving %ldMB of low memory at %ldMB for crashkernel (System low RAM: %ldMB)\n",
- (unsigned long)(low_size >> 20),
- (unsigned long)(low_base >> 20),
- (unsigned long)(total_low_mem >> 20));
+ pi_info("Reserving %ldMB of low memory at %ldMB for crashkernel (System low RAM: %ldMB)\n",
+ (unsigned long)(low_size >> 20),
+ (unsigned long)(low_base >> 20),
+ (unsigned long)(total_low_mem >> 20));
crashk_low_res.start = low_base;
crashk_low_res.end = low_base + low_size - 1;
insert_resource(&iomem_resource, &crashk_low_res);
@@ -599,7 +600,7 @@ static void __init reserve_crashkernel(void)
crash_size, alignment);

if (!crash_base) {
- pr_info("crashkernel reservation failed - No suitable area found.\n");
+ pi_info("crashkernel reservation failed - No suitable area found.\n");
return;
}

@@ -609,17 +610,16 @@ static void __init reserve_crashkernel(void)
start = memblock_find_in_range(crash_base,
crash_base + crash_size, crash_size, 1<<20);
if (start != crash_base) {
- pr_info("crashkernel reservation failed - memory is in use.\n");
+ pi_info("crashkernel reservation failed - memory is in use.\n");
return;
}
}
memblock_reserve(crash_base, crash_size);

- printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
- "for crashkernel (System RAM: %ldMB)\n",
- (unsigned long)(crash_size >> 20),
- (unsigned long)(crash_base >> 20),
- (unsigned long)(total_mem >> 20));
+ pi_info("Reserving %ldMB of memory at %ldMB for crashkernel (System RAM: %ldMB)\n",
+ (unsigned long)(crash_size >> 20),
+ (unsigned long)(crash_base >> 20),
+ (unsigned long)(total_mem >> 20));

crashk_res.start = crash_base;
crashk_res.end = crash_base + crash_size - 1;
@@ -727,7 +727,7 @@ static void __init trim_snb_memory(void)
if (!snb_gfx_workaround_needed())
return;

- printk(KERN_DEBUG "reserving inaccessible SNB gfx pages\n");
+ printk_init(KERN_DEBUG "reserving inaccessible SNB gfx pages\n");

/*
* Reserve all memory below the 1 MB mark that has not
@@ -737,8 +737,7 @@ static void __init trim_snb_memory(void)

for (i = 0; i < ARRAY_SIZE(bad_pages); i++) {
if (memblock_reserve(bad_pages[i], PAGE_SIZE))
- printk(KERN_WARNING "failed to reserve 0x%08lx\n",
- bad_pages[i]);
+ pi_warn("failed to reserve 0x%08lx\n", bad_pages[i]);
}
}

@@ -793,7 +792,7 @@ static void __init e820_add_kernel_range(void)
if (e820_all_mapped(start, start + size, E820_RAM))
return;

- pr_warn(".text .data .bss are not marked as E820_RAM!\n");
+ pi_warn(".text .data .bss are not marked as E820_RAM!\n");
e820_remove_range(start, size, E820_RAM, 0);
e820_add_region(start, size, E820_RAM);
}
@@ -819,7 +818,6 @@ static int __init parse_reservelow(char *p)

return 0;
}
-
early_param("reservelow", parse_reservelow);

static void __init trim_low_memory_range(void)
@@ -881,7 +879,7 @@ void __init setup_arch(char **cmdline_p)
load_cr3(swapper_pg_dir);
__flush_tlb_all();
#else
- printk(KERN_INFO "Command line: %s\n", boot_command_line);
+ pi_info("Command line: %s\n", boot_command_line);
#endif

/*
@@ -924,10 +922,10 @@ void __init setup_arch(char **cmdline_p)
#endif
#ifdef CONFIG_EFI
if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
- "EL32", 4)) {
+ _("EL32"), 4)) {
set_bit(EFI_BOOT, &efi.flags);
} else if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
- "EL64", 4)) {
+ _("EL64"), 4)) {
set_bit(EFI_BOOT, &efi.flags);
set_bit(EFI_64BIT, &efi.flags);
}
@@ -1033,8 +1031,8 @@ void __init setup_arch(char **cmdline_p)
e820_update_range(0x70000000ULL, 0x40000ULL, E820_RAM,
E820_RESERVED);
sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
- printk(KERN_INFO "fixed physical RAM map:\n");
- e820_print_map("bad_ppro");
+ pi_info("fixed physical RAM map:\n");
+ e820_print_map(_("bad_ppro"));
}
#else
early_gart_iommu_check();
@@ -1103,8 +1101,8 @@ void __init setup_arch(char **cmdline_p)
#endif

#ifdef CONFIG_X86_32
- printk(KERN_DEBUG "initial memory mapped: [mem 0x00000000-%#010lx]\n",
- (max_pfn_mapped<<PAGE_SHIFT) - 1);
+ printk_init(KERN_DEBUG "initial memory mapped: [mem 0x00000000-%#010lx]\n",
+ (max_pfn_mapped<<PAGE_SHIFT) - 1);
#endif

reserve_real_mode();
--
1.7.10.4

2014-07-12 14:44:28

by Mathias Krause

[permalink] [raw]
Subject: [PATCH v2 6/8] x86, mm: e820 - mark __init strings as such

Make use of the pi_<level>() helpers to mark the strings printed during
initialization for automatic release. Do so for the strings used in
command line parsing as well, by using the __init_str() macro.

The debug messages have been converted to printk_init(KERN_DEBUG ...)
instead of pi_debug(...), though. They might have some value beyond
debugging. Moreover, this ensures we won't loose any message by this
conversion.

This moves ~0.8 kB from the .rodata section to .init.rodata, marking it
for release after initialization.

Signed-off-by: Mathias Krause <[email protected]>
---
arch/x86/kernel/e820.c | 87 ++++++++++++++++++++++++------------------------
1 file changed, 44 insertions(+), 43 deletions(-)

diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index bfe9238e12..e347a272a9 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -25,6 +25,8 @@
#include <asm/proto.h>
#include <asm/setup.h>

+#define _(x) __init_str(x)
+
/*
* The e820 map is the map that gets modified e.g. with command line parameters
* and that is also registered with modifications in the kernel resource tree
@@ -113,7 +115,7 @@ static void __init __e820_add_region(struct e820map *e820x, u64 start, u64 size,
int x = e820x->nr_map;

if (x >= ARRAY_SIZE(e820x->map)) {
- printk(KERN_ERR "e820: too many entries; ignoring [mem %#010llx-%#010llx]\n",
+ pi_err("e820: too many entries; ignoring [mem %#010llx-%#010llx]\n",
(unsigned long long) start,
(unsigned long long) (start + size - 1));
return;
@@ -135,22 +137,22 @@ static void __init e820_print_type(u32 type)
switch (type) {
case E820_RAM:
case E820_RESERVED_KERN:
- printk(KERN_CONT "usable");
+ pi_cont("usable");
break;
case E820_RESERVED:
- printk(KERN_CONT "reserved");
+ pi_cont("reserved");
break;
case E820_ACPI:
- printk(KERN_CONT "ACPI data");
+ pi_cont("ACPI data");
break;
case E820_NVS:
- printk(KERN_CONT "ACPI NVS");
+ pi_cont("ACPI NVS");
break;
case E820_UNUSABLE:
- printk(KERN_CONT "unusable");
+ pi_cont("unusable");
break;
default:
- printk(KERN_CONT "type %u", type);
+ pi_cont("type %u", type);
break;
}
}
@@ -160,12 +162,12 @@ void __init e820_print_map(const char *who)
int i;

for (i = 0; i < e820.nr_map; i++) {
- printk(KERN_INFO "%s: [mem %#018Lx-%#018Lx] ", who,
- (unsigned long long) e820.map[i].addr,
- (unsigned long long)
- (e820.map[i].addr + e820.map[i].size - 1));
+ pi_info("%s: [mem %#018Lx-%#018Lx] ", who,
+ (unsigned long long) e820.map[i].addr,
+ (unsigned long long)
+ (e820.map[i].addr + e820.map[i].size - 1));
e820_print_type(e820.map[i].type);
- printk(KERN_CONT "\n");
+ pi_cont("\n");
}
}

@@ -430,12 +432,12 @@ static u64 __init __e820_update_range(struct e820map *e820x, u64 start,
size = ULLONG_MAX - start;

end = start + size;
- printk(KERN_DEBUG "e820: update [mem %#010Lx-%#010Lx] ",
- (unsigned long long) start, (unsigned long long) (end - 1));
+ printk_init(KERN_DEBUG "e820: update [mem %#010Lx-%#010Lx] ",
+ (unsigned long long) start, (unsigned long long) (end - 1));
e820_print_type(old_type);
- printk(KERN_CONT " ==> ");
+ pi_cont(" ==> ");
e820_print_type(new_type);
- printk(KERN_CONT "\n");
+ pi_cont("\n");

for (i = 0; i < e820x->nr_map; i++) {
struct e820entry *ei = &e820x->map[i];
@@ -510,11 +512,11 @@ u64 __init e820_remove_range(u64 start, u64 size, unsigned old_type,
size = ULLONG_MAX - start;

end = start + size;
- printk(KERN_DEBUG "e820: remove [mem %#010Lx-%#010Lx] ",
- (unsigned long long) start, (unsigned long long) (end - 1));
+ printk_init(KERN_DEBUG "e820: remove [mem %#010Lx-%#010Lx] ",
+ (unsigned long long) start, (unsigned long long) (end - 1));
if (checktype)
e820_print_type(old_type);
- printk(KERN_CONT "\n");
+ pi_cont("\n");

for (i = 0; i < e820.nr_map; i++) {
struct e820entry *ei = &e820.map[i];
@@ -567,8 +569,8 @@ void __init update_e820(void)
if (sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &nr_map))
return;
e820.nr_map = nr_map;
- printk(KERN_INFO "e820: modified physical RAM map:\n");
- e820_print_map("modified");
+ pi_info("e820: modified physical RAM map:\n");
+ e820_print_map(_("modified"));
}
static void __init update_e820_saved(void)
{
@@ -636,7 +638,7 @@ __init void e820_setup_gap(void)
#ifdef CONFIG_X86_64
if (!found) {
gapstart = (max_pfn << PAGE_SHIFT) + 1024*1024;
- printk(KERN_ERR
+ pi_err(
"e820: cannot find a gap in the 32bit address range\n"
"e820: PCI devices with unassigned 32bit BARs may break!\n");
}
@@ -647,9 +649,8 @@ __init void e820_setup_gap(void)
*/
pci_mem_start = gapstart;

- printk(KERN_INFO
- "e820: [mem %#010lx-%#010lx] available for PCI devices\n",
- gapstart, gapstart + gapsize - 1);
+ pi_info("e820: [mem %#010lx-%#010lx] available for PCI devices\n",
+ gapstart, gapstart + gapsize - 1);
}

/**
@@ -670,8 +671,8 @@ void __init parse_e820_ext(u64 phys_addr, u32 data_len)
__append_e820_map(extmap, entries);
sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
early_iounmap(sdata, data_len);
- printk(KERN_INFO "e820: extended physical RAM map:\n");
- e820_print_map("extended");
+ pi_info("e820: extended physical RAM map:\n");
+ e820_print_map(_("extended"));
}

#if defined(CONFIG_X86_64) || \
@@ -737,7 +738,7 @@ u64 __init early_reserve_e820(u64 size, u64 align)
addr = __memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
if (addr) {
e820_update_range_saved(addr, size, E820_RAM, E820_RESERVED);
- printk(KERN_INFO "e820: update e820_saved for early_reserve_e820\n");
+ pi_info("e820: update e820_saved for early_reserve_e820\n");
update_e820_saved();
}

@@ -787,8 +788,8 @@ static unsigned long __init e820_end_pfn(unsigned long limit_pfn, unsigned type)
if (last_pfn > max_arch_pfn)
last_pfn = max_arch_pfn;

- printk(KERN_INFO "e820: last_pfn = %#lx max_arch_pfn = %#lx\n",
- last_pfn, max_arch_pfn);
+ pi_info("e820: last_pfn = %#lx max_arch_pfn = %#lx\n", last_pfn,
+ max_arch_pfn);
return last_pfn;
}
unsigned long __init e820_end_of_ram_pfn(void)
@@ -803,8 +804,8 @@ unsigned long __init e820_end_of_low_ram_pfn(void)

static void early_panic(const char *msg)
{
- early_printk("%s", msg);
- panic("%s", msg);
+ early_printk(_("%s"), msg);
+ panic(_("%s"), msg);
}

static int userdef __initdata;
@@ -817,12 +818,12 @@ static int __init parse_memopt(char *p)
if (!p)
return -EINVAL;

- if (!strcmp(p, "nopentium")) {
+ if (!strcmp(p, _("nopentium"))) {
#ifdef CONFIG_X86_32
setup_clear_cpu_cap(X86_FEATURE_PSE);
return 0;
#else
- printk(KERN_WARNING "mem=nopentium ignored! (only supported on x86_32)\n");
+ pi_warn("mem=nopentium ignored! (only supported on x86_32)\n");
return -EINVAL;
#endif
}
@@ -846,7 +847,7 @@ static int __init parse_memmap_one(char *p)
if (!p)
return -EINVAL;

- if (!strncmp(p, "exactmap", 8)) {
+ if (!strncmp(p, _("exactmap"), 8)) {
#ifdef CONFIG_CRASH_DUMP
/*
* If we are doing a crash dump, we still need to know
@@ -902,11 +903,11 @@ void __init finish_e820_parsing(void)
u32 nr = e820.nr_map;

if (sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &nr) < 0)
- early_panic("Invalid user supplied memory map");
+ early_panic(_("Invalid user supplied memory map"));
e820.nr_map = nr;

- printk(KERN_INFO "e820: user-defined physical RAM map:\n");
- e820_print_map("user");
+ pi_info("e820: user-defined physical RAM map:\n");
+ e820_print_map(_("user"));
}
}

@@ -1013,7 +1014,7 @@ void __init e820_reserve_resources_late(void)
end = MAX_RESOURCE_SIZE;
if (start >= end)
continue;
- printk(KERN_DEBUG
+ printk_init(KERN_DEBUG
"e820: reserve RAM buffer [mem %#010llx-%#010llx]\n",
start, end);
reserve_region_with_split(&iomem_resource, start, end,
@@ -1023,7 +1024,7 @@ void __init e820_reserve_resources_late(void)

const char *__init default_machine_specific_memory_setup(void)
{
- const char *who = "BIOS-e820";
+ const char *who = _("BIOS-e820");
u32 new_nr;
/*
* Try to copy the BIOS-supplied E820-map.
@@ -1044,10 +1045,10 @@ const char *__init default_machine_specific_memory_setup(void)
if (boot_params.alt_mem_k
< boot_params.screen_info.ext_mem_k) {
mem_size = boot_params.screen_info.ext_mem_k;
- who = "BIOS-88";
+ who = _("BIOS-88");
} else {
mem_size = boot_params.alt_mem_k;
- who = "BIOS-e801";
+ who = _("BIOS-e801");
}

e820.nr_map = 0;
@@ -1065,7 +1066,7 @@ void __init setup_memory_map(void)

who = x86_init.resources.memory_setup();
memcpy(&e820_saved, &e820, sizeof(struct e820map));
- printk(KERN_INFO "e820: BIOS-provided physical RAM map:\n");
+ pi_info("e820: BIOS-provided physical RAM map:\n");
e820_print_map(who);
}

--
1.7.10.4

2014-07-12 14:44:39

by Mathias Krause

[permalink] [raw]
Subject: [PATCH v2 8/8] kallsyms: exclude pseudo symbols for __init / __exit strings

The __init_str() / __exit_str() annotations create pseudo symbols.
Ignore them, they have no value for us.

Signed-off-by: Mathias Krause <[email protected]>
---
scripts/kallsyms.c | 13 +++++++++++++
1 file changed, 13 insertions(+)

diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index dc7aa45e80..8fd0f2965d 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -88,6 +88,16 @@ static inline int is_arm_mapping_symbol(const char *str)
&& (str[2] == '\0' || str[2] == '.');
}

+/*
+ * This ignores the pseudo symbols for __init_str() / __exit_str() annotated
+ * strings.
+ */
+static inline int is_init_exit_str_symbol(const char *str)
+{
+ return strncmp(str, "__UNIQUE_ID__init_str_", 22) == 0 ||
+ strncmp(str, "__UNIQUE_ID__exit_str_", 22) == 0;
+}
+
static int check_symbol_range(const char *sym, unsigned long long addr,
struct addr_range *ranges, int entries)
{
@@ -158,6 +168,9 @@ static int read_symbol(FILE *in, struct sym_entry *s)
/* exclude debugging symbols */
else if (stype == 'N')
return -1;
+ /* exclude pseudo symbols for __init / __exit strings */
+ else if (stype == 't' && is_init_exit_str_symbol(sym))
+ return -1;

/* include the type field in the symbol name, so that it gets
* compressed together */
--
1.7.10.4

2014-07-12 14:45:24

by Mathias Krause

[permalink] [raw]
Subject: [PATCH v2 3/8] x86, acpi: Mark __init strings as such

Make use of the pi_<level>() helpers to mark the strings printed during
initialization for automatic release. Do so for the strings used in
command line parsing as well, by using the __init_str() macro.

Also convert the remaining printk() calls to their pr_<level> /
pi_<level> counterparts.

This moves ~1.7 kB from the .rodata section to .init.rodata, marking it
for release after initialization.

Signed-off-by: Mathias Krause <[email protected]>

---
v2: handle all of arch/x86/kernel/acpi/
---
arch/x86/kernel/acpi/boot.c | 162 +++++++++++++++++++-----------------------
arch/x86/kernel/acpi/sleep.c | 17 +++--
2 files changed, 82 insertions(+), 97 deletions(-)

diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 86281ffb96..dc7d8b1f54 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -23,6 +23,8 @@
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/

+#define pr_fmt(fmt) "ACPI: " fmt
+
#include <linux/init.h>
#include <linux/acpi.h>
#include <linux/acpi_pmtmr.h>
@@ -53,7 +55,7 @@ EXPORT_SYMBOL(acpi_disabled);
# include <asm/proto.h>
#endif /* X86 */

-#define PREFIX "ACPI: "
+#define _(x) __init_str(x)

int acpi_noirq; /* skip ACPI IRQ initialization */
int acpi_pci_disabled; /* skip ACPI PCI scan and IRQ initialization */
@@ -167,15 +169,14 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)

madt = (struct acpi_table_madt *)table;
if (!madt) {
- printk(KERN_WARNING PREFIX "Unable to map MADT\n");
+ pi_warn("Unable to map MADT\n");
return -ENODEV;
}

if (madt->address) {
acpi_lapic_addr = (u64) madt->address;

- printk(KERN_DEBUG PREFIX "Local APIC address 0x%08x\n",
- madt->address);
+ pi_debug("Local APIC address 0x%08x\n", madt->address);
}

default_acpi_madt_oem_check(madt->header.oem_id,
@@ -196,7 +197,7 @@ static int acpi_register_lapic(int id, u8 enabled)
unsigned int ver = 0;

if (id >= MAX_LOCAL_APIC) {
- printk(KERN_INFO PREFIX "skipped apicid that is too big\n");
+ pr_info("skipped apicid that is too big\n");
return -EINVAL;
}

@@ -236,11 +237,11 @@ acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end)
* when we use CPU hotplug.
*/
if (!apic->apic_id_valid(apic_id) && enabled)
- printk(KERN_WARNING PREFIX "x2apic entry ignored\n");
+ pi_warn("x2apic entry ignored\n");
else
acpi_register_lapic(apic_id, enabled);
#else
- printk(KERN_WARNING PREFIX "x2apic entry ignored\n");
+ pi_warn("x2apic entry ignored\n");
#endif

return 0;
@@ -319,7 +320,7 @@ acpi_parse_x2apic_nmi(struct acpi_subtable_header *header,
acpi_table_print_madt_entry(header);

if (x2apic_nmi->lint != 1)
- printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n");
+ pi_warn("NMI not connected to LINT 1!\n");

return 0;
}
@@ -337,7 +338,7 @@ acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long e
acpi_table_print_madt_entry(header);

if (lapic_nmi->lint != 1)
- printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n");
+ pi_warn("NMI not connected to LINT 1!\n");

return 0;
}
@@ -420,14 +421,14 @@ acpi_parse_int_src_ovr(struct acpi_subtable_header * header,

if (intsrc->source_irq == 0) {
if (acpi_skip_timer_override) {
- printk(PREFIX "BIOS IRQ0 override ignored.\n");
+ pi_info("BIOS IRQ0 override ignored.\n");
return 0;
}

if ((intsrc->global_irq == 2) && acpi_fix_pin2_polarity
&& (intsrc->inti_flags & ACPI_MADT_POLARITY_MASK)) {
intsrc->inti_flags &= ~ACPI_MADT_POLARITY_MASK;
- printk(PREFIX "BIOS IRQ0 pin2 override: forcing polarity to high active.\n");
+ pi_info("BIOS IRQ0 pin2 override: forcing polarity to high active.\n");
}
}

@@ -503,7 +504,7 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
if (old == new)
return;

- printk(PREFIX "setting ELCR to %04x (from %04x)\n", new, old);
+ pi_info("setting ELCR to %04x (from %04x)\n", new, old);
outb(new, 0x4d0);
outb(new >> 8, 0x4d1);
}
@@ -622,7 +623,7 @@ static int _acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu)

cpu = acpi_register_lapic(physid, ACPI_MADT_ENABLED);
if (cpu < 0) {
- pr_info(PREFIX "Unable to map lapic to logical cpu number\n");
+ pr_info("Unable to map lapic to logical cpu number\n");
return cpu;
}

@@ -678,7 +679,7 @@ static int __init acpi_parse_sbf(struct acpi_table_header *table)

sb = (struct acpi_table_boot *)table;
if (!sb) {
- printk(KERN_WARNING PREFIX "Unable to map SBF\n");
+ pi_warn("Unable to map SBF\n");
return -ENODEV;
}

@@ -698,13 +699,12 @@ static int __init acpi_parse_hpet(struct acpi_table_header *table)

hpet_tbl = (struct acpi_table_hpet *)table;
if (!hpet_tbl) {
- printk(KERN_WARNING PREFIX "Unable to map HPET\n");
+ pi_warn("Unable to map HPET\n");
return -ENODEV;
}

if (hpet_tbl->address.space_id != ACPI_SPACE_MEM) {
- printk(KERN_WARNING PREFIX "HPET timers must be located in "
- "memory.\n");
+ pi_warn("HPET timers must be located in memory.\n");
return -1;
}

@@ -716,9 +716,8 @@ static int __init acpi_parse_hpet(struct acpi_table_header *table)
* want to allocate a resource there.
*/
if (!hpet_address) {
- printk(KERN_WARNING PREFIX
- "HPET id: %#x base: %#lx is invalid\n",
- hpet_tbl->id, hpet_address);
+ pi_warn("HPET id: %#x base: %#lx is invalid\n", hpet_tbl->id,
+ hpet_address);
return 0;
}
#ifdef CONFIG_X86_64
@@ -729,21 +728,19 @@ static int __init acpi_parse_hpet(struct acpi_table_header *table)
*/
if (hpet_address == 0xfed0000000000000UL) {
if (!hpet_force_user) {
- printk(KERN_WARNING PREFIX "HPET id: %#x "
- "base: 0xfed0000000000000 is bogus\n "
- "try hpet=force on the kernel command line to "
- "fix it up to 0xfed00000.\n", hpet_tbl->id);
+ pi_warn("HPET id: %#x base: %#lx is bogus\n",
+ hpet_tbl->id, 0xfed0000000000000UL);
+ pi_cont("try hpet=force on the kernel command line "
+ "to fix it up to 0xfed00000.\n"),
hpet_address = 0;
return 0;
}
- printk(KERN_WARNING PREFIX
- "HPET id: %#x base: 0xfed0000000000000 fixed up "
- "to 0xfed00000.\n", hpet_tbl->id);
+ pi_warn("HPET id: %#x base: %#lx fixed up to 0xfed00000.\n",
+ hpet_tbl->id, 0xfed0000000000000UL);
hpet_address >>= 32;
}
#endif
- printk(KERN_INFO PREFIX "HPET id: %#x base: %#lx\n",
- hpet_tbl->id, hpet_address);
+ pi_info("HPET id: %#x base: %#lx\n", hpet_tbl->id, hpet_address);

/*
* Allocate and initialize the HPET firmware resource for adding into
@@ -754,7 +751,7 @@ static int __init acpi_parse_hpet(struct acpi_table_header *table)

hpet_res->name = (void *)&hpet_res[1];
hpet_res->flags = IORESOURCE_MEM;
- snprintf((char *)hpet_res->name, HPET_RESOURCE_NAME_SIZE, "HPET %u",
+ snprintf((char *)hpet_res->name, HPET_RESOURCE_NAME_SIZE, _("HPET %u"),
hpet_tbl->sequence);

hpet_res->start = hpet_address;
@@ -805,8 +802,7 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table)
pmtmr_ioport = acpi_gbl_FADT.pm_timer_block;
}
if (pmtmr_ioport)
- printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x\n",
- pmtmr_ioport);
+ pi_info("PM-Timer IO Port: %#x\n", pmtmr_ioport);
#endif
return 0;
}
@@ -833,8 +829,7 @@ static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
acpi_parse_lapic_addr_ovr, 0);
if (count < 0) {
- printk(KERN_ERR PREFIX
- "Error parsing LAPIC address override entry\n");
+ pi_err("Error parsing LAPIC address override entry\n");
return count;
}

@@ -860,8 +855,7 @@ static int __init acpi_parse_madt_lapic_entries(void)
acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
acpi_parse_lapic_addr_ovr, 0);
if (count < 0) {
- printk(KERN_ERR PREFIX
- "Error parsing LAPIC address override entry\n");
+ pi_err("Error parsing LAPIC address override entry\n");
return count;
}

@@ -877,11 +871,11 @@ static int __init acpi_parse_madt_lapic_entries(void)
acpi_parse_lapic, MAX_LOCAL_APIC);
}
if (!count && !x2count) {
- printk(KERN_ERR PREFIX "No LAPIC entries present\n");
+ pi_err("No LAPIC entries present\n");
/* TBD: Cleanup to allow fallback to MPS */
return -ENODEV;
} else if (count < 0 || x2count < 0) {
- printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n");
+ pi_err("Error parsing LAPIC entry\n");
/* TBD: Cleanup to allow fallback to MPS */
return count;
}
@@ -892,7 +886,7 @@ static int __init acpi_parse_madt_lapic_entries(void)
count =
acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI, acpi_parse_lapic_nmi, 0);
if (count < 0 || x2count < 0) {
- printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
+ pi_err("Error parsing LAPIC NMI entry\n");
/* TBD: Cleanup to allow fallback to MPS */
return count;
}
@@ -950,7 +944,7 @@ void __init mp_config_acpi_legacy_irqs(void)
mp_bus_id_to_type[MP_ISA_BUS] = MP_BUS_ISA;
#endif
set_bit(MP_ISA_BUS, mp_bus_not_pci);
- pr_debug("Bus #%d is ISA\n", MP_ISA_BUS);
+ pi_debug("Bus #%d is ISA\n", MP_ISA_BUS);

/*
* Use the default configuration for the IRQs 0-15. Unless
@@ -988,7 +982,7 @@ void __init mp_config_acpi_legacy_irqs(void)
}

if (idx != mp_irq_entries) {
- printk(KERN_DEBUG "ACPI: IRQ%d used by override.\n", i);
+ pi_debug("IRQ%d used by override.\n", i);
continue; /* IRQ already used */
}

@@ -1056,16 +1050,15 @@ int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)

ioapic = mp_find_ioapic(gsi);
if (ioapic < 0) {
- printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
+ pr_warn("No IOAPIC for GSI %u\n", gsi);
return gsi;
}

ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);

if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
- printk(KERN_ERR "Invalid reference to IOAPIC pin "
- "%d-%d\n", mpc_ioapic_id(ioapic),
- ioapic_pin);
+ pr_err("Invalid reference to IOAPIC pin %d-%d\n",
+ mpc_ioapic_id(ioapic), ioapic_pin);
return gsi;
}

@@ -1106,8 +1099,7 @@ static int __init acpi_parse_madt_ioapic_entries(void)
* if "noapic" boot option, don't look for IO-APICs
*/
if (skip_ioapic_setup) {
- printk(KERN_INFO PREFIX "Skipping IOAPIC probe "
- "due to 'noapic' option.\n");
+ pi_info("Skipping IOAPIC probe due to 'noapic' option.\n");
return -ENODEV;
}

@@ -1115,10 +1107,10 @@ static int __init acpi_parse_madt_ioapic_entries(void)
acpi_table_parse_madt(ACPI_MADT_TYPE_IO_APIC, acpi_parse_ioapic,
MAX_IO_APICS);
if (!count) {
- printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
+ pi_err("No IOAPIC entries present\n");
return -ENODEV;
} else if (count < 0) {
- printk(KERN_ERR PREFIX "Error parsing IOAPIC entry\n");
+ pi_err("Error parsing IOAPIC entry\n");
return count;
}

@@ -1126,8 +1118,7 @@ static int __init acpi_parse_madt_ioapic_entries(void)
acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, acpi_parse_int_src_ovr,
nr_irqs);
if (count < 0) {
- printk(KERN_ERR PREFIX
- "Error parsing interrupt source overrides entry\n");
+ pi_err("Error parsing interrupt source overrides entry\n");
/* TBD: Cleanup to allow fallback to MPS */
return count;
}
@@ -1147,7 +1138,7 @@ static int __init acpi_parse_madt_ioapic_entries(void)
acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE, acpi_parse_nmi_src,
nr_irqs);
if (count < 0) {
- printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
+ pi_err("Error parsing NMI SRC entry\n");
/* TBD: Cleanup to allow fallback to MPS */
return count;
}
@@ -1180,8 +1171,7 @@ static void __init early_acpi_process_madt(void)
/*
* Dell Precision Workstation 410, 610 come here.
*/
- printk(KERN_ERR PREFIX
- "Invalid BIOS MADT, disabling ACPI\n");
+ pi_err("Invalid BIOS MADT, disabling ACPI\n");
disable_acpi();
}
}
@@ -1216,8 +1206,7 @@ static void __init acpi_process_madt(void)
/*
* Dell Precision Workstation 410, 610 come here.
*/
- printk(KERN_ERR PREFIX
- "Invalid BIOS MADT, disabling ACPI\n");
+ pi_err("Invalid BIOS MADT, disabling ACPI\n");
disable_acpi();
}
} else {
@@ -1227,8 +1216,7 @@ static void __init acpi_process_madt(void)
* Boot with "acpi=off" to use MPS on such a system.
*/
if (smp_found_config) {
- printk(KERN_WARNING PREFIX
- "No APIC-table, disabling MPS\n");
+ pi_warn("No APIC-table, disabling MPS\n");
smp_found_config = 0;
}
}
@@ -1238,11 +1226,11 @@ static void __init acpi_process_madt(void)
* processors, where MPS only supports physical.
*/
if (acpi_lapic && acpi_ioapic)
- printk(KERN_INFO "Using ACPI (MADT) for SMP configuration "
- "information\n");
+ pi_info("Using ACPI (MADT) for SMP configuration "
+ "information\n");
else if (acpi_lapic)
- printk(KERN_INFO "Using ACPI for processor (LAPIC) "
- "configuration information\n");
+ pi_info("Using ACPI for processor (LAPIC) configuration "
+ "information\n");
#endif
return;
}
@@ -1250,8 +1238,7 @@ static void __init acpi_process_madt(void)
static int __init disable_acpi_irq(const struct dmi_system_id *d)
{
if (!acpi_force) {
- printk(KERN_NOTICE "%s detected: force use of acpi=noirq\n",
- d->ident);
+ pi_info("%s detected: force use of acpi=noirq\n", d->ident);
acpi_noirq_set();
}
return 0;
@@ -1260,8 +1247,7 @@ static int __init disable_acpi_irq(const struct dmi_system_id *d)
static int __init disable_acpi_pci(const struct dmi_system_id *d)
{
if (!acpi_force) {
- printk(KERN_NOTICE "%s detected: force use of pci=noacpi\n",
- d->ident);
+ pi_notice("%s detected: force use of pci=noacpi\n", d->ident);
acpi_disable_pci();
}
return 0;
@@ -1270,11 +1256,11 @@ static int __init disable_acpi_pci(const struct dmi_system_id *d)
static int __init dmi_disable_acpi(const struct dmi_system_id *d)
{
if (!acpi_force) {
- printk(KERN_NOTICE "%s detected: acpi off\n", d->ident);
+ pi_notice("%s detected: acpi off\n", d->ident);
disable_acpi();
} else {
- printk(KERN_NOTICE
- "Warning: DMI blacklist says broken, but acpi forced\n");
+ pi_notice("Warning: DMI blacklist says broken, but acpi "
+ "forced\n");
}
return 0;
}
@@ -1285,8 +1271,8 @@ static int __init dmi_disable_acpi(const struct dmi_system_id *d)
static int __init dmi_ignore_irq0_timer_override(const struct dmi_system_id *d)
{
if (!acpi_skip_timer_override) {
- pr_notice("%s detected: Ignoring BIOS IRQ0 override\n",
- d->ident);
+ pi_notice("%s detected: Ignoring BIOS IRQ0 override\n",
+ d->ident);
acpi_skip_timer_override = 1;
}
return 0;
@@ -1469,9 +1455,9 @@ void __init acpi_boot_table_init(void)
*/
if (acpi_blacklisted()) {
if (acpi_force) {
- printk(KERN_WARNING PREFIX "acpi=force override\n");
+ pi_warn("acpi=force override\n");
} else {
- printk(KERN_WARNING PREFIX "Disabling ACPI support\n");
+ pi_warn("Disabling ACPI support\n");
disable_acpi();
return;
}
@@ -1531,32 +1517,32 @@ static int __init parse_acpi(char *arg)
return -EINVAL;

/* "acpi=off" disables both ACPI table parsing and interpreter */
- if (strcmp(arg, "off") == 0) {
+ if (strcmp(arg, _("off")) == 0) {
disable_acpi();
}
/* acpi=force to over-ride black-list */
- else if (strcmp(arg, "force") == 0) {
+ else if (strcmp(arg, _("force")) == 0) {
acpi_force = 1;
acpi_disabled = 0;
}
/* acpi=strict disables out-of-spec workarounds */
- else if (strcmp(arg, "strict") == 0) {
+ else if (strcmp(arg, _("strict")) == 0) {
acpi_strict = 1;
}
/* acpi=rsdt use RSDT instead of XSDT */
- else if (strcmp(arg, "rsdt") == 0) {
+ else if (strcmp(arg, _("rsdt")) == 0) {
acpi_gbl_do_not_use_xsdt = TRUE;
}
/* "acpi=noirq" disables ACPI interrupt routing */
- else if (strcmp(arg, "noirq") == 0) {
+ else if (strcmp(arg, _("noirq")) == 0) {
acpi_noirq_set();
}
/* "acpi=copy_dsdt" copys DSDT */
- else if (strcmp(arg, "copy_dsdt") == 0) {
+ else if (strcmp(arg, _("copy_dsdt")) == 0) {
acpi_gbl_copy_dsdt_locally = 1;
}
/* "acpi=nocmcff" disables FF mode for corrected errors */
- else if (strcmp(arg, "nocmcff") == 0) {
+ else if (strcmp(arg, _("nocmcff")) == 0) {
acpi_disable_cmcff = 1;
} else {
/* Core will printk when we return error. */
@@ -1569,7 +1555,7 @@ early_param("acpi", parse_acpi);
/* FIXME: Using pci= for an ACPI parameter is a travesty. */
static int __init parse_pci(char *arg)
{
- if (arg && strcmp(arg, "noacpi") == 0)
+ if (arg && strcmp(arg, _("noacpi")) == 0)
acpi_disable_pci();
return 0;
}
@@ -1580,9 +1566,9 @@ int __init acpi_mps_check(void)
#if defined(CONFIG_X86_LOCAL_APIC) && !defined(CONFIG_X86_MPPARSE)
/* mptable code is not built-in*/
if (acpi_disabled || acpi_noirq) {
- printk(KERN_WARNING "MPS support code is not built-in.\n"
- "Using acpi=off or acpi=noirq or pci=noacpi "
- "may have problem\n");
+ pi_warn("MPS support code is not built-in.\n");
+ pi_cont("Using acpi=off or acpi=noirq or pci=noacpi "
+ "may have problems.\n");
return 1;
}
#endif
@@ -1609,16 +1595,16 @@ static int __init setup_acpi_sci(char *s)
{
if (!s)
return -EINVAL;
- if (!strcmp(s, "edge"))
+ if (!strcmp(s, _("edge")))
acpi_sci_flags = ACPI_MADT_TRIGGER_EDGE |
(acpi_sci_flags & ~ACPI_MADT_TRIGGER_MASK);
- else if (!strcmp(s, "level"))
+ else if (!strcmp(s, _("level")))
acpi_sci_flags = ACPI_MADT_TRIGGER_LEVEL |
(acpi_sci_flags & ~ACPI_MADT_TRIGGER_MASK);
- else if (!strcmp(s, "high"))
+ else if (!strcmp(s, _("high")))
acpi_sci_flags = ACPI_MADT_POLARITY_ACTIVE_HIGH |
(acpi_sci_flags & ~ACPI_MADT_POLARITY_MASK);
- else if (!strcmp(s, "low"))
+ else if (!strcmp(s, _("low")))
acpi_sci_flags = ACPI_MADT_POLARITY_ACTIVE_LOW |
(acpi_sci_flags & ~ACPI_MADT_POLARITY_MASK);
else
diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
index 3136820783..dd75669104 100644
--- a/arch/x86/kernel/acpi/sleep.c
+++ b/arch/x86/kernel/acpi/sleep.c
@@ -114,27 +114,26 @@ int x86_acpi_suspend_lowlevel(void)
static int __init acpi_sleep_setup(char *str)
{
while ((str != NULL) && (*str != '\0')) {
- if (strncmp(str, "s3_bios", 7) == 0)
+ if (strncmp(str, __init_str("s3_bios"), 7) == 0)
acpi_realmode_flags |= 1;
- if (strncmp(str, "s3_mode", 7) == 0)
+ if (strncmp(str, __init_str("s3_mode"), 7) == 0)
acpi_realmode_flags |= 2;
- if (strncmp(str, "s3_beep", 7) == 0)
+ if (strncmp(str, __init_str("s3_beep"), 7) == 0)
acpi_realmode_flags |= 4;
#ifdef CONFIG_HIBERNATION
- if (strncmp(str, "s4_nohwsig", 10) == 0)
+ if (strncmp(str, __init_str("s4_nohwsig"), 10) == 0)
acpi_no_s4_hw_signature();
#endif
- if (strncmp(str, "nonvs", 5) == 0)
+ if (strncmp(str, __init_str("nonvs"), 5) == 0)
acpi_nvs_nosave();
- if (strncmp(str, "nonvs_s3", 8) == 0)
+ if (strncmp(str, __init_str("nonvs_s3"), 8) == 0)
acpi_nvs_nosave_s3();
- if (strncmp(str, "old_ordering", 12) == 0)
+ if (strncmp(str, __init_str("old_ordering"), 12) == 0)
acpi_old_suspend_ordering();
str = strchr(str, ',');
if (str != NULL)
- str += strspn(str, ", \t");
+ str += strspn(str, __init_str(", \t"));
}
return 1;
}
-
__setup("acpi_sleep=", acpi_sleep_setup);
--
1.7.10.4

2014-07-12 14:45:20

by Mathias Krause

[permalink] [raw]
Subject: [PATCH v2 5/8] x86, mm: early_panic() - pass on the message as string

early_printk() and panic() expect a format string as first argument.
Change early_panic() to pass on the message as string instead of a
format string.

Signed-off-by: Mathias Krause <[email protected]>
---
arch/x86/kernel/e820.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 14323a7c66..bfe9238e12 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -801,10 +801,10 @@ unsigned long __init e820_end_of_low_ram_pfn(void)
return e820_end_pfn(1UL<<(32 - PAGE_SHIFT), E820_RAM);
}

-static void early_panic(char *msg)
+static void early_panic(const char *msg)
{
- early_printk(msg);
- panic(msg);
+ early_printk("%s", msg);
+ panic("%s", msg);
}

static int userdef __initdata;
--
1.7.10.4

2014-07-12 14:45:15

by Mathias Krause

[permalink] [raw]
Subject: [PATCH v2 4/8] x86, mm: Make x86_init.memory_setup() return a const char *

All implementations of x86_init.memory_setup() actually return a const
char *. Adjust the prototypes to reflect reality.

Also add the missing __init annotation to xen_auto_xlated_memory_setup().

Signed-off-by: Mathias Krause <[email protected]>
---
arch/x86/include/asm/e820.h | 4 ++--
arch/x86/include/asm/x86_init.h | 2 +-
arch/x86/kernel/e820.c | 8 ++++----
arch/x86/lguest/boot.c | 2 +-
arch/x86/xen/setup.c | 4 ++--
arch/x86/xen/xen-ops.h | 4 ++--
6 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h
index 779c2efe2e..7d17fb2b16 100644
--- a/arch/x86/include/asm/e820.h
+++ b/arch/x86/include/asm/e820.h
@@ -17,7 +17,7 @@ extern unsigned long pci_mem_start;
extern int e820_any_mapped(u64 start, u64 end, unsigned type);
extern int e820_all_mapped(u64 start, u64 end, unsigned type);
extern void e820_add_region(u64 start, u64 size, int type);
-extern void e820_print_map(char *who);
+extern void e820_print_map(const char *who);
extern int
sanitize_e820_map(struct e820entry *biosmap, int max_nr_map, u32 *pnr_map);
extern u64 e820_update_range(u64 start, u64 size, unsigned old_type,
@@ -59,7 +59,7 @@ extern void finish_e820_parsing(void);
extern void e820_reserve_resources(void);
extern void e820_reserve_resources_late(void);
extern void setup_memory_map(void);
-extern char *default_machine_specific_memory_setup(void);
+extern const char *default_machine_specific_memory_setup(void);

/*
* Returns true iff the specified range [s,e) is completely contained inside
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index e45e4da96b..64e80c9815 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -42,7 +42,7 @@ struct x86_init_mpparse {
struct x86_init_resources {
void (*probe_roms)(void);
void (*reserve_resources)(void);
- char *(*memory_setup)(void);
+ const char *(*memory_setup)(void);
};

/**
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index 988c00a1f6..14323a7c66 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -155,7 +155,7 @@ static void __init e820_print_type(u32 type)
}
}

-void __init e820_print_map(char *who)
+void __init e820_print_map(const char *who)
{
int i;

@@ -1021,9 +1021,9 @@ void __init e820_reserve_resources_late(void)
}
}

-char *__init default_machine_specific_memory_setup(void)
+const char *__init default_machine_specific_memory_setup(void)
{
- char *who = "BIOS-e820";
+ const char *who = "BIOS-e820";
u32 new_nr;
/*
* Try to copy the BIOS-supplied E820-map.
@@ -1061,7 +1061,7 @@ char *__init default_machine_specific_memory_setup(void)

void __init setup_memory_map(void)
{
- char *who;
+ const char *who;

who = x86_init.resources.memory_setup();
memcpy(&e820_saved, &e820, sizeof(struct e820map));
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index aae94132bc..28457edc2f 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -1167,7 +1167,7 @@ static struct notifier_block paniced = {
};

/* Setting up memory is fairly easy. */
-static __init char *lguest_memory_setup(void)
+static __init const char *lguest_memory_setup(void)
{
/*
* The Linux bootloader header contains an "e820" memory map: the
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index 2e555163c2..fabe61f6f3 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -336,7 +336,7 @@ void xen_ignore_unusable(struct e820entry *list, size_t map_size)
/**
* machine_specific_memory_setup - Hook for machine specific memory setup.
**/
-char * __init xen_memory_setup(void)
+const char * __init xen_memory_setup(void)
{
static struct e820entry map[E820MAX] __initdata;

@@ -502,7 +502,7 @@ char * __init xen_memory_setup(void)
/*
* Machine specific memory setup for auto-translated guests.
*/
-char * __init xen_auto_xlated_memory_setup(void)
+const char * __init xen_auto_xlated_memory_setup(void)
{
static struct e820entry map[E820MAX] __initdata;

diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index 97d87659f7..67b97574b1 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -35,8 +35,8 @@ void xen_mm_pin_all(void);
void xen_mm_unpin_all(void);
void xen_set_pat(u64);

-char * __init xen_memory_setup(void);
-char * xen_auto_xlated_memory_setup(void);
+const char * __init xen_memory_setup(void);
+const char * __init xen_auto_xlated_memory_setup(void);
void __init xen_arch_setup(void);
void xen_enable_sysenter(void);
void xen_enable_syscall(void);
--
1.7.10.4

2014-07-12 14:46:09

by Mathias Krause

[permalink] [raw]
Subject: [PATCH v2 2/8] printk: Provide pi_<level> / pe_<level> macros for __init / __exit code

The memory used for functions marked with __init will be released after
initialization, albeit static data referenced by such code will not, if
not explicitly marked this way, too. This is especially true for format
strings used in messages printed by such code. Those are not marked and
therefore will survive the __init cleanup -- dangling in memory without
ever being referenced again.

Ideally we would like the compiler to automatically recognise such
constructs but it does not and it's not as simple as it might sound, as
strings used in initialization code might latter still be used, e.g. as
a slab cache name. Therefore we need to explicitly mark the strings we
want to release together with the function itself.

For a seamless integration of the necessary __init_str() / __exit_str()
macros to mark the format strings, this patch provides new variants of
the well known pr_<level>() macros as pi_<level>() for __init code and
pe_<level>() for __exit code. Changing existing code should thereby be
as simple as changing a single letter.

For code that cannot be changed to use the pi_<level>() / pe_<level>()
macros printk_init() and printk_exit() macros are provided, too.

One remark, though: We cannot provide appropriate p[ie]_debug() macros
for the CONFIG_DYNAMIC_DEBUG case as there is (currently) no way to
remove entries from dyndbg after initialization. But supporting that
scenario would require more work (and code), therefore not necessarily
justifying the memory savings.

Signed-off-by: Mathias Krause <[email protected]>

---
v2: introduce printk_init / printk_exit macros (suggested by Joe)
---
include/linux/init.h | 7 ++++--
include/linux/printk.h | 59 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/include/linux/init.h b/include/linux/init.h
index 2c1cf10bb7..dc5691b2f3 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -39,14 +39,17 @@
* For strings used in __init / __exit functions the __init_str() /
* __exit_str() macros will take care of marking the strings accordingly so
* they can be freed, too. Otherwise the strings would resist in memory, even
- * though they are no longer referenced.
+ * though they are no longer referenced. They're also used to implement the
+ * printk_init() / printk_exit() macros.
*
* Use them like this:
*
* static int __init my_setup(char *arg)
* {
- * if (!strcmp(arg, __init_str("disable")))
+ * if (!strcmp(arg, __init_str("disable"))) {
+ * printk_init("Disabled by commandline\n");
* enabled = false;
+ * }
* }
* __setup("mydev=", my_setup);
*/
diff --git a/include/linux/printk.h b/include/linux/printk.h
index 319ff7e53e..342b9e9501 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -226,6 +226,10 @@ extern asmlinkage void dump_stack(void) __cold;
* All of these will print unconditionally, although note that pr_debug()
* and other debug macros are compiled out unless either DEBUG is defined
* or CONFIG_DYNAMIC_DEBUG is set.
+ *
+ * The printk_init() and pi_<level>() macros shall be used in __init code in
+ * favour of printk() / pr_<level>(). The printk_exit() and pe_<level>()
+ * variants shall be used in __exit code.
*/
#define pr_emerg(fmt, ...) \
printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
@@ -245,13 +249,60 @@ extern asmlinkage void dump_stack(void) __cold;
#define pr_cont(fmt, ...) \
printk(KERN_CONT fmt, ##__VA_ARGS__)

+#define printk_init(fmt, ...) \
+ printk(__init_str(fmt), ##__VA_ARGS__)
+#define printk_exit(fmt, ...) \
+ printk(__exit_str(fmt), ##__VA_ARGS__)
+
+#define pi_emerg(fmt, ...) \
+ printk_init(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
+#define pi_alert(fmt, ...) \
+ printk_init(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
+#define pi_crit(fmt, ...) \
+ printk_init(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
+#define pi_err(fmt, ...) \
+ printk_init(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
+#define pi_warning(fmt, ...) \
+ printk_init(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
+#define pi_warn pi_warning
+#define pi_notice(fmt, ...) \
+ printk_init(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
+#define pi_info(fmt, ...) \
+ printk_init(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
+#define pi_cont(fmt, ...) \
+ printk_init(KERN_CONT fmt, ##__VA_ARGS__)
+
+#define pe_emerg(fmt, ...) \
+ printk_exit(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
+#define pe_alert(fmt, ...) \
+ printk_exit(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
+#define pe_crit(fmt, ...) \
+ printk_exit(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
+#define pe_err(fmt, ...) \
+ printk_exit(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
+#define pe_warning(fmt, ...) \
+ printk_exit(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
+#define pe_warn pe_warning
+#define pe_notice(fmt, ...) \
+ printk_exit(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
+#define pe_info(fmt, ...) \
+ printk_exit(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
+#define pe_cont(fmt, ...) \
+ printk_exit(KERN_CONT fmt, ##__VA_ARGS__)
+
/* pr_devel() should produce zero code unless DEBUG is defined */
#ifdef DEBUG
#define pr_devel(fmt, ...) \
printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
+#define pi_devel(fmt, ...) \
+ printk_init(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
+#define pe_devel(fmt, ...) \
+ printk_exit(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#else
#define pr_devel(fmt, ...) \
no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
+#define pi_devel pr_devel
+#define pe_devel pr_devel
#endif

#include <linux/dynamic_debug.h>
@@ -261,12 +312,20 @@ extern asmlinkage void dump_stack(void) __cold;
/* dynamic_pr_debug() uses pr_fmt() internally so we don't need it here */
#define pr_debug(fmt, ...) \
dynamic_pr_debug(fmt, ##__VA_ARGS__)
+#define pi_debug pr_debug
+#define pe_debug pr_debug
#elif defined(DEBUG)
#define pr_debug(fmt, ...) \
printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
+#define pi_debug(fmt, ...) \
+ printk_init(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
+#define pe_debug(fmt, ...) \
+ printk_exit(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#else
#define pr_debug(fmt, ...) \
no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
+#define pi_debug pr_debug
+#define pe_debug pr_debug
#endif

/*
--
1.7.10.4

2014-07-15 23:23:35

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH v2 2/8] printk: Provide pi_<level> / pe_<level> macros for __init / __exit code

On Sat, 12 Jul 2014 16:43:26 +0200 Mathias Krause <[email protected]> wrote:

> The memory used for functions marked with __init will be released after
> initialization, albeit static data referenced by such code will not, if
> not explicitly marked this way, too. This is especially true for format
> strings used in messages printed by such code. Those are not marked and
> therefore will survive the __init cleanup -- dangling in memory without
> ever being referenced again.
>
> Ideally we would like the compiler to automatically recognise such
> constructs but it does not and it's not as simple as it might sound, as
> strings used in initialization code might latter still be used, e.g. as
> a slab cache name. Therefore we need to explicitly mark the strings we
> want to release together with the function itself.
>
> For a seamless integration of the necessary __init_str() / __exit_str()
> macros to mark the format strings, this patch provides new variants of
> the well known pr_<level>() macros as pi_<level>() for __init code and
> pe_<level>() for __exit code. Changing existing code should thereby be
> as simple as changing a single letter.
>
> For code that cannot be changed to use the pi_<level>() / pe_<level>()
> macros printk_init() and printk_exit() macros are provided, too.
>
> One remark, though: We cannot provide appropriate p[ie]_debug() macros
> for the CONFIG_DYNAMIC_DEBUG case as there is (currently) no way to
> remove entries from dyndbg after initialization. But supporting that
> scenario would require more work (and code), therefore not necessarily
> justifying the memory savings.

I assume that if a programmer gets this wrong,
CONFIG_DEBUG_SECTION_MISMATCH will detect and report the error?

Please thoroughly test this if you have not done so.

2014-07-15 23:27:00

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH v2 0/8] Mark literal strings in __init / __exit code

On Sat, 12 Jul 2014 16:43:24 +0200 Mathias Krause <[email protected]> wrote:

> This is v2 of the patch series initially posted here:
>
> https://lkml.org/lkml/2014/6/22/149

That was a useful overall description. But it got lost in the
transition to v2 and is now out of date.

Please resurrect it, and maintain it.

2014-07-16 06:29:17

by Mathias Krause

[permalink] [raw]
Subject: Re: [PATCH v2 2/8] printk: Provide pi_<level> / pe_<level> macros for __init / __exit code

On Tue, Jul 15, 2014 at 04:23:30PM -0700, Andrew Morton wrote:
> On Sat, 12 Jul 2014 16:43:26 +0200 Mathias Krause <[email protected]> wrote:
>
> > The memory used for functions marked with __init will be released after
> > initialization, albeit static data referenced by such code will not, if
> > not explicitly marked this way, too. This is especially true for format
> > strings used in messages printed by such code. Those are not marked and
> > therefore will survive the __init cleanup -- dangling in memory without
> > ever being referenced again.
> >
> > Ideally we would like the compiler to automatically recognise such
> > constructs but it does not and it's not as simple as it might sound, as
> > strings used in initialization code might latter still be used, e.g. as
> > a slab cache name. Therefore we need to explicitly mark the strings we
> > want to release together with the function itself.
> >
> > For a seamless integration of the necessary __init_str() / __exit_str()
> > macros to mark the format strings, this patch provides new variants of
> > the well known pr_<level>() macros as pi_<level>() for __init code and
> > pe_<level>() for __exit code. Changing existing code should thereby be
> > as simple as changing a single letter.
> >
> > For code that cannot be changed to use the pi_<level>() / pe_<level>()
> > macros printk_init() and printk_exit() macros are provided, too.
> >
> > One remark, though: We cannot provide appropriate p[ie]_debug() macros
> > for the CONFIG_DYNAMIC_DEBUG case as there is (currently) no way to
> > remove entries from dyndbg after initialization. But supporting that
> > scenario would require more work (and code), therefore not necessarily
> > justifying the memory savings.
>
> I assume that if a programmer gets this wrong,
> CONFIG_DEBUG_SECTION_MISMATCH will detect and report the error?

Yes it does. Very much the same as it detects wrong __init / __exit code
annotations. For wrong uses of the pi_*() / pe_*() helpers or manually
__init_str / __exit_str annotated strings modpost will detect all of the
following cases (8 wrong uses in total: 4 wrong pi_info / pe_info and 4
wrong __init_str / __exit_str annotations):

void __init init_fun(void)
{
pe_info("%s: Wrong use of pe_*() and __exit_str() in __init code\n",
__exit_str("init test"));
}

void normal_fun(void)
{
pi_info("%s: Wrong use of pi_*() and __init_str() in normal code\n",
__init_str("normal test"));
pe_info("%s: Wrong use of pe_*() and __exit_str() in normal code\n",
__exit_str("normal test"));
}

void __exit exit_fun(void)
{
pi_info("%s: Wrong use of pi_*() and __init_str() in __exit code\n",
__init_str("exit test"));
}

Those will be detected either rather silently with the following message:

WARNING: modpost: Found 8 section mismatch(es).
To see full details build your kernel with:
'make CONFIG_DEBUG_SECTION_MISMATCH=y'

Or, with CONFIG_DEBUG_SECTION_MISMATCH=y, rather verbose:

WARNING: lib/test_module.o(.text+0x4): Section mismatch in reference from the function normal_fun() to the variable .init.rodata:__UNIQUE_ID__init_str_3
The function normal_fun() references
the variable __initconst __UNIQUE_ID__init_str_3.
This is often because normal_fun lacks a __initconst
annotation or the annotation of __UNIQUE_ID__init_str_3 is wrong.

WARNING: lib/test_module.o(.text+0xb): Section mismatch in reference from the function normal_fun() to the variable .init.rodata:__UNIQUE_ID__init_str_2
The function normal_fun() references
the variable __initconst __UNIQUE_ID__init_str_2.
This is often because normal_fun lacks a __initconst
annotation or the annotation of __UNIQUE_ID__init_str_2 is wrong.

WARNING: lib/test_module.o(.text+0x1c): Section mismatch in reference from the function normal_fun() to the variable .exit.data:__UNIQUE_ID__exit_str_5
The function normal_fun() references a variable in an exit section.
Often the variable __UNIQUE_ID__exit_str_5 has valid usage outside the exit section
and the fix is to remove the __exitdata annotation of __UNIQUE_ID__exit_str_5.

WARNING: lib/test_module.o(.text+0x25): Section mismatch in reference from the function normal_fun() to the variable .exit.data:__UNIQUE_ID__exit_str_4
The function normal_fun() references a variable in an exit section.
Often the variable __UNIQUE_ID__exit_str_4 has valid usage outside the exit section
and the fix is to remove the __exitdata annotation of __UNIQUE_ID__exit_str_4.

WARNING: lib/test_module.o(.init.text+0x4): Section mismatch in reference from the function init_fun() to the variable .exit.data:__UNIQUE_ID__exit_str_1
The function __init init_fun() references
a variable __exitdata __UNIQUE_ID__exit_str_1.
This is often seen when error handling in the init function
uses functionality in the exit path.
The fix is often to remove the __exitdata annotation of
__UNIQUE_ID__exit_str_1 so it may be used outside an exit section.

WARNING: lib/test_module.o(.init.text+0xb): Section mismatch in reference from the function init_fun() to the variable .exit.data:__UNIQUE_ID__exit_str_0
The function __init init_fun() references
a variable __exitdata __UNIQUE_ID__exit_str_0.
This is often seen when error handling in the init function
uses functionality in the exit path.
The fix is often to remove the __exitdata annotation of
__UNIQUE_ID__exit_str_0 so it may be used outside an exit section.

WARNING: lib/test_module.o(.exit.text+0x4): Section mismatch in reference from the function exit_fun() to the variable .init.rodata:__UNIQUE_ID__init_str_7
The function __exit exit_fun() references
a variable __initconst __UNIQUE_ID__init_str_7.
This is often seen when error handling in the exit function
uses functionality in the init path.
The fix is often to remove the __initconst annotation of
__UNIQUE_ID__init_str_7 so it may be used outside an init section.

WARNING: lib/test_module.o(.exit.text+0xb): Section mismatch in reference from the function exit_fun() to the variable .init.rodata:__UNIQUE_ID__init_str_6
The function __exit exit_fun() references
a variable __initconst __UNIQUE_ID__init_str_6.
This is often seen when error handling in the exit function
uses functionality in the init path.
The fix is often to remove the __initconst annotation of
__UNIQUE_ID__init_str_6 so it may be used outside an init section.


I'll see if I can make modpost detect the __UNIQUE_ID__init_str_* /
__UNIQUE_ID__exit_str_* variables and emit a more fitting message in
this case.

>
> Please thoroughly test this if you have not done so.

I'll add the above in a more condensed form to the patch description as
this question came up for the second time, by now.


Thanks,
Mathias

2014-07-16 06:30:18

by Mathias Krause

[permalink] [raw]
Subject: Re: [PATCH v2 0/8] Mark literal strings in __init / __exit code

On Tue, Jul 15, 2014 at 04:26:54PM -0700, Andrew Morton wrote:
> On Sat, 12 Jul 2014 16:43:24 +0200 Mathias Krause <[email protected]> wrote:
>
> > This is v2 of the patch series initially posted here:
> >
> > https://lkml.org/lkml/2014/6/22/149
>
> That was a useful overall description. But it got lost in the
> transition to v2 and is now out of date.
>
> Please resurrect it, and maintain it.

Will do.

Thanks,
Mathias