Re: [PATCH 0/4] __cpuinitconst and __devinitconst

From: Sam Ravnborg
Date: Sat Jan 12 2008 - 15:56:40 EST


On Fri, Jan 11, 2008 at 08:44:28PM +0100, Sam Ravnborg wrote:
> Hi Jan.
>
> On Fri, Jan 11, 2008 at 08:55:29AM +0000, Jan Beulich wrote:
> > Since __cpuinitdata/__devinitdata don't allow const to be specified with
> > them (otherwise .init.data sections with and without the writeable attribute
> > will be generated by the compiler), and since __devinitdata except for
> > embedded systems evaluates to <empty> unconditionally and
> > __cpuinitdata at least in most production kernel configurations also
> > likely evaluates to <empty>, it seems appropriate to add an additional
> > attribute allowing the respective objects to end up in .rodata rather than
> > .data when not used at initialization time only.
>
> How about a slightly diffrent approach...
> Consider
> __cpuinitconst => function is placed in section .init.const.text
> __devinitconst => function is placed in section .init.const.text
>
> Then we in the linker scrip can distingush between the two
> and locate the sections as appropriate.
>
> This will require some updates to modpost but are align with an
> idea I have had for a while.
> All of the following should have dedicated sections associated
> unconditionally:
>
> __init
> __cpuinit
> __meminit
> __initdata
> __cpuinitdata
> __meminitdata
>
> And then in the linker script we decide what to do with the section.
> In the built-in case we put them in the "to-be-discarded" section.
> In the module case we put them as today.
>
> The primary tasks needed to accomplish this is:
> 1) Update all arch linker scripts (and some of them looks ugly)
> 2) Teach modpost about the new sections
>
> If you following the suggestion above this is a simple step
> in this direction which would be good.

The following patch implment first step in this direction.
It is only an RFC as I have not touched anything else than
64 bit x86 for the arch specific parts.
But it should show what I tried to say above.

On top of x86.git mm-branch.

Sam

diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S
index ba8ea97..26c1d81 100644
--- a/arch/x86/kernel/vmlinux_64.lds.S
+++ b/arch/x86/kernel/vmlinux_64.lds.S
@@ -155,12 +155,16 @@ SECTIONS
__init_begin = .;
.init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
_sinittext = .;
+ INIT_TEXT
*(.init.text)
_einittext = .;
}
- __initdata_begin = .;
- .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) }
- __initdata_end = .;
+ .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
+ __initdata_begin = .;
+ INIT_DATA
+ __initdata_end = .;
+ }
+
. = ALIGN(16);
__setup_start = .;
.init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { *(.init.setup) }
@@ -187,8 +191,12 @@ SECTIONS
}
/* .exit.text is discard at runtime, not link time, to deal with references
from .altinstructions and .eh_frame */
- .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) }
- .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) }
+ .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) {
+ EXIT_TEXT
+ }
+ .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) {
+ EXIT_DATA
+ }

/* vdso blob that is mapped into user space */
vdso_start = . ;
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 9f584cc..2f359d9 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -9,10 +9,48 @@
/* Align . to a 8 byte boundary equals to maximum function alignment. */
#define ALIGN_FUNCTION() . = ALIGN(8)

+#ifdef CONFIG_HOTPLUG
+#define DEV_KEEP(sec)
+#define DEV_DISCARD(sec) *(.dev##sec)
+#else
+#define DEV_KEEP(sec) *(.dev##sec)
+#define DEV_DISCARD(sec)
+#endif
+
+#ifdef CONFIG_HOTPLUG_CPU
+#define CPU_KEEP(sec)
+#define CPU_DISCARD(sec) *(.cpu##sec)
+#else
+#define CPU_KEEP(sec) *(.cpu##sec)
+#define CPU_DISCARD(sec)
+#endif
+
+#if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \
+ || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
+#define MEM_KEEP(sec)
+#define MEM_DISCARD(sec) *(.mem##sec)
+#else
+#define MEM_KEEP(sec) *(.mem##sec)
+#define MEM_DISCARD(sec)
+#endif
+
+
/* .data section */
#define DATA_DATA \
*(.data) \
*(.data.init.refok) \
+ DEV_KEEP(init.data) \
+ DEV_KEEP(init.data.const) \
+ DEV_KEEP(exit.data) \
+ DEV_KEEP(exit.data.const) \
+ CPU_KEEP(init.data) \
+ CPU_KEEP(init.data.const) \
+ CPU_KEEP(exit.data) \
+ CPU_KEEP(exit.data.const) \
+ MEM_KEEP(init.data) \
+ MEM_KEEP(init.data.const) \
+ MEM_KEEP(exit.data) \
+ MEM_KEEP(exit.data.const) \
. = ALIGN(8); \
VMLINUX_SYMBOL(__start___markers) = .; \
*(__markers) \
@@ -159,7 +197,14 @@
ALIGN_FUNCTION(); \
*(.text) \
*(.text.init.refok) \
- *(.exit.text.refok)
+ *(.exit.text.refok) \
+ DEV_KEEP(init.text) \
+ DEV_KEEP(exit.text) \
+ CPU_KEEP(init.text) \
+ CPU_KEEP(exit.text) \
+ MEM_KEEP(init.text) \
+ MEM_KEEP(exit.text)
+

/* sched.text is aling to function alignment to secure we have same
* address even at second ld pass when generating System.map */
@@ -255,6 +300,36 @@
*(.initcall7.init) \
*(.initcall7s.init)

+#define INIT_DATA \
+ *(.init.data) \
+ DEV_DISCARD(init.data) \
+ DEV_DISCARD(init.data.const) \
+ CPU_DISCARD(init.data) \
+ CPU_DISCARD(init.data.const) \
+ MEM_DISCARD(init.data) \
+ MEM_DISCARD(init.data.const)
+
+#define INIT_TEXT \
+ *(.init.text) \
+ DEV_DISCARD(init.text) \
+ CPU_DISCARD(init.text) \
+ MEM_DISCARD(init.text)
+
+#define EXIT_DATA \
+ *(.exit.data) \
+ DEV_DISCARD(exit.data) \
+ DEV_DISCARD(exit.data.const) \
+ CPU_DISCARD(exit.data) \
+ CPU_DISCARD(exit.data.const) \
+ MEM_DISCARD(exit.data) \
+ MEM_DISCARD(exit.data.const)
+
+#define EXIT_TEXT \
+ *(.exit.text) \
+ DEV_DISCARD(exit.text) \
+ CPU_DISCARD(exit.text) \
+ MEM_DISCARD(exit.text)
+
#define PERCPU(align) \
. = ALIGN(align); \
__per_cpu_start = .; \
diff --git a/include/linux/init.h b/include/linux/init.h
index 86e7e94..b72897d 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -254,42 +254,26 @@ void __init parse_early_param(void);
#define __initdata_or_module __initdata
#endif /*CONFIG_MODULES*/

-#ifdef CONFIG_HOTPLUG
-#define __devinit
-#define __devinitdata
-#define __devexit
-#define __devexitdata
-#else
-#define __devinit __init
-#define __devinitdata __initdata
-#define __devexit __exit
-#define __devexitdata __exitdata
-#endif
-
-#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_CPUINIT)
-#define __cpuinit
-#define __cpuinitdata
-#define __cpuexit
-#define __cpuexitdata
-#else
-#define __cpuinit __init
-#define __cpuinitdata __initdata
-#define __cpuexit __exit
-#define __cpuexitdata __exitdata
-#endif
-
-#if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \
- || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
-#define __meminit
-#define __meminitdata
-#define __memexit
-#define __memexitdata
-#else
-#define __meminit __init
-#define __meminitdata __initdata
-#define __memexit __exit
-#define __memexitdata __exitdata
-#endif
+#define __devinit __attribute__ ((__section__ (".devinit.text")))
+#define __devinitdata __attribute__ ((__section__ (".devinit.data")))
+#define __devinitcdata __attribute__ ((__section__ (".devinit.data.const")))
+#define __devexit __attribute__ ((__section__ (".devexit.text")))
+#define __devexitdata __attribute__ ((__section__ (".devexit.data")))
+#define __devexitcdata __attribute__ ((__section__ (".devexit.data.const")))
+
+#define __cpuinit __attribute__ ((__section__ (".cpuinit.text")))
+#define __cpuinitdata __attribute__ ((__section__ (".cpuinit.data")))
+#define __cpuinitcdata __attribute__ ((__section__ (".cpuinit.data.const")))
+#define __cpuexit __attribute__ ((__section__ (".cpuexit.text")))
+#define __cpuexitdata __attribute__ ((__section__ (".cpuexit.data")))
+#define __cpuexitcdata __attribute__ ((__section__ (".cpuexit.data.const")))
+
+#define __meminit __attribute__ ((__section__ (".meminit.text")))
+#define __meminitdata __attribute__ ((__section__ (".meminit.data")))
+#define __meminitcdata __attribute__ ((__section__ (".meminit.data.const")))
+#define __memexit __attribute__ ((__section__ (".memexit.text")))
+#define __memexitdata __attribute__ ((__section__ (".memexit.data")))
+#define __memexitcdata __attribute__ ((__section__ (".memexit.data.const")))

/* Functions marked as __devexit may be discarded at kernel link time, depending
on config options. Newer versions of binutils detect references from
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/