[OPW,kernel,RFC] include/linux: Constant folding for kernel core_param
diff mbox

Message ID 20150227163435.GA24873@winterfell
State New, archived
Headers show

Commit Message

Iulia Manda Feb. 27, 2015, 4:34 p.m. UTC
This patch aims to prove GCC's capability to constant fold kernel command line
arguments, if they are specified at compile time and no argument is passed at
boot time.

At the moment, this patch treats only core_param arguments and exemplified on
initcall_debug. Also, initcall_debug variable is set to a default value,
known at compile time.

Because at some point we need to access the address of var, it can not be const.
This is why we need to add a dummy variable that does not affect the rest of
the code and only provides us with a valid address of var, knowing that in this
case that address will never be used.

Bloat-o-meter output:

add/remove: 1/0 grow/shrink: 0/2 up/down: 1/-95 (-94)
function                                     old     new   delta
__initcall_debug                               -       1      +1
async_run_entry_fn                           178     174      -4
do_one_initcall                              339     248     -91

Signed-off-by: Iulia Manda <iulia.manda21@gmail.com>
---
 include/linux/init.h        |    4 ++++
 include/linux/moduleparam.h |    8 ++++++++
 init/main.c                 |    4 ++++
 3 files changed, 16 insertions(+)

Comments

Josh Triplett Feb. 27, 2015, 5:49 p.m. UTC | #1
On Fri, Feb 27, 2015 at 06:34:35PM +0200, Iulia Manda wrote:
> This patch aims to prove GCC's capability to constant fold kernel command line
> arguments, if they are specified at compile time and no argument is passed at
> boot time.
> 
> At the moment, this patch treats only core_param arguments and exemplified on
> initcall_debug. Also, initcall_debug variable is set to a default value,
> known at compile time.
> 
> Because at some point we need to access the address of var, it can not be const.
> This is why we need to add a dummy variable that does not affect the rest of
> the code and only provides us with a valid address of var, knowing that in this
> case that address will never be used.

The kernel config option needs to have "no" as the "don't support kernel
command-line, make everything const" option, and "yes" as the "do
support parsing a kernel command line" option, so that "make
allnoconfig" and "make tinyconfig" do the right thing.  (Related to
that, the option could actually turn off kernel command-line processing,
and the option to compile in a kernel command line should depend on it.
You also need to include the Kconfig bits in the patch.)

Also, you don't want to introduce ifdefs at the point of usage.
Instead, core_default_param should always exist, and should use "const"
when the config option is enabled.  I'd also suggest renaming it to
DEFINE_CORE_PARAM, as a parallel to similar macros that define
variables.  Similarly, you should have a DECLARE_CORE_PARAM, which
translates to the necessary "extern" statement.  Then neither the
definition nor the declaration of initcall_debug will need an ifdef.

When the config option is disabled, you should *only* define the const
variable, and not define the command-line handling at all.

Finally, you'll want to post this as a two-patch series, the first
introducing the macros, and the second changing something like
initcall_debug over to use it.

- Josh Triplett

Patch
diff mbox

diff --git a/include/linux/init.h b/include/linux/init.h
index 2df8e8d..cb96cd3 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -155,7 +155,11 @@  int __init init_rootfs(void);
 
 extern void (*late_time_init)(void);
 
+#ifdef CONFIG_CMDLINE_OVERRIDE
+extern const bool initcall_debug;
+#else
 extern bool initcall_debug;
+#endif
 
 #endif
   
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index 1c9effa..4d42302 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -310,8 +310,16 @@  static inline void __kernel_param_unlock(void)
 #define core_param(name, var, type, perm)				\
 	param_check_##type(name, &(var));				\
 	__module_param_call("", name, &param_ops_##type, &var, perm, -1, 0)
+
+#ifdef CONFIG_CMDLINE_OVERRIDE
+#define core_default_param(name, var, val, type, perm)			\
+        const type name = val;                                          \
+        type __##var;                                                   \
+        core_param(name, __##var, type, perm);
+#endif
 #endif /* !MODULE */
 
+
 /**
  * module_param_string - a char array parameter
  * @name: the name of the parameter
diff --git a/init/main.c b/init/main.c
index 61b99376..9a9fd10 100644
--- a/init/main.c
+++ b/init/main.c
@@ -698,8 +698,12 @@  static void __init do_ctors(void)
 #endif
 }
 
+#ifdef CONFIG_CMDLINE_OVERRIDE
+core_default_param(initcall_debug, initcall_debug, 0, bool, 0644);
+#else
 bool initcall_debug;
 core_param(initcall_debug, initcall_debug, bool, 0644);
+#endif
 
 #ifdef CONFIG_KALLSYMS
 struct blacklist_entry {