From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933650AbbGGU0v (ORCPT ); Tue, 7 Jul 2015 16:26:51 -0400 Received: from aserp1040.oracle.com ([141.146.126.69]:51171 "EHLO aserp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932428AbbGGUU5 (ORCPT ); Tue, 7 Jul 2015 16:20:57 -0400 From: Yinghai Lu To: Kees Cook , "H. Peter Anvin" , Baoquan He Cc: linux-kernel@vger.kernel.org, Yinghai Lu Subject: [PATCH 24/42] x86: Setup early console as early as possible in x86_start_kernel() Date: Tue, 7 Jul 2015 13:20:10 -0700 Message-Id: <1436300428-21163-25-git-send-email-yinghai@kernel.org> X-Mailer: git-send-email 1.8.4.5 In-Reply-To: <1436300428-21163-1-git-send-email-yinghai@kernel.org> References: <1436300428-21163-1-git-send-email-yinghai@kernel.org> X-Source-IP: aserv0022.oracle.com [141.146.126.234] Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Analyze "console=uart8250,io,0x3f8,115200n8" in i386_start_kernel/x86_64_start_kernel, and call setup_early_serial8250_console() to init early serial console. Only can handle io port kind of 8250, because mmio need ioremap. Use boot_params.hdr.version instead of adding another variable, Suggested by hpa. Also need to apply this one after x86 memblock patchset. Signed-off-by: Yinghai Lu --- arch/x86/include/asm/setup.h | 2 ++ arch/x86/kernel/head.c | 26 ++++++++++++++++++++++++++ arch/x86/kernel/head32.c | 1 + arch/x86/kernel/head64.c | 5 ++++- drivers/tty/serial/8250/8250_early.c | 17 +++++++++++++++++ kernel/printk/printk.c | 11 +++++++---- 6 files changed, 57 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h index 11af24e..3e5aa41 100644 --- a/arch/x86/include/asm/setup.h +++ b/arch/x86/include/asm/setup.h @@ -40,6 +40,8 @@ static inline void vsmp_init(void) { } void setup_bios_corruption_check(void); extern unsigned long saved_video_mode; +int setup_early_serial8250_console(char *cmdline); +void setup_early_console(void); extern void reserve_standard_io_resources(void); extern void i386_reserve_resources(void); diff --git a/arch/x86/kernel/head.c b/arch/x86/kernel/head.c index 992f442..cc0cd83 100644 --- a/arch/x86/kernel/head.c +++ b/arch/x86/kernel/head.c @@ -69,3 +69,29 @@ void __init reserve_ebda_region(void) /* reserve all memory between lowmem and the 1MB mark */ memblock_reserve(lowmem, 0x100000 - lowmem); } + +void __init setup_early_console(void) +{ +#ifdef CONFIG_SERIAL_8250_CONSOLE + char constr[64], *p, *q; + + /* Can not handle mmio type 8250 uart yet, too early */ + p = strstr(boot_command_line, "console=uart8250,io,"); + if (!p) + p = strstr(boot_command_line, "console=uart,io,"); + if (!p) + return; + + p += 8; /* sizeof "console=" */ + q = strchrnul(p, ' '); + if ((q - p) >= sizeof(constr)) + return; + + memset(constr, 0, sizeof(constr)); + memcpy(constr, p, q - p); + + lockdep_init(); + + setup_early_serial8250_console(constr); +#endif +} diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c index 2911ef3..87ddca1 100644 --- a/arch/x86/kernel/head32.c +++ b/arch/x86/kernel/head32.c @@ -33,6 +33,7 @@ asmlinkage __visible void __init i386_start_kernel(void) { cr4_init_shadow(); sanitize_boot_params(&boot_params); + setup_early_console(); /* Call the subarch specific early setup function */ switch (boot_params.hdr.hardware_subarch) { diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 5a46681..44dc63b 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_early_console(); /* * Load microcode early on BSP. @@ -189,8 +190,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_console(); + } reserve_ebda_region(); diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c index 771dda2..8a7fe75 100644 --- a/drivers/tty/serial/8250/8250_early.c +++ b/drivers/tty/serial/8250/8250_early.c @@ -152,3 +152,20 @@ int __init early_serial8250_setup(struct earlycon_device *device, } EARLYCON_DECLARE(uart8250, early_serial8250_setup); EARLYCON_DECLARE(uart, early_serial8250_setup); + +/* for x86 early early console */ +int __init setup_early_serial8250_console(char *cmdline) +{ + char *options; + + options = strstr(cmdline, "uart8250,"); + if (options) + return setup_earlycon(options); + + options = strstr(cmdline, "uart,"); + if (options) + return setup_earlycon(options); + + return 0; +} + diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index cf8c242..f554c5f 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -2454,11 +2454,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 -- 1.8.4.5