[<prev] [next>] [day] [month] [year] [list]
Message-Id: <200812012325.08606.rusty@rustcorp.com.au>
Date: Mon, 1 Dec 2008 23:25:08 +1030
From: Rusty Russell <rusty@...tcorp.com.au>
To: linux-kernel@...r.kernel.org
Subject: [RFC 2/8] core_param: call these really, really early.
As soon as we have command line, so even before early_param. They
just set vars, so it makes sense to do them as early as possible.
This allows them to replace early_param, and fixes a bug in the new
cpu_alloc implementation patches which was a complete PITA to find.
Signed-off-by: Rusty Russell <rusty@...tcorp.com.au>
---
include/asm-generic/vmlinux.lds.h | 3 +++
include/linux/moduleparam.h | 26 ++++++++++++++++----------
init/main.c | 25 ++++++++++++++++++++++++-
kernel/params.c | 20 ++++++++++----------
4 files changed, 53 insertions(+), 21 deletions(-)
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -213,6 +213,9 @@
VMLINUX_SYMBOL(__start___param) = .; \
*(__param) \
VMLINUX_SYMBOL(__stop___param) = .; \
+ VMLINUX_SYMBOL(__start___core_param) = .; \
+ *(__core_param) \
+ VMLINUX_SYMBOL(__stop___core_param) = .; \
. = ALIGN((align)); \
VMLINUX_SYMBOL(__end_rodata) = .; \
} \
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -79,7 +79,7 @@ struct kparam_array
parameters. perm sets the visibility in sysfs: 000 means it's
not there, read bits mean it's readable, write bits mean it's
writable. */
-#define __module_param_call(prefix, name, set, get, arg, perm) \
+#define __module_param_call(prefix, section, name, set, get, arg, perm) \
/* Default value instead of permissions? */ \
static int __param_perm_check_##name __attribute__((unused)) = \
BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)) \
@@ -87,11 +87,12 @@ struct kparam_array
static const char __param_str_##name[] = prefix #name; \
static struct kernel_param __moduleparam_const __param_##name \
__used \
- __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \
+ __attribute__ ((unused, __section__(section), aligned(sizeof(void *)))) \
= { __param_str_##name, perm, set, get, { arg } }
#define module_param_call(name, set, get, arg, perm) \
- __module_param_call(MODULE_PARAM_PREFIX, name, set, get, arg, perm)
+ __module_param_call(MODULE_PARAM_PREFIX, "__param", \
+ name, set, get, arg, perm)
/* Helper functions: type is byte, short, ushort, int, uint, long,
ulong, charp, bool or invbool, or XXX if you define param_get_XXX,
@@ -106,21 +107,22 @@ struct kparam_array
#ifndef MODULE
/**
- * core_param - define a historical core kernel parameter.
+ * core_param - define a core kernel parameter to be set very early
* @name: the name of the cmdline and sysfs parameter (often the same as var)
* @var: the variable
* @type: the type (for param_set_##type and param_get_##type)
* @perm: visibility in sysfs
*
- * core_param is just like module_param(), but cannot be modular and
- * doesn't add a prefix (such as "printk."). This is for compatibility
- * with __setup(), and it makes sense as truly core parameters aren't
- * tied to the particular file they're in.
+ * core_param is just like module_param(), but cannot be modular,
+ * doesn't add a prefix (such as "printk.") and is called insanely
+ * early in boot. This is for compatibility with __setup(), and it
+ * makes sense as truly core parameters aren't tied to the particular
+ * file they're in.
*/
#define core_param(name, var, type, perm) \
param_check_##type(name, &(var)); \
- __module_param_call("", name, param_set_##type, param_get_##type, \
- &var, perm)
+ __module_param_call("", "__core_param", name, param_set_##type, \
+ param_get_##type, &var, perm)
#endif /* !MODULE */
/* Actually copy string: maxlen param is usually sizeof(string). */
@@ -224,4 +226,8 @@ static inline void module_param_sysfs_re
{ }
#endif
+/* Created by include/asm-generic/vmlinux.lds.h */
+extern struct kernel_param __start___core_param[], __stop___core_param[];
+extern struct kernel_param __start___param[], __stop___param[];
+
#endif /* _LINUX_MODULE_PARAMS_H */
diff --git a/init/main.c b/init/main.c
--- a/init/main.c
+++ b/init/main.c
@@ -256,12 +256,32 @@ static int __init loglevel(char *str)
early_param("loglevel", loglevel);
+static bool __init is_core_param(const char *param)
+{
+ const struct kernel_param *i;
+
+ for (i = __start___core_param; i < __stop___core_param; i++)
+ if (strcmp(param, i->name) == 0)
+ return true;
+ return false;
+}
+
+/* We can ignore options not found in core params. */
+static int __init unknown_core_ok(char *param, char *val)
+{
+ return 0;
+}
+
/*
* Unknown boot options get handed to init, unless they look like
* failed parameters
*/
static int __init unknown_bootoption(char *param, char *val)
{
+ /* Already handled as a core param? */
+ if (is_core_param(param))
+ return 0;
+
/* Change NUL term back to "=", to make "param" the whole string. */
if (val) {
/* param=val or param="val"? */
@@ -537,7 +557,6 @@ asmlinkage void __init start_kernel(void
asmlinkage void __init start_kernel(void)
{
char * command_line;
- extern struct kernel_param __start___param[], __stop___param[];
smp_setup_processor_id();
@@ -567,6 +586,10 @@ asmlinkage void __init start_kernel(void
setup_arch(&command_line);
mm_init_owner(&init_mm, &init_task);
setup_command_line(command_line);
+ parse_args("Core params", command_line, __start___core_param,
+ __stop___core_param - __start___core_param,
+ unknown_core_ok, true);
+
unwind_setup();
setup_per_cpu_areas();
setup_nr_cpu_ids();
diff --git a/kernel/params.c b/kernel/params.c
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -376,8 +376,6 @@ int param_get_string(char *buffer, struc
#define to_module_attr(n) container_of(n, struct module_attribute, attr);
#define to_module_kobject(n) container_of(n, struct module_kobject, kobj);
-extern struct kernel_param __start___param[], __stop___param[];
-
struct param_attribute
{
struct module_attribute mattr;
@@ -636,15 +634,19 @@ static void __init param_sysfs_builtin(v
continue;
dot = strchr(kp->name, '.');
- if (!dot) {
- /* This happens for core_param() */
- strcpy(modname, "kernel");
- name_len = 0;
- } else {
- name_len = dot - kp->name + 1;
- strlcpy(modname, kp->name, name_len);
- }
+ /* FIXME: USB code sets prefix to "". Should use core_param */
+ if (!dot)
+ continue;
+ name_len = dot - kp->name + 1;
+ strlcpy(modname, kp->name, name_len);
kernel_add_sysfs_param(modname, kp, name_len);
+ }
+
+ for (kp = __start___core_param; kp < __stop___core_param; kp++) {
+ if (kp->perm == 0)
+ continue;
+
+ kernel_add_sysfs_param("kernel", kp, 0);
}
}
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists