x86/nmi: Fix section mismatch warnings on 32-bit

It was reported that compiling for 32-bit caused a bunch of
section mismatch warnings:

VDSOSYM arch/x86/vdso/vdso32-syms.lds
LD arch/x86/vdso/built-in.o
LD arch/x86/built-in.o

WARNING: arch/x86/built-in.o(.data+0x5af0): Section mismatch in
reference from the variable test_nmi_ipi_callback_na.10451 to
the function .init.text:test_nmi_ipi_callback() [...]

WARNING: arch/x86/built-in.o(.data+0x5b04): Section mismatch in
reference from the variable nmi_unk_cb_na.10399 to the function
.init.text:nmi_unk_cb() The variable nmi_unk_cb_na.10399
references the function __init nmi_unk_cb() [...]

Both of these are attributed to the internal representation of
the nmiaction struct created during register_nmi_handler. The
reason for this is that those structs are not defined in the
init section whereas the rest of the code in nmi_selftest.c is.

To resolve this, I created a new #define,
register_nmi_handler_initonly, that tags the struct as
__initdata to resolve the mismatch. This #define should only be
used in rare situations where the register/unregister is called
during init of the kernel.

Big thanks to Jan Beulich for decoding this for me as I didn't
have a clue what was going on.

Reported-by: Witold Baryluk <baryluk@smp.if.uj.edu.pl>
Tested-by: Witold Baryluk <baryluk@smp.if.uj.edu.pl>
Cc: Jan Beulich <JBeulich@suse.com>
Signed-off-by: Don Zickus <dzickus@redhat.com>
Link: http://lkml.kernel.org/r/1338991542-23000-1-git-send-email-dzickus@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>

authored by

Don Zickus and committed by
Ingo Molnar
eeaaa96a d5d2d2ee

+16 -2
+14
arch/x86/include/asm/nmi.h
··· 54 54 __register_nmi_handler((t), &fn##_na); \ 55 55 }) 56 56 57 + /* 58 + * For special handlers that register/unregister in the 59 + * init section only. This should be considered rare. 60 + */ 61 + #define register_nmi_handler_initonly(t, fn, fg, n) \ 62 + ({ \ 63 + static struct nmiaction fn##_na __initdata = { \ 64 + .handler = (fn), \ 65 + .name = (n), \ 66 + .flags = (fg), \ 67 + }; \ 68 + __register_nmi_handler((t), &fn##_na); \ 69 + }) 70 + 57 71 int __register_nmi_handler(unsigned int, struct nmiaction *); 58 72 59 73 void unregister_nmi_handler(unsigned int, const char *);
+2 -2
arch/x86/kernel/nmi_selftest.c
··· 42 42 static void __init init_nmi_testsuite(void) 43 43 { 44 44 /* trap all the unknown NMIs we may generate */ 45 - register_nmi_handler(NMI_UNKNOWN, nmi_unk_cb, 0, "nmi_selftest_unk"); 45 + register_nmi_handler_initonly(NMI_UNKNOWN, nmi_unk_cb, 0, "nmi_selftest_unk"); 46 46 } 47 47 48 48 static void __init cleanup_nmi_testsuite(void) ··· 64 64 { 65 65 unsigned long timeout; 66 66 67 - if (register_nmi_handler(NMI_LOCAL, test_nmi_ipi_callback, 67 + if (register_nmi_handler_initonly(NMI_LOCAL, test_nmi_ipi_callback, 68 68 NMI_FLAG_FIRST, "nmi_selftest")) { 69 69 nmi_fail = FAILURE; 70 70 return;