- Use __pa() around the VGA base address: more friendly for the 4g/4g split. - Use cpu_relax() rather than open-coding rep_nop(). - Default to 9600 baud - Move documentation to Documentation/kernel-parameters.txt - Make CONFIG_EARLY_PRINTK disableable if CONFIG_EMBEDDED --- Documentation/kernel-parameters.txt | 4 +- arch/i386/Kconfig | 12 ++++++- arch/i386/kernel/Makefile | 0 arch/i386/kernel/setup.c | 3 + arch/x86_64/Kconfig | 14 ++++---- arch/x86_64/kernel/early_printk.c | 60 ++++++++++++++++++------------------ arch/x86_64/kernel/head64.c | 4 +- arch/x86_64/kernel/setup.c | 0 8 files changed, 55 insertions(+), 42 deletions(-) diff -puN arch/i386/Kconfig~early_printk-tweaks arch/i386/Kconfig --- 25/arch/i386/Kconfig~early_printk-tweaks 2004-02-08 21:40:20.000000000 -0800 +++ 25-akpm/arch/i386/Kconfig 2004-02-08 21:40:20.000000000 -0800 @@ -1209,7 +1209,17 @@ config DEBUG_KERNEL identify kernel problems. config EARLY_PRINTK - default y + bool "Early printk" if EMBEDDED + default y + help + Write kernel log output directly into the VGA buffer or to a 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. config DEBUG_STACKOVERFLOW bool "Check for stack overflows" diff -puN arch/i386/kernel/Makefile~early_printk-tweaks arch/i386/kernel/Makefile diff -puN arch/i386/kernel/setup.c~early_printk-tweaks arch/i386/kernel/setup.c --- 25/arch/i386/kernel/setup.c~early_printk-tweaks 2004-02-08 21:40:20.000000000 -0800 +++ 25-akpm/arch/i386/kernel/setup.c 2004-02-08 21:40:20.000000000 -0800 @@ -1170,7 +1170,8 @@ void __init setup_arch(char **cmdline_p) char *s = strstr(*cmdline_p, "earlyprintk="); if (s) { extern void setup_early_printk(char *); - setup_early_printk(s+12); + + setup_early_printk(s); printk("early console enabled\n"); } } diff -puN arch/x86_64/kernel/early_printk.c~early_printk-tweaks arch/x86_64/kernel/early_printk.c --- 25/arch/x86_64/kernel/early_printk.c~early_printk-tweaks 2004-02-08 21:40:20.000000000 -0800 +++ 25-akpm/arch/x86_64/kernel/early_printk.c 2004-02-08 21:40:20.000000000 -0800 @@ -8,7 +8,7 @@ /* Simple VGA output */ #ifdef __i386__ -#define VGABASE (__PAGE_OFFSET + 0xb8000UL) +#define VGABASE __pa(__PAGE_OFFSET + 0xb8000UL) #else #define VGABASE 0xffffffff800b8000UL #endif @@ -26,15 +26,14 @@ static void early_vga_write(struct conso 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++) { + 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++) { + for (i = 0; i < MAX_XPOS; i++) writew(0x720, VGABASE + 2*(MAX_XPOS*j + i)); - } current_ypos = MAX_YPOS-1; } if (c == '\n') { @@ -42,7 +41,8 @@ static void early_vga_write(struct conso current_ypos++; } else if (c != '\r') { writew(((0x7 << 8) | (unsigned short) c), - VGABASE + 2*(MAX_XPOS*current_ypos + current_xpos++)); + VGABASE + 2*(MAX_XPOS*current_ypos + + current_xpos++)); if (current_xpos >= MAX_XPOS) { current_xpos = 0; current_ypos++; @@ -82,7 +82,7 @@ static int early_serial_putc(unsigned ch { unsigned timeout = 0xffff; while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout) - rep_nop(); + cpu_relax(); outb(ch, early_serial_base + TXR); return timeout ? 0 : -1; } @@ -97,10 +97,13 @@ static void early_serial_write(struct co } } +#define DEFAULT_BAUD 9600 + static __init void early_serial_init(char *opt) { unsigned char c; - unsigned divisor, baud = 38400; + unsigned divisor; + unsigned baud = DEFAULT_BAUD; char *s, *e; if (*opt == ',') @@ -113,25 +116,26 @@ static __init void early_serial_init(cha 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]; - } + + 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 */ + 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; + baud = DEFAULT_BAUD; } divisor = 115200 / baud; @@ -158,6 +162,7 @@ void early_printk(const char *fmt, ...) char buf[512]; int n; va_list ap; + va_start(ap,fmt); n = vscnprintf(buf,512,fmt,ap); early_console->write(early_console,buf,n); @@ -174,6 +179,8 @@ int __init setup_early_printk(char *opt) if (early_console_initialized) return -1; + opt = strchr(opt, '=') + 1; + strlcpy(buf,opt,sizeof(buf)); space = strchr(buf, ' '); if (space) @@ -204,19 +211,12 @@ void __init disable_early_printk(void) if (!early_console_initialized || !early_console) return; if (!keep_early) { - printk("disabling early console...\n"); + printk("disabling early console\n"); unregister_console(early_console); early_console_initialized = 0; } else { - printk("keeping early console.\n"); + 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); +__setup("earlyprintk=", setup_early_printk); diff -puN Documentation/kernel-parameters.txt~early_printk-tweaks Documentation/kernel-parameters.txt --- 25/Documentation/kernel-parameters.txt~early_printk-tweaks 2004-02-08 21:40:20.000000000 -0800 +++ 25-akpm/Documentation/kernel-parameters.txt 2004-02-08 21:40:20.000000000 -0800 @@ -318,8 +318,8 @@ running once the system is up. dtc3181e= [HW,SCSI] earlyprintk= [x86, x86_64] - earlyprintk=vga - earlyprintk=serial[,ttySn[,baudrate]] + early_printk=vga + early_printk=serial[,ttySn[,baudrate]] Append ,keep to not disable it when the real console takes over. diff -puN arch/x86_64/Kconfig~early_printk-tweaks arch/x86_64/Kconfig --- 25/arch/x86_64/Kconfig~early_printk-tweaks 2004-02-08 21:40:20.000000000 -0800 +++ 25-akpm/arch/x86_64/Kconfig 2004-02-08 21:40:20.000000000 -0800 @@ -48,12 +48,14 @@ config EARLY_PRINTK bool default y help - Write kernel log output directly into the VGA buffer. 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. + Write kernel log output directly into the VGA buffer or to a 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. config HPET_TIMER bool diff -puN arch/x86_64/kernel/setup.c~early_printk-tweaks arch/x86_64/kernel/setup.c diff -puN arch/x86_64/kernel/head64.c~early_printk-tweaks arch/x86_64/kernel/head64.c --- 25/arch/x86_64/kernel/head64.c~early_printk-tweaks 2004-02-08 21:40:20.000000000 -0800 +++ 25-akpm/arch/x86_64/kernel/head64.c 2004-02-08 21:40:20.000000000 -0800 @@ -83,9 +83,9 @@ void __init x86_64_start_kernel(char * r /* default console: */ if (!strstr(saved_command_line, "console=")) strcat(saved_command_line, " console=tty0"); - s = strstr(saved_command_line, "earlyprintk="); + s = strstr(saved_command_line, "earlyprintk="); if (s != NULL) - setup_early_printk(s+12); + setup_early_printk(s); #ifdef CONFIG_DISCONTIGMEM s = strstr(saved_command_line, "numa="); if (s != NULL) _