Skip to contentSkip to conversation

early printk for x86

RFC New Dave Hansen 1 participant 1 message Jun 9, 2003

lore
Share & tools
lore
#0 lore raw

RFC 1/1 early printk for x86

Most architectures have some way of doing printk()'s before console_init(). x86 doesn't. x86_64 has a self-contained serial and vga driver that do the trick. This could easily be a multiple architecture thing, but I didn't want to clutter up generic code with things that no one else is ever going to use.

The ugly part here is the de-static'ing of the console init functions, and trying to keep the serial init function from running twice. The other part that I don't like is getting the console= part at config time. But, getting arguments parsed this early requires some invasive surgery in early boot.

Although it _is_ ugly, it's also pretty small. Martin Bligh has promised to add vga support too.

Signature · 2 lines
Dave Hansen
[email protected]
arch/i386/Kconfig +31 -0
diff -pru linux-2.5.70-clean/arch/i386/Kconfig linux-2.5.70-early_printk/arch/i386/Kconfig
@@ -1535,6 +1535,37 @@ config FRAME_POINTER
 	  and slower, but it will give very useful debugging information.
 	  If you don't debug the kernel, you can say N, but we may not be able
 	  to solve problems without frame pointers.
+choice
+	prompt "Early printk support"
+	default DEBUG_EARLY_PRINTK_OFF
+	depends on DEBUG_KERNEL
+
+config DEBUG_EARLY_PRINTK_OFF
+	bool "off"
+
+config DEBUG_EP_SERIAL
+	bool "serial"
+	depends on SERIAL_8250_CONSOLE && SERIAL_CORE_CONSOLE
+
+config DEBUG_EP_VGA
+	bool "vga"
+
+endchoice
+
+config DEBUG_EARLY_PRINTK
+	bool
+	depends on !DEBUG_EARLY_PRINTK_OFF
+	default y
+
+config DEBUG_SERIAL_OPTIONS
+	string "serial port options"
+	default "ttyS0,57600"
+	depends on DEBUG_EP_SERIAL
+	help
+	  This should be the same thing that you would put on the kernel
+	  command line for the serial console, minus the 'console=' part.
+	  This will override whatever you put on the command line, so 
+	  be sure to get it right.
 
 config X86_EXTRA_IRQS
 	bool
arch/i386/kernel/setup.c +23 -0
diff -pru linux-2.5.70-clean/arch/i386/kernel/setup.c linux-2.5.70-early_printk/arch/i386/kernel/setup.c
@@ -903,6 +903,29 @@ static int __init noreplacement_setup(ch
 
 __setup("noreplacement", noreplacement_setup); 
 
+#ifdef CONFIG_DEBUG_EARLY_PRINTK
+extern int __init console_setup(char *);
+extern int __init serial8250_console_init(void);
+void setup_early_printk(void)
+{
+	/* 
+	 * printk currently checks cpu_online_map to make sure that
+	 * we don't try to printk from a CPU which hasn't had resources
+	 * allocated for it yet.  Make sure that whatever consoles you
+	 * enable here don't require per-cpu resources.
+	 */
+	set_bit(smp_processor_id(), &cpu_online_map);
+#ifdef CONFIG_DEBUG_EP_SERIAL
+	console_setup(CONFIG_DEBUG_SERIAL_OPTIONS);
+	serial8250_console_init();
+	printk("early serial console support registered\n");
+#endif
+#ifdef DEBUG_EARLY_PRINTK_VGA
+	// blah blah
+#endif
+}
+#endif
+
 void __init setup_arch(char **cmdline_p)
 {
 	unsigned long max_low_pfn;
drivers/serial/8250.c +6 -1
diff -pru linux-2.5.70-clean/drivers/serial/8250.c linux-2.5.70-early_printk/drivers/serial/8250.c
@@ -1983,10 +1983,15 @@ static struct console serial8250_console
 	.data		= &serial8250_reg,
 };
 
-static int __init serial8250_console_init(void)
+int __init serial8250_console_init(void)
 {
+	static int initialized = 0;
+	if (initialized)
+		return 0;
+
 	serial8250_isa_init_ports();
 	register_console(&serial8250_console);
+	initialized = 1;
 	return 0;
 }
 console_initcall(serial8250_console_init);
include/linux/kernel.h +6 -0
diff -pru linux-2.5.70-clean/include/linux/kernel.h linux-2.5.70-early_printk/include/linux/kernel.h
@@ -47,6 +47,12 @@ extern int console_printk[];
 #define minimum_console_loglevel (console_printk[2])
 #define default_console_loglevel (console_printk[3])
 
+#ifdef CONFIG_DEBUG_EARLY_PRINTK
+extern void setup_early_printk(void);
+#else
+#define setup_early_printk() do {} while (0)
+#endif
+
 struct completion;
 
 #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
init/main.c +1 -0
diff -pru linux-2.5.70-clean/init/main.c linux-2.5.70-early_printk/init/main.c
@@ -386,6 +386,7 @@ asmlinkage void __init start_kernel(void
  * enable them
  */
 	lock_kernel();
+	setup_early_printk();
 	printk(linux_banner);
 	setup_arch(&command_line);
 	setup_per_cpu_areas();
kernel/printk.c +1 -1
diff -pru linux-2.5.70-clean/kernel/printk.c linux-2.5.70-early_printk/kernel/printk.c
@@ -89,7 +89,7 @@ static int console_may_schedule;
 /*
  *	Setup a list of consoles. Called from init/main.c
  */
-static int __init console_setup(char *str)
+int __init console_setup(char *str)
 {
 	struct console_cmdline *c;
 	char name[sizeof(c->name)];