* [PATCH 0/2] x86/earlyprintk: setup earlyprintk as early as possible
@ 2015-04-08 9:31 Alexander Kuleshov
2015-04-08 9:31 ` [PATCH 1/2] x86/setup: update boot_command_line with builtin_cmdline in separate function Alexander Kuleshov
2015-04-08 9:31 ` [PATCH 2/2] x86/earlyprintk: setup earlyprintk as early as possible Alexander Kuleshov
0 siblings, 2 replies; 5+ messages in thread
From: Alexander Kuleshov @ 2015-04-08 9:31 UTC (permalink / raw)
To: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Greg Kroah-Hartman,
Yinghai Lu
Cc: linux-kernel
As setup_early_printk passed to the early_param, it will be usable only after
'parse_early_param' function will be called from the 'setup_arch'. So we have
earlyprintk during early boot and decompression. Next point after decompression
of the kernel where we can use early_printk is after call of the
'parse_early_param'.
This patch provides initialization of earlyprintk serial console as early
as possible in the arch/x86/kerne/head{32,64}.c
Alexander Kuleshov (2):
x86/setup: update boot_command_line with builtin_cmdline in separate
function
x86/earlyprintk: setup earlyprintk as early as possible
arch/x86/kernel/early_printk.c | 2 +-
arch/x86/kernel/head.c | 14 ++++++++++++++
arch/x86/kernel/head32.c | 3 +++
arch/x86/kernel/head64.c | 8 +++++++-
arch/x86/kernel/setup.c | 31 ++++++++++++++++++-------------
include/linux/init.h | 6 +++++-
include/linux/printk.h | 4 ++++
kernel/printk/printk.c | 11 +++++++----
8 files changed, 59 insertions(+), 20 deletions(-)
--
2.3.3.611.g09038fc.dirty
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH 1/2] x86/setup: update boot_command_line with builtin_cmdline in separate function 2015-04-08 9:31 [PATCH 0/2] x86/earlyprintk: setup earlyprintk as early as possible Alexander Kuleshov @ 2015-04-08 9:31 ` Alexander Kuleshov 2015-04-08 9:31 ` [PATCH 2/2] x86/earlyprintk: setup earlyprintk as early as possible Alexander Kuleshov 1 sibling, 0 replies; 5+ messages in thread From: Alexander Kuleshov @ 2015-04-08 9:31 UTC (permalink / raw) To: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Greg Kroah-Hartman, Yinghai Lu Cc: linux-kernel, Alexander Kuleshov This patch introduces setup_cmdline function which appends/overrides boot_command_linew with builtin_cmdline if CONFIG_CMDLINE_BOOL is set. Previously this functional was in the setup_arch, but we need to move it for getting actual command line as early as possible in the arch/x86/kernel/head{32,64}.c Signed-off-by: Alexander Kuleshov <kuleshovmail@gmail.com> --- arch/x86/kernel/head32.c | 1 + arch/x86/kernel/head64.c | 1 + arch/x86/kernel/setup.c | 31 ++++++++++++++++++------------- include/linux/init.h | 6 +++++- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c index 2911ef3..7ad0ad0 100644 --- a/arch/x86/kernel/head32.c +++ b/arch/x86/kernel/head32.c @@ -31,6 +31,7 @@ static void __init i386_default_early_setup(void) asmlinkage __visible void __init i386_start_kernel(void) { + setup_cmdline(); cr4_init_shadow(); sanitize_boot_params(&boot_params); diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index c4f8d46..6eea2de 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -171,6 +171,7 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data) load_idt((const struct desc_ptr *)&idt_descr); copy_bootdata(__va(real_mode_data)); + setup_cmdline(); /* * Load microcode early on BSP. diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 0a2421c..d578f37 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -841,6 +841,24 @@ dump_kernel_offset(struct notifier_block *self, unsigned long v, void *p) } /* + * Append/Override boot command line with builtin command line if need + */ +void __init setup_cmdline(void) { +#ifdef CONFIG_CMDLINE_BOOL +#ifdef CONFIG_CMDLINE_OVERRIDE + strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); +#else + if (builtin_cmdline[0]) { + /* append boot loader cmdline to builtin */ + strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE); + strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE); + strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); + } +#endif +#endif +} + +/* * Determine if we were loaded by an EFI loader. If so, then we have also been * passed the efi memmap, systab, etc., so we should use these data structures * for initialization. Note, the efi init code path is determined by the @@ -968,19 +986,6 @@ void __init setup_arch(char **cmdline_p) bss_resource.start = __pa_symbol(__bss_start); bss_resource.end = __pa_symbol(__bss_stop)-1; -#ifdef CONFIG_CMDLINE_BOOL -#ifdef CONFIG_CMDLINE_OVERRIDE - strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); -#else - if (builtin_cmdline[0]) { - /* append boot loader cmdline to builtin */ - strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE); - strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE); - strlcpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE); - } -#endif -#endif - strlcpy(command_line, boot_command_line, COMMAND_LINE_SIZE); *cmdline_p = command_line; diff --git a/include/linux/init.h b/include/linux/init.h index 2df8e8d..af8f2ec 100644 --- a/include/linux/init.h +++ b/include/linux/init.h @@ -152,7 +152,11 @@ void setup_arch(char **); void prepare_namespace(void); void __init load_default_modules(void); int __init init_rootfs(void); - +#ifdef CONFIG_CMDLINE_BOOL +void __init setup_cmdline(void); +#else +static void __init setup_cmdline(void) {}; +#endif extern void (*late_time_init)(void); extern bool initcall_debug; -- 2.3.3.611.g09038fc.dirty ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] x86/earlyprintk: setup earlyprintk as early as possible 2015-04-08 9:31 [PATCH 0/2] x86/earlyprintk: setup earlyprintk as early as possible Alexander Kuleshov 2015-04-08 9:31 ` [PATCH 1/2] x86/setup: update boot_command_line with builtin_cmdline in separate function Alexander Kuleshov @ 2015-04-08 9:31 ` Alexander Kuleshov 2015-04-08 11:32 ` Peter Hurley 1 sibling, 1 reply; 5+ messages in thread From: Alexander Kuleshov @ 2015-04-08 9:31 UTC (permalink / raw) To: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Greg Kroah-Hartman, Yinghai Lu Cc: linux-kernel, Alexander Kuleshov As setup_early_printk passed to the early_param, it will be usable only after 'parse_early_param' function will be called from the 'setup_arch'. So we have earlyprintk during early boot and decompression. Next point after decompression of the kernel where we can use early_printk is after call of the 'parse_early_param'. This patch makes setup_early_printk visible for head{32,64}.c So 'early_printk' function will be usabable after decompression of the kernel and before parse_early_param will be called. It also must be safe if CONFIG_CMDLINE_BOOL and CONFIG_CMDLINE_OVERRIDE are set, because setup_cmdline function will be called before setup_early_printk. Tested it with qemu, so early_printk() is usable and prints to serial console right after setup_early_printk function called from arch/x86/kerne/head64.c Changes v1->v2: * Comment added before the setup_early_printk call; * Added information about testing to the commit message. Changes v2->v3: * Call setup_cmdline before setup_early_printk; * setup_early_printk call wrapped with the setup_early_serial_console which checks that 'serial' given to the earlyprintk command line option. This prevents call of the setup_early_printk with the given pciserial/dbgp/efi, because they are using early_ioremap. Signed-off-by: Alexander Kuleshov <kuleshovmail@gmail.com> --- arch/x86/kernel/early_printk.c | 2 +- arch/x86/kernel/head.c | 14 ++++++++++++++ arch/x86/kernel/head32.c | 2 ++ arch/x86/kernel/head64.c | 7 ++++++- include/linux/printk.h | 4 ++++ kernel/printk/printk.c | 11 +++++++---- 6 files changed, 34 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index a62536a..19a94e0 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c @@ -329,7 +329,7 @@ static inline void early_console_register(struct console *con, int keep_early) register_console(early_console); } -static int __init setup_early_printk(char *buf) +int __init setup_early_printk(char *buf) { int keep; diff --git a/arch/x86/kernel/head.c b/arch/x86/kernel/head.c index 992f442..b6e72aa 100644 --- a/arch/x86/kernel/head.c +++ b/arch/x86/kernel/head.c @@ -69,3 +69,17 @@ void __init reserve_ebda_region(void) /* reserve all memory between lowmem and the 1MB mark */ memblock_reserve(lowmem, 0x100000 - lowmem); } + +void setup_early_serial_console() { +#ifdef CONFIG_EARLY_PRINTK + char *arg; + + arg = strstr(boot_command_line, "earlyprintk=serial"); + if (!arg) + arg = strstr(boot_command_line, "earlyprintk=ttyS"); + if (!arg) + return; + + setup_early_printk(boot_command_line); +#endif +} diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c index 7ad0ad0..64c7a80 100644 --- a/arch/x86/kernel/head32.c +++ b/arch/x86/kernel/head32.c @@ -32,6 +32,8 @@ static void __init i386_default_early_setup(void) asmlinkage __visible void __init i386_start_kernel(void) { setup_cmdline(); + /* setup serial console as early as possible */ + setup_early_serial_console(); cr4_init_shadow(); sanitize_boot_params(&boot_params); diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 6eea2de..f0c03bd 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -172,12 +172,15 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data) copy_bootdata(__va(real_mode_data)); setup_cmdline(); + /* setup serial console as early as possible */ + setup_early_serial_console(); /* * Load microcode early on BSP. */ load_ucode_bsp(); + if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG) early_printk("Kernel alive\n"); @@ -193,8 +196,10 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data) void __init x86_64_start_reservations(char *real_mode_data) { /* version is always not zero if it is copied */ - if (!boot_params.hdr.version) + if (!boot_params.hdr.version) { copy_bootdata(__va(real_mode_data)); + setup_early_serial_console(); + } reserve_ebda_region(); diff --git a/include/linux/printk.h b/include/linux/printk.h index baa3f97..17358dd 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -115,9 +115,13 @@ int no_printk(const char *fmt, ...) #ifdef CONFIG_EARLY_PRINTK extern asmlinkage __printf(1, 2) void early_printk(const char *fmt, ...); +int setup_early_printk(char *buf); +void setup_early_serial_console(void); #else static inline __printf(1, 2) __cold void early_printk(const char *s, ...) { } +int setup_early_printk(char *buf) { } +static void setup_early_serial_console(void) { } #endif typedef int(*printk_func_t)(const char *fmt, va_list args); diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index bb0635b..e56285c 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -2409,11 +2409,14 @@ void register_console(struct console *newcon) struct console_cmdline *c; if (console_drivers) - for_each_console(bcon) - if (WARN(bcon == newcon, - "console '%s%d' already registered\n", - bcon->name, bcon->index)) + for_each_console(bcon) { + /* not again */ + if (bcon == newcon) { + printk(KERN_INFO "console '%s%d' already registered\n", + bcon->name, bcon->index); return; + } + } /* * before we register a new CON_BOOT console, make sure we don't -- 2.3.3.611.g09038fc.dirty ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] x86/earlyprintk: setup earlyprintk as early as possible 2015-04-08 9:31 ` [PATCH 2/2] x86/earlyprintk: setup earlyprintk as early as possible Alexander Kuleshov @ 2015-04-08 11:32 ` Peter Hurley 2015-04-09 7:39 ` Alexander Kuleshov 0 siblings, 1 reply; 5+ messages in thread From: Peter Hurley @ 2015-04-08 11:32 UTC (permalink / raw) To: Alexander Kuleshov, Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Greg Kroah-Hartman, Yinghai Lu Cc: linux-kernel Hi Alexander, On 04/08/2015 05:31 AM, Alexander Kuleshov wrote: > As setup_early_printk passed to the early_param, it will be usable only after > 'parse_early_param' function will be called from the 'setup_arch'. So we have > earlyprintk during early boot and decompression. Next point after decompression > of the kernel where we can use early_printk is after call of the > 'parse_early_param'. > > This patch makes setup_early_printk visible for head{32,64}.c So 'early_printk' > function will be usabable after decompression of the kernel and before > parse_early_param will be called. It also must be safe if CONFIG_CMDLINE_BOOL > and CONFIG_CMDLINE_OVERRIDE are set, because setup_cmdline function will be > called before setup_early_printk. > > Tested it with qemu, so early_printk() is usable and prints to serial console > right after setup_early_printk function called from arch/x86/kerne/head64.c > > Changes v1->v2: > > * Comment added before the setup_early_printk call; > * Added information about testing to the commit message. > > Changes v2->v3: > > * Call setup_cmdline before setup_early_printk; > * setup_early_printk call wrapped with the setup_early_serial_console which > checks that 'serial' given to the earlyprintk command line option. This > prevents call of the setup_early_printk with the given pciserial/dbgp/efi, > because they are using early_ioremap. > > Signed-off-by: Alexander Kuleshov <kuleshovmail@gmail.com> > --- > arch/x86/kernel/early_printk.c | 2 +- > arch/x86/kernel/head.c | 14 ++++++++++++++ > arch/x86/kernel/head32.c | 2 ++ > arch/x86/kernel/head64.c | 7 ++++++- > include/linux/printk.h | 4 ++++ > kernel/printk/printk.c | 11 +++++++---- > 6 files changed, 34 insertions(+), 6 deletions(-) > > diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c > index a62536a..19a94e0 100644 > --- a/arch/x86/kernel/early_printk.c > +++ b/arch/x86/kernel/early_printk.c > @@ -329,7 +329,7 @@ static inline void early_console_register(struct console *con, int keep_early) > register_console(early_console); > } > > -static int __init setup_early_printk(char *buf) > +int __init setup_early_printk(char *buf) > { > int keep; > > diff --git a/arch/x86/kernel/head.c b/arch/x86/kernel/head.c > index 992f442..b6e72aa 100644 > --- a/arch/x86/kernel/head.c > +++ b/arch/x86/kernel/head.c > @@ -69,3 +69,17 @@ void __init reserve_ebda_region(void) > /* reserve all memory between lowmem and the 1MB mark */ > memblock_reserve(lowmem, 0x100000 - lowmem); > } > + > +void setup_early_serial_console() { If you put this function in kernel/early_printk.c, then setup_early_printk() can remain file scope. > +#ifdef CONFIG_EARLY_PRINTK > + char *arg; > + > + arg = strstr(boot_command_line, "earlyprintk=serial"); > + if (!arg) > + arg = strstr(boot_command_line, "earlyprintk=ttyS"); > + if (!arg) > + return; > + > + setup_early_printk(boot_command_line); Like Ingo already pointed out, you need to emit a printk() after the call to setup_early_printk() which validates that earlier-than-early is working. Because this isn't. setup_early_printk() expects the argument to point to the start of the earlyprintk= parameter; ie., earlyprintk=ttyS0,115200 ^ buf > +#endif > +} > diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c > index 7ad0ad0..64c7a80 100644 > --- a/arch/x86/kernel/head32.c > +++ b/arch/x86/kernel/head32.c > @@ -32,6 +32,8 @@ static void __init i386_default_early_setup(void) > asmlinkage __visible void __init i386_start_kernel(void) > { > setup_cmdline(); > + /* setup serial console as early as possible */ > + setup_early_serial_console(); > cr4_init_shadow(); > sanitize_boot_params(&boot_params); > > diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c > index 6eea2de..f0c03bd 100644 > --- a/arch/x86/kernel/head64.c > +++ b/arch/x86/kernel/head64.c > @@ -172,12 +172,15 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data) > > copy_bootdata(__va(real_mode_data)); > setup_cmdline(); > + /* setup serial console as early as possible */ > + setup_early_serial_console(); > > /* > * Load microcode early on BSP. > */ > load_ucode_bsp(); > > + > if (console_loglevel >= CONSOLE_LOGLEVEL_DEBUG) > early_printk("Kernel alive\n"); > > @@ -193,8 +196,10 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data) > void __init x86_64_start_reservations(char *real_mode_data) > { > /* version is always not zero if it is copied */ > - if (!boot_params.hdr.version) > + if (!boot_params.hdr.version) { > copy_bootdata(__va(real_mode_data)); > + setup_early_serial_console(); > + } > > reserve_ebda_region(); > > diff --git a/include/linux/printk.h b/include/linux/printk.h > index baa3f97..17358dd 100644 > --- a/include/linux/printk.h > +++ b/include/linux/printk.h > @@ -115,9 +115,13 @@ int no_printk(const char *fmt, ...) > #ifdef CONFIG_EARLY_PRINTK > extern asmlinkage __printf(1, 2) > void early_printk(const char *fmt, ...); > +int setup_early_printk(char *buf); > +void setup_early_serial_console(void); > #else > static inline __printf(1, 2) __cold > void early_printk(const char *s, ...) { } > +int setup_early_printk(char *buf) { } > +static void setup_early_serial_console(void) { } > #endif These can't go here, because this will break the build of every non-x86 arch, since these symbols will not be defined in those arches. These need to be in x86 includes only. > > typedef int(*printk_func_t)(const char *fmt, va_list args); > diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c > index bb0635b..e56285c 100644 > --- a/kernel/printk/printk.c > +++ b/kernel/printk/printk.c > @@ -2409,11 +2409,14 @@ void register_console(struct console *newcon) > struct console_cmdline *c; > > if (console_drivers) > - for_each_console(bcon) > - if (WARN(bcon == newcon, > - "console '%s%d' already registered\n", > - bcon->name, bcon->index)) > + for_each_console(bcon) { > + /* not again */ > + if (bcon == newcon) { > + printk(KERN_INFO "console '%s%d' already registered\n", > + bcon->name, bcon->index); > return; > + } > + } The WARN is still required here because the register_console() caller is not always obvious. A better way to achieve what you want is to not re-register the console to begin with. Looking at early_console_register() and setup_early_printk(), it seems like re-registration would already be prevented (since early_console != 0 after the first call to early_console_register())? Have you tried this? Regards, Peter Hurley > > /* > * before we register a new CON_BOOT console, make sure we don't > ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] x86/earlyprintk: setup earlyprintk as early as possible 2015-04-08 11:32 ` Peter Hurley @ 2015-04-09 7:39 ` Alexander Kuleshov 0 siblings, 0 replies; 5+ messages in thread From: Alexander Kuleshov @ 2015-04-09 7:39 UTC (permalink / raw) To: Peter Hurley Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, Greg Kroah-Hartman, Yinghai Lu, LKML Hello Peter, 2015-04-08 17:32 GMT+06:00 Peter Hurley <peter@hurleysoftware.com>: >> + >> +void setup_early_serial_console() { > > If you put this function in kernel/early_printk.c, then > setup_early_printk() can remain file scope. > Yes, right. will fix it. > > The WARN is still required here because the register_console() caller > is not always obvious. > > A better way to achieve what you want is to not re-register the console > to begin with. Looking at early_console_register() and setup_early_printk(), > it seems like re-registration would already be prevented (since early_console > != 0 after the first call to early_console_register())? Have you tried this? > hmm, now, thanks for the point will test it. Thank you. ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2015-04-09 7:39 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-04-08 9:31 [PATCH 0/2] x86/earlyprintk: setup earlyprintk as early as possible Alexander Kuleshov 2015-04-08 9:31 ` [PATCH 1/2] x86/setup: update boot_command_line with builtin_cmdline in separate function Alexander Kuleshov 2015-04-08 9:31 ` [PATCH 2/2] x86/earlyprintk: setup earlyprintk as early as possible Alexander Kuleshov 2015-04-08 11:32 ` Peter Hurley 2015-04-09 7:39 ` Alexander Kuleshov
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox