* Re: [PATCH] early printk for x86 [not found] ` <ar1sdm$gfe$1@cesium.transmeta.com.suse.lists.linux.kernel> @ 2002-11-15 4:31 ` Andi Kleen 2002-11-15 4:33 ` H. Peter Anvin 0 siblings, 1 reply; 14+ messages in thread From: Andi Kleen @ 2002-11-15 4:31 UTC (permalink / raw) To: H. Peter Anvin; +Cc: linux-kernel > > That's overkill. Most architectures have an early_printk equivalent in > > firmware. Only i386 and x86-64 are not lucky enough to have one > > that is usable from the CPU mode linux uses. > > > > That's a pretty big assumption. I wouldn't hold that to be > necessarily true. But then assuming they have PC style VGA/serial is a pretty big assumption too. It is probably better hidden in arch/ -Andi ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] early printk for x86 2002-11-15 4:31 ` [PATCH] early printk for x86 Andi Kleen @ 2002-11-15 4:33 ` H. Peter Anvin 0 siblings, 0 replies; 14+ messages in thread From: H. Peter Anvin @ 2002-11-15 4:33 UTC (permalink / raw) To: Andi Kleen; +Cc: linux-kernel Andi Kleen wrote: > > But then assuming they have PC style VGA/serial is a pretty big > assumption too. > That's a configure option more than anything else, IMO. > It is probably better hidden in arch/ It's not arch though; rather it's a platform option. -hpa ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH] early printk for x86
@ 2002-11-14 19:42 Dave Hansen
2002-11-14 19:55 ` Andi Kleen
` (4 more replies)
0 siblings, 5 replies; 14+ messages in thread
From: Dave Hansen @ 2002-11-14 19:42 UTC (permalink / raw)
To: linux-kernel; +Cc: Andi Kleen
[-- Attachment #1: Type: text/plain, Size: 145 bytes --]
I copied the x86_64 early printk support for plain x86. Is anyone
opposed to me sending this on to Linus?
--
Dave Hansen
haveblue@us.ibm.com
[-- Attachment #2: early_printk-i386-2.5.47.patch --]
[-- Type: text/plain, Size: 8253 bytes --]
diff -urN linux-2.5.47-clean/arch/i386/Kconfig linux-2.5.47/arch/i386/Kconfig
--- linux-2.5.47-clean/arch/i386/Kconfig Sun Nov 10 19:28:05 2002
+++ linux-2.5.47/arch/i386/Kconfig Tue Nov 12 15:19:24 2002
@@ -1574,6 +1574,26 @@
that can still be used by old drivers that are being ported from
2.0/2.2.
+config EARLY_PRINTK
+ bool "Early console support"
+ default n
+ depends on DEBUG_KERNEL
+ help
+ Write kernel log output directly into the VGA buffer or serial port.
+ This is useful for kernel debugging when your machine crashes very
+ early before the console code is initialized. For normal operation
+ it is not recommended because it looks ugly and doesn't cooperate
+ with klogd/syslogd or the X server.You should normally N here,
+ unless you want to debug such a crash.
+
+ Syntax: earlyprintk=vga
+ earlyprintk=serial[,ttySn[,baudrate]]
+ Append ,keep to not disable it when the real console takes over.
+ Only vga or serial at a time, not both.
+ Currently only ttyS0 and ttyS1 are supported.
+ Interaction with the standard serial driver is not very good.
+ The VGA output is eventually overwritten by the real console.
+
config MAGIC_SYSRQ
bool "Magic SysRq key"
depends on DEBUG_KERNEL
diff -urN linux-2.5.47-clean/arch/i386/kernel/Makefile linux-2.5.47/arch/i386/kernel/Makefile
--- linux-2.5.47-clean/arch/i386/kernel/Makefile Sun Nov 10 19:28:05 2002
+++ linux-2.5.47/arch/i386/kernel/Makefile Tue Nov 12 14:57:05 2002
@@ -28,6 +28,7 @@
obj-$(CONFIG_X86_NUMAQ) += numaq.o
obj-$(CONFIG_PROFILING) += profile.o
obj-$(CONFIG_EDD) += edd.o
+obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
EXTRA_AFLAGS := -traditional
diff -urN linux-2.5.47-clean/arch/i386/kernel/early_printk.c linux-2.5.47/arch/i386/kernel/early_printk.c
--- linux-2.5.47-clean/arch/i386/kernel/early_printk.c Wed Dec 31 16:00:00 1969
+++ linux-2.5.47/arch/i386/kernel/early_printk.c Thu Nov 14 11:29:26 2002
@@ -0,0 +1,220 @@
+#include <linux/console.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <asm/io.h>
+
+/* Simple VGA output */
+
+#define VGABASE 0xB8000
+
+#define MAX_YPOS 25
+#define MAX_XPOS 80
+
+static int current_ypos = 1, current_xpos = 0;
+
+static void early_vga_write(struct console *con, const char *str, unsigned n)
+{
+ char c;
+ int i, k, j;
+
+ while ((c = *str++) != '\0' && n-- > 0) {
+ if (current_ypos >= MAX_YPOS) {
+ /* scroll 1 line up */
+ for(k = 1, j = 0; k < MAX_YPOS; k++, j++) {
+ for(i = 0; i < MAX_XPOS; i++) {
+ writew(readw(VGABASE + 2*(MAX_XPOS*k + i)),
+ VGABASE + 2*(MAX_XPOS*j + i));
+ }
+ }
+ for(i = 0; i < MAX_XPOS; i++) {
+ writew(0x720, VGABASE + 2*(MAX_XPOS*j + i));
+ }
+ current_ypos = MAX_YPOS-1;
+ }
+ if (c == '\n') {
+ current_xpos = 0;
+ current_ypos++;
+ } else if (c != '\r') {
+ writew(((0x7 << 8) | (unsigned short) c),
+ VGABASE + 2*(MAX_XPOS*current_ypos + current_xpos++));
+ if (current_xpos >= MAX_XPOS) {
+ current_xpos = 0;
+ current_ypos++;
+ }
+ }
+ }
+}
+
+static struct console early_vga_console = {
+ .name = "earlyvga",
+ .write = early_vga_write,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+};
+
+/* Serial functions losely based on a similar package from Klaus P. Gerlicher */
+
+int early_serial_base = 0x3f8; /* ttyS0 */
+#define DEFAULT_BAUD 57600
+#define XMTRDY 0x20
+
+#define DLAB 0x80
+
+#define TXR 0 /* Transmit register (WRITE) */
+#define RXR 0 /* Receive register (READ) */
+#define IER 1 /* Interrupt Enable */
+#define IIR 2 /* Interrupt ID */
+#define FCR 2 /* FIFO control */
+#define LCR 3 /* Line control */
+#define MCR 4 /* Modem control */
+#define LSR 5 /* Line Status */
+#define MSR 6 /* Modem Status */
+#define DLL 0 /* Divisor Latch Low */
+#define DLH 1 /* Divisor latch High */
+
+
+static int early_serial_putc(unsigned char ch)
+{
+ unsigned timeout = 0xffff;
+ while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout)
+ rep_nop();
+ outb(ch, early_serial_base + TXR);
+ return timeout ? 0 : -1;
+}
+
+static void early_serial_write(struct console *con, const char *s, unsigned n)
+{
+ while (*s && n-- > 0) {
+ early_serial_putc(*s);
+ if (*s == '\n')
+ early_serial_putc('\r');
+ s++;
+ }
+}
+
+static __init void early_serial_init(char *opt)
+{
+ unsigned char c;
+ unsigned divisor, baud = DEFAULT_BAUD;
+ char *s, *e;
+
+ if (*opt == ',')
+ ++opt;
+
+ s = strsep(&opt, ",");
+ if (s != NULL) {
+ unsigned port;
+ if (!strncmp(s,"0x",2))
+ early_serial_base = simple_strtoul(s, &e, 16);
+ else {
+ static int bases[] = { 0x3f8, 0x2f8 };
+ if (!strncmp(s,"ttyS",4))
+ s+=4;
+ port = simple_strtoul(s, &e, 10);
+ if (port > 1 || s == e)
+ port = 0;
+ early_serial_base = bases[port];
+ }
+ }
+
+ outb(0x3, early_serial_base + LCR); /* 8n1 */
+ outb(0, early_serial_base + IER); /* no interrupt */
+ outb(0, early_serial_base + FCR); /* no fifo */
+ outb(0x3, early_serial_base + MCR); /* DTR + RTS */
+
+ s = strsep(&opt, ",");
+ if (s != NULL) {
+ baud = simple_strtoul(s, &e, 0);
+ if (baud == 0 || s == e)
+ baud = DEFAULT_BAUD;
+ }
+
+ divisor = 115200 / baud;
+ c = inb(early_serial_base + LCR);
+ outb(c | DLAB, early_serial_base + LCR);
+ outb(divisor & 0xff, early_serial_base + DLL);
+ outb((divisor >> 8) & 0xff, early_serial_base + DLH);
+ outb(c & ~DLAB, early_serial_base + LCR);
+}
+
+static struct console early_serial_console = {
+ .name = "earlyser",
+ .write = early_serial_write,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+};
+
+/* Direct interface for emergencies */
+struct console *early_console = &early_vga_console;
+static int early_console_initialized = 0;
+
+void early_printk(const char *fmt, ...)
+{
+ char buf[512];
+ int n;
+ va_list ap;
+ va_start(ap,fmt);
+ n = vsnprintf(buf,512,fmt,ap);
+ early_console->write(early_console,buf,n);
+ va_end(ap);
+}
+
+static int keep_early;
+
+int __init setup_early_printk(char *opt)
+{
+ char *space;
+ char buf[256];
+
+ if (early_console_initialized)
+ return -1;
+
+ strncpy(buf,opt,256);
+ buf[255] = 0;
+ space = strchr(buf, ' ');
+ if (space)
+ *space = 0;
+
+ if (strstr(buf,"keep"))
+ keep_early = 1;
+
+ if (!strncmp(buf, "serial", 6)) {
+ early_serial_init(buf + 6);
+ early_console = &early_serial_console;
+ } else if (!strncmp(buf, "ttyS", 4)) {
+ early_serial_init(buf);
+ early_console = &early_serial_console;
+ } else if (!strncmp(buf, "vga", 3)) {
+ early_console = &early_vga_console;
+ } else {
+ early_console = NULL;
+ return -1;
+ }
+ early_console_initialized = 1;
+ register_console(early_console);
+ early_printk( "early printk console registered\n" );
+ return 0;
+}
+
+void __init disable_early_printk(void)
+{
+ if (!early_console_initialized || !early_console)
+ return;
+ if (!keep_early) {
+ printk("disabling early console...\n");
+ unregister_console(early_console);
+ early_console_initialized = 0;
+ } else {
+ printk("keeping early console.\n");
+ }
+}
+
+/* syntax: earlyprintk=vga
+ earlyprintk=serial[,ttySn[,baudrate]]
+ Append ,keep to not disable it when the real console takes over.
+ Only vga or serial at a time, not both.
+ Currently only ttyS0 and ttyS1 are supported.
+ Interaction with the standard serial driver is not very good.
+ The VGA output is eventually overwritten by the real console. */
+__setup("earlyprintk=", setup_early_printk);
diff -urN linux-2.5.47-clean/arch/i386/kernel/setup.c linux-2.5.47/arch/i386/kernel/setup.c
--- linux-2.5.47-clean/arch/i386/kernel/setup.c Sun Nov 10 19:28:13 2002
+++ linux-2.5.47/arch/i386/kernel/setup.c Thu Nov 14 11:15:22 2002
@@ -84,6 +84,7 @@
extern void early_cpu_init(void);
extern void dmi_scan_machine(void);
+extern void setup_early_printk(char *);
extern int root_mountflags;
extern char _text, _etext, _edata, _end;
extern int blk_nohighio;
@@ -836,7 +837,12 @@
void __init setup_arch(char **cmdline_p)
{
unsigned long max_low_pfn;
+ char* s;
+ s = strstr(saved_command_line, "earlyprintk=");
+ if (s != NULL)
+ setup_early_printk(s+12);
+
pre_setup_arch_hook();
early_cpu_init();
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [PATCH] early printk for x86 2002-11-14 19:42 Dave Hansen @ 2002-11-14 19:55 ` Andi Kleen 2002-11-14 20:27 ` Jeff Garzik ` (3 subsequent siblings) 4 siblings, 0 replies; 14+ messages in thread From: Andi Kleen @ 2002-11-14 19:55 UTC (permalink / raw) To: Dave Hansen; +Cc: linux-kernel, Andi Kleen On Thu, Nov 14, 2002 at 11:42:43AM -0800, Dave Hansen wrote: > I copied the x86_64 early printk support for plain x86. Is anyone > opposed to me sending this on to Linus? No problem from my side. although it may make sense to just put in the #ifdef __i386__ for vgabase and then #include it. -Andi ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] early printk for x86 2002-11-14 19:42 Dave Hansen 2002-11-14 19:55 ` Andi Kleen @ 2002-11-14 20:27 ` Jeff Garzik 2002-11-14 22:50 ` Dave Hansen 2002-11-14 21:05 ` Jeff Garzik ` (2 subsequent siblings) 4 siblings, 1 reply; 14+ messages in thread From: Jeff Garzik @ 2002-11-14 20:27 UTC (permalink / raw) To: Dave Hansen; +Cc: linux-kernel, Andi Kleen VGA and serial are certainly not hammer+ia32-specific. Make the generic parts generic... the arch-specific components would need to change early-foo base addresses perhaps, but otherwise, it's pretty generic. Jeff ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] early printk for x86 2002-11-14 20:27 ` Jeff Garzik @ 2002-11-14 22:50 ` Dave Hansen 2002-11-15 3:43 ` Andi Kleen 0 siblings, 1 reply; 14+ messages in thread From: Dave Hansen @ 2002-11-14 22:50 UTC (permalink / raw) To: Jeff Garzik; +Cc: linux-kernel, Andi Kleen [-- Attachment #1: Type: text/plain, Size: 987 bytes --] Jeff Garzik wrote: > VGA and serial are certainly not hammer+ia32-specific. Make the generic > parts generic... the arch-specific components would need to change > early-foo base addresses perhaps, but otherwise, it's pretty generic. Take 2. - Move the x86_64 early_printk.c into kernel/ - move some of the basic defines into linux/early_printk.h and asm-{i386,x86_64}/early_printk.h - run the setup in start_kernel() before setup_arch() arch/i386/Kconfig | 20 +++ arch/x86_64/kernel/early_printk.c | 218 ----------------------------- arch/x86_64/kernel/head64.c | 5 include/asm-i386/early_printk.h | 8 + include/asm-x86_64/early_printk.h | 8 + include/linux/early_printk.h | 47 ++++++++ init/main.c | 1 kernel/Makefile | 1 kernel/early_printk.c | 209 +++++++++++++++++++++++++++++ 9 files changed, 295 insertions(+), 222 deletions(-) -- Dave Hansen haveblue@us.ibm.com [-- Attachment #2: early_printk-i386-2.5.47-2.patch --] [-- Type: text/plain, Size: 16963 bytes --] diff -urN linux-2.5.47-clean/arch/i386/Kconfig linux-2.5.47/arch/i386/Kconfig --- linux-2.5.47-clean/arch/i386/Kconfig Sun Nov 10 19:28:05 2002 +++ linux-2.5.47/arch/i386/Kconfig Thu Nov 14 14:17:45 2002 @@ -1588,6 +1588,26 @@ keys are documented in <file:Documentation/sysrq.txt>. Don't say Y unless you really know what this hack does. +config EARLY_PRINTK + bool "Early console support" + default n + depends on DEBUG_KERNEL + help + Write kernel log output directly into the VGA buffer or serial port. + This is useful for kernel debugging when your machine crashes very + early before the console code is initialized. For normal operation + it is not recommended because it looks ugly and doesn't cooperate + with klogd/syslogd or the X server.You should normally N here, + unless you want to debug such a crash. + + Syntax: earlyprintk=vga + earlyprintk=serial[,ttySn[,baudrate]] + Append ,keep to not disable it when the real console takes over. + Only vga or serial at a time, not both. + Currently only ttyS0 and ttyS1 are supported. + Interaction with the standard serial driver is not very good. + The VGA output is eventually overwritten by the real console. + config DEBUG_SPINLOCK bool "Spinlock debugging" depends on DEBUG_KERNEL diff -urN linux-2.5.47-clean/arch/x86_64/kernel/early_printk.c linux-2.5.47/arch/x86_64/kernel/early_printk.c --- linux-2.5.47-clean/arch/x86_64/kernel/early_printk.c Sun Nov 10 19:28:26 2002 +++ linux-2.5.47/arch/x86_64/kernel/early_printk.c Wed Dec 31 16:00:00 1969 @@ -1,218 +0,0 @@ -#include <linux/console.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/string.h> -#include <asm/io.h> - -/* Simple VGA output */ - -#define VGABASE 0xffffffff800b8000UL - -#define MAX_YPOS 25 -#define MAX_XPOS 80 - -static int current_ypos = 1, current_xpos = 0; - -static void early_vga_write(struct console *con, const char *str, unsigned n) -{ - char c; - int i, k, j; - - while ((c = *str++) != '\0' && n-- > 0) { - if (current_ypos >= MAX_YPOS) { - /* scroll 1 line up */ - for(k = 1, j = 0; k < MAX_YPOS; k++, j++) { - for(i = 0; i < MAX_XPOS; i++) { - writew(readw(VGABASE + 2*(MAX_XPOS*k + i)), - VGABASE + 2*(MAX_XPOS*j + i)); - } - } - for(i = 0; i < MAX_XPOS; i++) { - writew(0x720, VGABASE + 2*(MAX_XPOS*j + i)); - } - current_ypos = MAX_YPOS-1; - } - if (c == '\n') { - current_xpos = 0; - current_ypos++; - } else if (c != '\r') { - writew(((0x7 << 8) | (unsigned short) c), - VGABASE + 2*(MAX_XPOS*current_ypos + current_xpos++)); - if (current_xpos >= MAX_XPOS) { - current_xpos = 0; - current_ypos++; - } - } - } -} - -static struct console early_vga_console = { - .name = "earlyvga", - .write = early_vga_write, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -/* Serial functions losely based on a similar package from Klaus P. Gerlicher */ - -int early_serial_base = 0x3f8; /* ttyS0 */ - -#define XMTRDY 0x20 - -#define DLAB 0x80 - -#define TXR 0 /* Transmit register (WRITE) */ -#define RXR 0 /* Receive register (READ) */ -#define IER 1 /* Interrupt Enable */ -#define IIR 2 /* Interrupt ID */ -#define FCR 2 /* FIFO control */ -#define LCR 3 /* Line control */ -#define MCR 4 /* Modem control */ -#define LSR 5 /* Line Status */ -#define MSR 6 /* Modem Status */ -#define DLL 0 /* Divisor Latch Low */ -#define DLH 1 /* Divisor latch High */ - -static int early_serial_putc(unsigned char ch) -{ - unsigned timeout = 0xffff; - while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout) - rep_nop(); - outb(ch, early_serial_base + TXR); - return timeout ? 0 : -1; -} - -static void early_serial_write(struct console *con, const char *s, unsigned n) -{ - while (*s && n-- > 0) { - early_serial_putc(*s); - if (*s == '\n') - early_serial_putc('\r'); - s++; - } -} - -static __init void early_serial_init(char *opt) -{ - unsigned char c; - unsigned divisor, baud = 38400; - char *s, *e; - - if (*opt == ',') - ++opt; - - s = strsep(&opt, ","); - if (s != NULL) { - unsigned port; - if (!strncmp(s,"0x",2)) - early_serial_base = simple_strtoul(s, &e, 16); - else { - static int bases[] = { 0x3f8, 0x2f8 }; - if (!strncmp(s,"ttyS",4)) - s+=4; - port = simple_strtoul(s, &e, 10); - if (port > 1 || s == e) - port = 0; - early_serial_base = bases[port]; - } - } - - outb(0x3, early_serial_base + LCR); /* 8n1 */ - outb(0, early_serial_base + IER); /* no interrupt */ - outb(0, early_serial_base + FCR); /* no fifo */ - outb(0x3, early_serial_base + MCR); /* DTR + RTS */ - - s = strsep(&opt, ","); - if (s != NULL) { - baud = simple_strtoul(s, &e, 0); - if (baud == 0 || s == e) - baud = 38400; - } - - divisor = 115200 / baud; - c = inb(early_serial_base + LCR); - outb(c | DLAB, early_serial_base + LCR); - outb(divisor & 0xff, early_serial_base + DLL); - outb((divisor >> 8) & 0xff, early_serial_base + DLH); - outb(c & ~DLAB, early_serial_base + LCR); -} - -static struct console early_serial_console = { - .name = "earlyser", - .write = early_serial_write, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -/* Direct interface for emergencies */ -struct console *early_console = &early_vga_console; -static int early_console_initialized = 0; - -void early_printk(const char *fmt, ...) -{ - char buf[512]; - int n; - va_list ap; - va_start(ap,fmt); - n = vsnprintf(buf,512,fmt,ap); - early_console->write(early_console,buf,n); - va_end(ap); -} - -static int keep_early; - -int __init setup_early_printk(char *opt) -{ - char *space; - char buf[256]; - - if (early_console_initialized) - return -1; - - strncpy(buf,opt,256); - buf[255] = 0; - space = strchr(buf, ' '); - if (space) - *space = 0; - - if (strstr(buf,"keep")) - keep_early = 1; - - if (!strncmp(buf, "serial", 6)) { - early_serial_init(buf + 6); - early_console = &early_serial_console; - } else if (!strncmp(buf, "ttyS", 4)) { - early_serial_init(buf); - early_console = &early_serial_console; - } else if (!strncmp(buf, "vga", 3)) { - early_console = &early_vga_console; - } else { - early_console = NULL; - return -1; - } - early_console_initialized = 1; - register_console(early_console); - return 0; -} - -void __init disable_early_printk(void) -{ - if (!early_console_initialized || !early_console) - return; - if (!keep_early) { - printk("disabling early console...\n"); - unregister_console(early_console); - early_console_initialized = 0; - } else { - printk("keeping early console.\n"); - } -} - -/* syntax: earlyprintk=vga - earlyprintk=serial[,ttySn[,baudrate]] - Append ,keep to not disable it when the real console takes over. - Only vga or serial at a time, not both. - Currently only ttyS0 and ttyS1 are supported. - Interaction with the standard serial driver is not very good. - The VGA output is eventually overwritten by the real console. */ -__setup("earlyprintk=", setup_early_printk); diff -urN linux-2.5.47-clean/arch/x86_64/kernel/head64.c linux-2.5.47/arch/x86_64/kernel/head64.c --- linux-2.5.47-clean/arch/x86_64/kernel/head64.c Sun Nov 10 19:28:10 2002 +++ linux-2.5.47/arch/x86_64/kernel/head64.c Thu Nov 14 14:34:47 2002 @@ -70,7 +70,7 @@ boot_cpu_data.x86_mask = eax & 0xf; } -extern void start_kernel(void), pda_init(int), setup_early_printk(char *); +extern void start_kernel(void), pda_init(int); extern int disable_apic; void __init x86_64_start_kernel(char * real_mode_data) @@ -80,9 +80,6 @@ clear_bss(); pda_init(0); copy_bootdata(real_mode_data); - s = strstr(saved_command_line, "earlyprintk="); - if (s != NULL) - setup_early_printk(s+12); #ifdef CONFIG_X86_IO_APIC if (strstr(saved_command_line, "disableapic")) disable_apic = 1; diff -urN linux-2.5.47-clean/include/asm-i386/early_printk.h linux-2.5.47/include/asm-i386/early_printk.h --- linux-2.5.47-clean/include/asm-i386/early_printk.h Wed Dec 31 16:00:00 1969 +++ linux-2.5.47/include/asm-i386/early_printk.h Thu Nov 14 14:20:43 2002 @@ -0,0 +1,8 @@ +#ifndef __EARLY_PRINTK_H_I386_ +#define __EARLY_PRINTK_H_i386_ + +#define VGABASE 0xB8000 +#define SERIAL_BASES { 0x3f8, 0x2f8 } +#define SERIAL_BASES_LEN 2 + +#endif diff -urN linux-2.5.47-clean/include/asm-x86_64/early_printk.h linux-2.5.47/include/asm-x86_64/early_printk.h --- linux-2.5.47-clean/include/asm-x86_64/early_printk.h Wed Dec 31 16:00:00 1969 +++ linux-2.5.47/include/asm-x86_64/early_printk.h Thu Nov 14 14:15:04 2002 @@ -0,0 +1,8 @@ +#ifdef __EARLY_PRINTK_H_X86_64_ +#define __EARLY_PRINTK_H_X86_64_ + +#define VGABASE 0xffffffff800b8000UL +#define SERIAL_BASES { 0x3f8, 0x2f8 } +#define SERIAL_BASES_LEN 2 + +#endif Binary files linux-2.5.47-clean/include/linux/.early_printk.h.swp and linux-2.5.47/include/linux/.early_printk.h.swp differ diff -urN linux-2.5.47-clean/include/linux/early_printk.h linux-2.5.47/include/linux/early_printk.h --- linux-2.5.47-clean/include/linux/early_printk.h Wed Dec 31 16:00:00 1969 +++ linux-2.5.47/include/linux/early_printk.h Thu Nov 14 14:48:29 2002 @@ -0,0 +1,47 @@ +#ifndef __EARLY_PRINTK_H_ +#define __EARLY_PRINTK_H_ + +#ifdef CONFIG_EARLY_PRINTK +#include <linux/console.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/string.h> +#include <asm/io.h> +#include <asm/early_printk.h> + +/* Simple VGA output */ + +#define MAX_YPOS 25 +#define MAX_XPOS 80 + +/* Simple serial port output */ + +#define DEFAULT_BAUD 57600 +#define XMTRDY 0x20 + +#define DLAB 0x80 + +#define TXR 0 /* Transmit register (WRITE) */ +#define RXR 0 /* Receive register (READ) */ +#define IER 1 /* Interrupt Enable */ +#define IIR 2 /* Interrupt ID */ +#define FCR 2 /* FIFO control */ +#define LCR 3 /* Line control */ +#define MCR 4 /* Modem control */ +#define LSR 5 /* Line Status */ +#define MSR 6 /* Modem Status */ +#define DLL 0 /* Divisor Latch Low */ +#define DLH 1 /* Divisor latch High */ + + +void early_printk(const char *fmt, ...); +int __init setup_early_printk(char *opt); + +#else + +#define early_printk(...) do {} while(0) +#define setup_early_printk(X) do {} while(0) + +#endif + +#endif diff -urN linux-2.5.47-clean/init/main.c linux-2.5.47/init/main.c --- linux-2.5.47-clean/init/main.c Sun Nov 10 19:28:05 2002 +++ linux-2.5.47/init/main.c Thu Nov 14 14:47:14 2002 @@ -33,6 +33,7 @@ #include <linux/workqueue.h> #include <linux/profile.h> #include <linux/rcupdate.h> +#include <linux/early_printk.h> #include <asm/io.h> #include <asm/bugs.h> @@ -387,6 +388,7 @@ */ lock_kernel(); printk(linux_banner); + setup_early_printk(&command_line); setup_arch(&command_line); setup_per_cpu_areas(); build_all_zonelists(); diff -urN linux-2.5.47-clean/kernel/Makefile linux-2.5.47/kernel/Makefile --- linux-2.5.47-clean/kernel/Makefile Sun Nov 10 19:28:06 2002 +++ linux-2.5.47/kernel/Makefile Thu Nov 14 14:16:00 2002 @@ -21,6 +21,7 @@ obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend.o +obj-$(CONFIG_EARLY_PRINTK) += early_printk.o ifneq ($(CONFIG_IA64),y) # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is diff -urN linux-2.5.47-clean/kernel/early_printk.c linux-2.5.47/kernel/early_printk.c --- linux-2.5.47-clean/kernel/early_printk.c Wed Dec 31 16:00:00 1969 +++ linux-2.5.47/kernel/early_printk.c Thu Nov 14 14:35:50 2002 @@ -0,0 +1,209 @@ +#include <linux/console.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/string.h> +#include <linux/early_printk.h> +#include <asm/io.h> + +/* Simple VGA output */ + +#define MAX_YPOS 25 +#define MAX_XPOS 80 + +static int current_ypos = 1, current_xpos = 0; + +static void early_vga_write(struct console *con, const char *str, unsigned n) +{ + char c; + int i, k, j; + + while ((c = *str++) != '\0' && n-- > 0) { + if (current_ypos >= MAX_YPOS) { + /* scroll 1 line up */ + for(k = 1, j = 0; k < MAX_YPOS; k++, j++) { + for(i = 0; i < MAX_XPOS; i++) { + writew(readw(VGABASE + 2*(MAX_XPOS*k + i)), + VGABASE + 2*(MAX_XPOS*j + i)); + } + } + for(i = 0; i < MAX_XPOS; i++) { + writew(0x720, VGABASE + 2*(MAX_XPOS*j + i)); + } + current_ypos = MAX_YPOS-1; + } + if (c == '\n') { + current_xpos = 0; + current_ypos++; + } else if (c != '\r') { + writew(((0x7 << 8) | (unsigned short) c), + VGABASE + 2*(MAX_XPOS*current_ypos + current_xpos++)); + if (current_xpos >= MAX_XPOS) { + current_xpos = 0; + current_ypos++; + } + } + } +} + +static struct console early_vga_console = { + .name = "earlyvga", + .write = early_vga_write, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + +/* Serial functions losely based on a similar package from Klaus P. Gerlicher */ + +int early_serial_base; /* ttyS0 */ + +static int early_serial_putc(unsigned char ch) +{ + unsigned timeout = 0xffff; + while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout) + rep_nop(); + outb(ch, early_serial_base + TXR); + return timeout ? 0 : -1; +} + +static void early_serial_write(struct console *con, const char *s, unsigned n) +{ + while (*s && n-- > 0) { + early_serial_putc(*s); + if (*s == '\n') + early_serial_putc('\r'); + s++; + } +} + +static __init void early_serial_init(char *opt) +{ + unsigned char c; + unsigned divisor, baud = DEFAULT_BAUD; + static int bases[] = SERIAL_BASES; + char *s, *e; + + early_serial_base = bases[0]; + + if (*opt == ',') + ++opt; + + s = strsep(&opt, ","); + if (s != NULL) { + unsigned port; + if (!strncmp(s,"0x",2)) + early_serial_base = simple_strtoul(s, &e, 16); + else { + if (!strncmp(s,"ttyS",4)) + s+=4; + port = simple_strtoul(s, &e, 10); + if (port > (SERIAL_BASES_LEN-1) || s == e) + port = 0; + early_serial_base = bases[port]; + } + } + + outb(0x3, early_serial_base + LCR); /* 8n1 */ + outb(0, early_serial_base + IER); /* no interrupt */ + outb(0, early_serial_base + FCR); /* no fifo */ + outb(0x3, early_serial_base + MCR); /* DTR + RTS */ + + s = strsep(&opt, ","); + if (s != NULL) { + baud = simple_strtoul(s, &e, 0); + if (baud == 0 || s == e) + baud = DEFAULT_BAUD; + } + + divisor = 115200 / baud; + c = inb(early_serial_base + LCR); + outb(c | DLAB, early_serial_base + LCR); + outb(divisor & 0xff, early_serial_base + DLL); + outb((divisor >> 8) & 0xff, early_serial_base + DLH); + outb(c & ~DLAB, early_serial_base + LCR); +} + +static struct console early_serial_console = { + .name = "earlyser", + .write = early_serial_write, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + +/* Direct interface for emergencies */ +struct console *early_console = &early_vga_console; +static int early_console_initialized = 0; + +void early_printk(const char *fmt, ...) +{ + char buf[512]; + int n; + va_list ap; + va_start(ap,fmt); + n = vsnprintf(buf,512,fmt,ap); + early_console->write(early_console,buf,n); + va_end(ap); +} + +static int keep_early; + +int __init setup_early_printk(char *opt) +{ + char *space, *s; + char buf[256]; + + s = strstr(opt, "earlyprintk="); + if (s == NULL) + return -1; + opt = s+12; + + if (early_console_initialized) + return -1; + + strncpy(buf,opt,256); + buf[255] = 0; + space = strchr(buf, ' '); + if (space) + *space = 0; + + if (strstr(buf,"keep")) + keep_early = 1; + + if (!strncmp(buf, "serial", 6)) { + early_serial_init(buf + 6); + early_console = &early_serial_console; + } else if (!strncmp(buf, "ttyS", 4)) { + early_serial_init(buf); + early_console = &early_serial_console; + } else if (!strncmp(buf, "vga", 3)) { + early_console = &early_vga_console; + } else { + early_console = NULL; + return -1; + } + early_console_initialized = 1; + register_console(early_console); + early_printk( "early printk console registered\n" ); + return 0; +} + +void __init disable_early_printk(void) +{ + if (!early_console_initialized || !early_console) + return; + if (!keep_early) { + printk("disabling early console...\n"); + unregister_console(early_console); + early_console_initialized = 0; + } else { + printk("keeping early console.\n"); + } +} + +/* syntax: earlyprintk=vga + earlyprintk=serial[,ttySn[,baudrate]] + Append ,keep to not disable it when the real console takes over. + Only vga or serial at a time, not both. + Currently only ttyS0 and ttyS1 are supported. + Interaction with the standard serial driver is not very good. + The VGA output is eventually overwritten by the real console. */ +__setup("earlyprintk=", setup_early_printk); ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] early printk for x86 2002-11-14 22:50 ` Dave Hansen @ 2002-11-15 3:43 ` Andi Kleen 2002-11-15 3:52 ` William Lee Irwin III 2002-11-15 4:15 ` H. Peter Anvin 0 siblings, 2 replies; 14+ messages in thread From: Andi Kleen @ 2002-11-15 3:43 UTC (permalink / raw) To: Dave Hansen; +Cc: Jeff Garzik, linux-kernel, Andi Kleen On Thu, Nov 14, 2002 at 02:50:43PM -0800, Dave Hansen wrote: > Jeff Garzik wrote: > >VGA and serial are certainly not hammer+ia32-specific. Make the generic > >parts generic... the arch-specific components would need to change > >early-foo base addresses perhaps, but otherwise, it's pretty generic. > > Take 2. > > - Move the x86_64 early_printk.c into kernel/ > - move some of the basic defines into linux/early_printk.h and > asm-{i386,x86_64}/early_printk.h > - run the setup in start_kernel() before setup_arch() That's overkill. Most architectures have an early_printk equivalent in firmware. Only i386 and x86-64 are not lucky enough to have one that is usable from the CPU mode linux uses. -Andi ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] early printk for x86 2002-11-15 3:43 ` Andi Kleen @ 2002-11-15 3:52 ` William Lee Irwin III 2002-11-15 4:15 ` H. Peter Anvin 1 sibling, 0 replies; 14+ messages in thread From: William Lee Irwin III @ 2002-11-15 3:52 UTC (permalink / raw) To: Andi Kleen; +Cc: Dave Hansen, Jeff Garzik, linux-kernel Jeff Garzik wrote: >>> VGA and serial are certainly not hammer+ia32-specific. Make the generic >>> parts generic... the arch-specific components would need to change >>> early-foo base addresses perhaps, but otherwise, it's pretty generic. On Thu, Nov 14, 2002 at 02:50:43PM -0800, Dave Hansen wrote: >> Take 2. >> - Move the x86_64 early_printk.c into kernel/ >> - move some of the basic defines into linux/early_printk.h and >> asm-{i386,x86_64}/early_printk.h >> - run the setup in start_kernel() before setup_arch() On Fri, Nov 15, 2002 at 04:43:00AM +0100, Andi Kleen wrote: > That's overkill. Most architectures have an early_printk equivalent in > firmware. Only i386 and x86-64 are not lucky enough to have one > that is usable from the CPU mode linux uses. Perhaps s/early_printk/prom_printf/ would pick up a few arches for free. Bill ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] early printk for x86 2002-11-15 3:43 ` Andi Kleen 2002-11-15 3:52 ` William Lee Irwin III @ 2002-11-15 4:15 ` H. Peter Anvin 1 sibling, 0 replies; 14+ messages in thread From: H. Peter Anvin @ 2002-11-15 4:15 UTC (permalink / raw) To: linux-kernel Followup to: <20021115044300.C20764@wotan.suse.de> By author: Andi Kleen <ak@suse.de> In newsgroup: linux.dev.kernel > > That's overkill. Most architectures have an early_printk equivalent in > firmware. Only i386 and x86-64 are not lucky enough to have one > that is usable from the CPU mode linux uses. > That's a pretty big assumption. I wouldn't hold that to be necessarily true. -hpa -- <hpa@transmeta.com> at work, <hpa@zytor.com> in private! "Unix gives you enough rope to shoot yourself in the foot." http://www.zytor.com/~hpa/puzzle.txt <amsp@zytor.com> ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] early printk for x86 2002-11-14 19:42 Dave Hansen 2002-11-14 19:55 ` Andi Kleen 2002-11-14 20:27 ` Jeff Garzik @ 2002-11-14 21:05 ` Jeff Garzik 2002-11-14 23:17 ` Jeff Garzik 2002-11-18 15:15 ` David Woodhouse 4 siblings, 0 replies; 14+ messages in thread From: Jeff Garzik @ 2002-11-14 21:05 UTC (permalink / raw) To: Dave Hansen; +Cc: linux-kernel, Andi Kleen VGA and serial are certainly not hammer+ia32-specific. Make the generic parts generic... the arch-specific components would need to change early-foo base addresses perhaps, but otherwise, it's pretty generic. Jeff - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] early printk for x86 2002-11-14 19:42 Dave Hansen ` (2 preceding siblings ...) 2002-11-14 21:05 ` Jeff Garzik @ 2002-11-14 23:17 ` Jeff Garzik 2002-11-18 15:15 ` David Woodhouse 4 siblings, 0 replies; 14+ messages in thread From: Jeff Garzik @ 2002-11-14 23:17 UTC (permalink / raw) To: Dave Hansen; +Cc: linux-kernel, Andi Kleen Looks pretty decent to me... minor comments: * might be a good idea to match defaults with the defaults of the normal serial console. IIRC that's 38400,N,8,1. which brings up a tangent, 57600 or 115200 is probably preferred these days, but that requires a later patch to update serial console and early serial console to be faster * VGA base might want to be a variable, though I have not convinced myself that such is useful ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] early printk for x86 2002-11-14 19:42 Dave Hansen ` (3 preceding siblings ...) 2002-11-14 23:17 ` Jeff Garzik @ 2002-11-18 15:15 ` David Woodhouse 2002-11-18 15:17 ` Andi Kleen 4 siblings, 1 reply; 14+ messages in thread From: David Woodhouse @ 2002-11-18 15:15 UTC (permalink / raw) To: Dave Hansen; +Cc: linux-kernel, Andi Kleen haveblue@us.ibm.com said: > 1. I copied the x86_64 early printk support for plain x86. Is > anyone opposed to me sending this on to Linus? Why is it necessary to reimplement serial console for each arch rather than just registering the generic serial console as early as possible from arch-specific code? There's no _reason_ to wait for console_init(), for most consoles. -- dwmw2 ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] early printk for x86 2002-11-18 15:15 ` David Woodhouse @ 2002-11-18 15:17 ` Andi Kleen 2002-11-18 15:39 ` David Woodhouse 0 siblings, 1 reply; 14+ messages in thread From: Andi Kleen @ 2002-11-18 15:17 UTC (permalink / raw) To: David Woodhouse; +Cc: Dave Hansen, linux-kernel, Andi Kleen On Mon, Nov 18, 2002 at 03:15:23PM +0000, David Woodhouse wrote: > > haveblue@us.ibm.com said: > > 1. I copied the x86_64 early printk support for plain x86. Is > > anyone opposed to me sending this on to Linus? > > Why is it necessary to reimplement serial console for each arch rather than > just registering the generic serial console as early as possible from > arch-specific code? > > There's no _reason_ to wait for console_init(), for most consoles. The generic serial driver needs lots of infrastructure that is not present in early boot. Also the early_printk serial driver is polled, not interrupt driven. The whole point of early_printk is that you can debug from line one of your code, so it is essential that it is self contained as far as possible. -Andi ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] early printk for x86 2002-11-18 15:17 ` Andi Kleen @ 2002-11-18 15:39 ` David Woodhouse 0 siblings, 0 replies; 14+ messages in thread From: David Woodhouse @ 2002-11-18 15:39 UTC (permalink / raw) To: Andi Kleen; +Cc: Dave Hansen, linux-kernel ak@suse.de said: > The generic serial driver needs lots of infrastructure that is not > present in early boot. Also the early_printk serial driver is polled, > not interrupt driven. No, the generic serial _console_ is polled and should require no more infrastructure than the early_console version which it strongly resembles. After all, it's generally called from console_init(), at which point there's little more infrastructure available than in setup_arch() _anyway_. You should happily be able to call serial8250_console_init() earlier then console_init() currently does. (Btw, if you're playing with this code I posted a cleanup to all the horrible #ifdefs in console_init, converting it to the __initcall mechanism. http://marc.theaimsgroup.com/?l=linux-kernel&m=103660078206270&w=2 ) -- dwmw2 ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2002-11-18 15:32 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <3DD3FCB3.40506@us.ibm.com.suse.lists.linux.kernel>
[not found] ` <3DD40719.5030108@pobox.com.suse.lists.linux.kernel>
[not found] ` <3DD428C3.4030700@us.ibm.com.suse.lists.linux.kernel>
[not found] ` <20021115044300.C20764@wotan.suse.de.suse.lists.linux.kernel>
[not found] ` <ar1sdm$gfe$1@cesium.transmeta.com.suse.lists.linux.kernel>
2002-11-15 4:31 ` [PATCH] early printk for x86 Andi Kleen
2002-11-15 4:33 ` H. Peter Anvin
2002-11-14 19:42 Dave Hansen
2002-11-14 19:55 ` Andi Kleen
2002-11-14 20:27 ` Jeff Garzik
2002-11-14 22:50 ` Dave Hansen
2002-11-15 3:43 ` Andi Kleen
2002-11-15 3:52 ` William Lee Irwin III
2002-11-15 4:15 ` H. Peter Anvin
2002-11-14 21:05 ` Jeff Garzik
2002-11-14 23:17 ` Jeff Garzik
2002-11-18 15:15 ` David Woodhouse
2002-11-18 15:17 ` Andi Kleen
2002-11-18 15:39 ` David Woodhouse
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox