x86_64: build and use GDT on copied compressed kernel
Subsystems (5)
PATCH 1/1 x86_64: build and use GDT on copied compressed kernel
please check the patch.
YH
[PATCH]x86_64: build and use GDT on copied compressed kernel
Build and use GDT on copied compressed kernel postion, instead of using GDT in data segment of loaded compressed kernel. Otherwise decompressing compressed kernel image later in 64bit longmode, will overwrite GDT.
arch/x86_64/boot/compressed/head.S +17 -13
@@ -94,10 +94,23 @@ startup_32: * Prepare for entering 64 bit mode */ +/* + * Build early GDT table on copied compressed kernel image position, So GDT + * is not be overwriten when decompressing the compressed kernel. + */ + movw $0x0020, gdt+0x00(%ebx) + movw $0x0000, gdt+0x06(%ebx) + movl $0x00000000, gdt+0x08(%ebx) /* NULL descriptor */ + movl $0x00000000, gdt+0x0c(%ebx) + movl $0x0000ffff, gdt+0x10(%ebx) /* __KERNEL_CS */ + movl $0x00af9a00, gdt+0x14(%ebx) + movl $0x0000ffff, gdt+0x18(%ebx) /* __KERNEL_DS */ + movl $0x00cf9200, gdt+0x1c(%ebx) + /* Load new GDT with the 64bit segments using 32bit descriptor */ - leal gdt(%ebp), %eax - movl %eax, gdt+2(%ebp) - lgdt gdt(%ebp) + leal gdt(%ebx), %eax + movl %eax, gdt+2(%ebx) + lgdt gdt(%ebx) /* Enable PAE mode */ xorl %eax, %eax
@@ -182,7 +195,7 @@ no_longmode: * it may change in the future. */ .code64 - .org 0x200 + .org 0x400 ENTRY(startup_64) /* We come here either from startup_32 or directly from a * 64bit bootloader. If we come here from a bootloader we depend on
@@ -287,15 +300,6 @@ relocated: */ jmp *%rbp - .data -gdt: - .word gdt_end - gdt - .long gdt - .word 0 - .quad 0x0000000000000000 /* NULL descriptor */ - .quad 0x00af9a000000ffff /* __KERNEL_CS */ - .quad 0x00cf92000000ffff /* __KERNEL_DS */ -gdt_end: .bss /* Stack for uncompression */ .balign 4
arch/x86_64/boot/compressed/vmlinux.lds +2 -0
@@ -36,6 +36,8 @@ SECTIONS *(COMMON) . = ALIGN(8); _end = . ; + gdt = . ; + . = . + 8 * 4; . = ALIGN(4096); pgtable = . ; . = . + 4096 * 6;
Quoted 1 line · On Sunday 13 May 2007 07:33:14 Yinghai Lu wrote:
please check the patch.
Can you please give a little more description on why you think the patch is needed? Also we need a Signed-off-by line.
Thanks,
-Andi
Quoted 4 lines · Andi Kleen
On Sunday 13 May 2007 07:33:14 Yinghai Lu wrote:
Can you please give a little more description on why you think the patch is needed? Also we need a Signed-off-by line.
in the arch/x86_64/boot/compressed/head.S.
it switch to 64 bit mode and then copy compressed image to higher address. and jump the copied image, then decompressed the compressed image to final uncompressed kernel and it may overlapped with original loaded compressed kernel image.
before jump to 64 bit mode, it will create new page table in some place higher in copied compressed kernel image. but still use the GDT in place of original loaded compressed image. So the GDT will be overwriten in the middle of decompressing.
So we could change to build the GDT like page table together with copied compressed kernel.
Quoted 9 lines · Yinghai Lu
please check the patch.
YH
[PATCH]x86_64: build and use GDT on copied compressed kernel
Build and use GDT on copied compressed kernel postion, instead of using GDT in data segment of loaded compressed kernel. Otherwise decompressing compressed kernel image later in 64bit longmode, will overwrite GDT.
Overwriting the GDT should be fine because we don't reload the segments, after we overwrite it. GDT entries are only read when we load segments. Interrupts are disabled so that should not cause a problem.
Why do you think the current behaviour is a problem?
Eric
Quoted 5 lines · Eric W. Biederman
Overwriting the GDT should be fine because we don't reload the segments, after we overwrite it. GDT entries are only read when we load segments. Interrupts are disabled so that should not cause a problem.
Why do you think the current behaviour is a problem?
just think if GDT should not be overwriten when we are still under that GDT setting.
didn't have chance to test that in HDT or other debug device, when setting breaking point after that GDT is overwriten.
YH
Quoted 11 lines · Yinghai Lu
Quoted 5 lines · Eric W. Biederman
Overwriting the GDT should be fine because we don't reload the segments, after we overwrite it. GDT entries are only read when we load segments. Interrupts are disabled so that should not cause a problem.
Why do you think the current behaviour is a problem?
just think if GDT should not be overwriten when we are still under that GDT setting.
didn't have chance to test that in HDT or other debug device, when setting breaking point after that GDT is overwriten.
It would be interesting to see if you could produce a failure using that gdt, I don't think you will be able to, even with a debugger.
For data segments we never use that GDT, it is only for the code segment we use the GDT and that only to get us into 64bit mode.
Eric
Quoted 4 lines · Eric W. Biederman
For data segments we never use that GDT, it is only for the code segment we use the GDT and that only to get us into 64bit mode.
after the patch linux:/home/yhlu/xx/xx/kernel/linux-2.6/arch/x86_64/boot/compressed # readelf -e vmlinux
...
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000000000 00100000
000000000032617c 0000000000000000 AX 0 0 16
[ 2] .rodata PROGBITS 0000000000326180 00426180
0000000000000400 0000000000000000 A 0 0 32
[ 3] .eh_frame PROGBITS 0000000000326580 00426580
0000000000000210 0000000000000000 A 0 0 8
[ 4] .data PROGBITS 0000000000326790 00426790
0000000000000008 0000000000000000 WA 0 0 8
[ 5] .bss NOBITS 00000000003267a0 00426798
000000000000b860 0000000000000000 WA 0 0 32
[ 6] .comment PROGBITS 0000000000000000 00426798
0000000000000035 0000000000000000 0 0 1
[ 7] .shstrtab STRTAB 0000000000000000 004267cd
0000000000000047 0000000000000000 0 0 1
[ 8] .symtab SYMTAB 0000000000000000 00426a98
00000000000007c8 0000000000000018 9 60 8
[ 9] .strtab STRTAB 0000000000000000 00427260
0000000000000350 0000000000000000 0 0 1Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
after the patch, it seems .data section size still have 8 bytes. before that will 0x28.
don't know what are the 8 bytes.
YH
Quoted 33 lines · Yinghai Lu
Quoted 4 lines · Eric W. Biederman
For data segments we never use that GDT, it is only for the code segment we use the GDT and that only to get us into 64bit mode.
after the patch linux:/home/yhlu/xx/xx/kernel/linux-2.6/arch/x86_64/boot/compressed # readelf -e vmlinux
...
Section Headers:[Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .text PROGBITS 0000000000000000 00100000 000000000032617c 0000000000000000 AX 0 0 16 [ 2] .rodata PROGBITS 0000000000326180 00426180 0000000000000400 0000000000000000 A 0 0 32 [ 3] .eh_frame PROGBITS 0000000000326580 00426580 0000000000000210 0000000000000000 A 0 0 8 [ 4] .data PROGBITS 0000000000326790 00426790 0000000000000008 0000000000000000 WA 0 0 8 [ 5] .bss NOBITS 00000000003267a0 00426798 000000000000b860 0000000000000000 WA 0 0 32 [ 6] .comment PROGBITS 0000000000000000 00426798 0000000000000035 0000000000000000 0 0 1 [ 7] .shstrtab STRTAB 0000000000000000 004267cd 0000000000000047 0000000000000000 0 0 1 [ 8] .symtab SYMTAB 0000000000000000 00426a98 00000000000007c8 0000000000000018 9 60 8 [ 9] .strtab STRTAB 0000000000000000 00427260 0000000000000350 0000000000000000 0 0 1
Quoted 8 lines
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)after the patch, it seems .data section size still have 8 bytes. before that will
0x28.
don't know what are the 8 bytes.
Probably variables in misc.c
Eric
Quoted 1 line · Eric W. Biederman
Probably variables in
misc.c
it is vidmem in misc.c
YH
Eric,
I got one question about kexec and bzImage on 64bit kernel.
The bzImage for 64bit kernel must be loaded under 4G? but vmlinux for 64bit kernel could be loaded above 4G.
So is there any plan to use 64bit entry point (startup_64) in arch/x86_64/boot/compressed/vmlinux in bzImage? so you may load bzImage above 4G too.
YH
Quoted 10 lines · Yinghai Lu
Eric,
I got one question about kexec and bzImage on 64bit kernel.
The bzImage for 64bit kernel must be loaded under 4G? but vmlinux for 64bit kernel could be loaded above 4G.
So is there any plan to use 64bit entry point (
startup_64) inarch/x86_64/boot/compressed/vmlinuxin bzImage? so you may load bzImage above 4G too.
We have big boot protocol revision coming up to more clearly document what is needed to work with the native entry points. It is a 2.6.23 targeted thing and that is one of the things that we are likely to look at.
Eric
Quoted 4 lines · Eric W. Biederman
We have big boot protocol revision coming up to more clearly document what is needed to work with the native entry points. It is a 2.6.23 targeted thing and that is one of the things that we are likely to look at.
Good, where is the thread for that?
YH
Quoted 7 lines · Yinghai Lu
Quoted 4 lines · Eric W. Biederman
We have big boot protocol revision coming up to more clearly document what is needed to work with the native entry points. It is a 2.6.23 targeted thing and that is one of the things that we are likely to look at.
Good, where is the thread for that?
Look on the virtualization list may lkml was cc'd about getting Xen and lguest. "boot bzImages under paravirt" I think was the subject on one of the pieces.
A lot of this work is held up in part by the need to get 2.6.22 out, and in part because we have so much in flight work for the early phases of boot that we need to let things settle before it we can do more.
Eric
PATCH 1/1 serial: set RTS and DTR if flow is 'r'
In reply to Eric W. Biederman[PATCH] serial: set RTS and DTR if flow is 'r'
if the serial console flow is set to 'r', We need to set RTS and DTR. Some UARTs on other side need these bit set, otherwise will send char to or receive char from the host that kernel is runing esp for kernel boot stage.
BTW:
earlyprintk and early_uart are hard coded to set DTR/RTS.
drivers/serial/8250.c +0 -0
@@ -2154,6 +2154,16 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
}serial_outp(up, UART_FCR, fcr); /* set fcr */
}
+
+ /* if serial console flow is 'r', we need to set RTS and DTR to MCR.
+ * some uarts on other side don't support no flow control. So we state
+ * console=ttyS0,9600n8r in kernel command line to make those uart can
+ * work.
+ */
+ if (termios->c_cflag & CRTSCTS) {
+ up->port.mctrl |= TIOCM_RTS | TIOCM_DTR;
+ }
+serial8250_set_mctrl(&up->port, up->port.mctrl); spin_unlock_irqrestore(&up->port.lock, flags);
}
Re: [PATCH] serial: set RTS and DTR if flow is 'r'
Quoted 21 lines · On Mon, 14 May 2007 10:26:26 -0700 Yinghai Lu wrote:
[PATCH] serial: set RTS and DTR if flow is 'r'
if the serial console flow is set to 'r', We need to set RTS and DTR. Some UARTs on other side need these bit set, otherwise will send char to or receive char from the host that kernel is runing esp for kernel boot stage.
BTW:
earlyprintk andearly_uartare hard coded to set DTR/RTS.Signed-off-by Yinghai Lu <[email protected]>Cc Russell King <[email protected]>Cc Andi Kleen <[email protected]>Cc Bjorn Helgaas <[email protected]>drivers/serial/8250.c +0
-0@@ -2154,6 +2154,16 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, }
Quoted 1 line
serial_outp(up, UART_FCR, fcr); /* set fcr */
Something is eating tabs above and presumably in the new patch lines...
Quoted 7 lines
}
+
+ /* if serial console flow is 'r', we need to set RTS and DTR to MCR.
+ * some uarts on other side don't support no flow control. So we state
+ * console=ttyS0,9600n8r in kernel command line to make those uart can
+ * work.
+ */
/*
* Linux long comment style is
* like this.
*/
Quoted 3 lines
+ if (
termios->c_cflag& CRTSCTS) {
+up->port.mctrl|=TIOCM_RTS|TIOCM_DTR;
+ }
Don't use braces on one-statement blocks.
Quoted 4 lines
+
serial8250_set_mctrl(&up->port, up->port.mctrl);spin_unlock_irqrestore(&up->port.lock, flags);
}
---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
PATCH 1/1 serial: set RTS and DTR if flow is 'r' --- resend
In reply to Yinghai Lu[PATCH] serial: set RTS and DTR if flow is 'r'
if the serial console flow is set to 'r', We need to set RTS and DTR. Some UARTs on other side need these bit set, otherwise will not send char to or receive char from the host that kernel is runing esp for kernel boot stage.
BTW:
earlyprintk and early_uart are hard coded to set DTR/RTS.
drivers/serial/8250.c +0 -0
@@ -2154,6 +2154,15 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
}serial_outp(up, UART_FCR, fcr); /* set fcr */
}
+
+ /* if serial console flow is 'r', we need to set RTS and DTR to MCR.
+ * some uarts on other side don't support no flow control. So we state
+ * console=ttyS0,9600n8r in kernel command line to make those uart can
+ * work.
+ */
+ if (termios->c_cflag & CRTSCTS)
+ up->port.mctrl |= TIOCM_RTS | TIOCM_DTR;
+serial8250_set_mctrl(&up->port, up->port.mctrl); spin_unlock_irqrestore(&up->port.lock, flags);
}
Re: [PATCH] serial: set RTS and DTR if flow is 'r' --- resend
Quoted 6 lines · Yinghai Lu
[PATCH] serial: set RTS and DTR if flow is 'r'
if the serial console flow is set to 'r', We need to set RTS and DTR. Some UARTs on other side need these bit set, otherwise will not send char to or
receive char from the host that kernel is runing esp for kernel boot stage.
Patch is still broken. Patch is completely wrong as well - we do _not_ want to set the RTS and DTR bits here, and is in fact undoing a fix I put in over the 2.4 drivers.
If CRTSCTS is enabled via userspace, and the port is not being used as a console, we do not want to raise RTS _until_ we are ready to receive characters. Your patch breaks this.
Moreover, I question the reasoning. RTS is normally raised to allow the remote end to send characters. Since the kernel console is output _only_, until userspace opens it, there's little point in raising RTS. RTS will be raised when userspace opens it.
There may be some sense, however, in allowing DTR to be permanently raised for serial consoles. However, I would err on caution since DTR is used to reliably instruct modems to drop the line, so making such a change would be undesirable for those folk.
Signature · 3 lines
Russell King Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/ maintainer of:
Re: [PATCH] serial: set RTS and DTR if flow is 'r' --- resend
Quoted 5 lines · Russell King
There may be some sense, however, in allowing DTR to be permanently raised for serial consoles. However, I would err on caution since DTR is used to reliably instruct modems to drop the line, so making such a change would be undesirable for those folk.
please check following is OK.
YH
[PATCH] serial: set DTR in uart for kernel serial console
Some UARTs on other side need host uart DTR is set, otherwise will not receive char from the host that kernel is runing during kernel boot stage.
BTW:
earlyprintk and early_uart are hard coded to set DTR/RTS.
*diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c*
index 48e259a..29c051c 100644
*--- a/drivers/serial/8250.c*
*+++ b/drivers/serial/8250.c*
@@ -2154,6 +2154,12 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
} serial_outp(up, UART_FCR, fcr); /* set fcr */ }
+
+ /* some uarts on other side don't support no flow control. So we set
+ * DTR in host uart to make them happy
+ */
+ up->port.mctrl |= TIOCM_DTR;
+
serial8250_set_mctrl(&up->port, up->port.mctrl); spin_unlock_irqrestore(&up->port.lock, flags); }
Re: [PATCH] serial: set RTS and DTR if flow is 'r' --- resend
Quoted 7 lines · Yinghai Lu
Quoted 5 lines · Russell King
There may be some sense, however, in allowing DTR to be permanently raised for serial consoles. However, I would err on caution since DTR is used to reliably instruct modems to drop the line, so making such a change would be undesirable for those folk.
please check following is OK.
Still wrong, and unfortunately you haven't understood what I was saying at all because this is worse. ;(
Do not put the code in serial8250_set_termios. It is the wrong place.
Quoted 35 lines
YH
[PATCH] serial: set DTR in uart for kernel serial console
Some UARTs on other side need host uart DTR is set, otherwise will not receive char from the host that kernel is runing during kernel boot stage.
BTW:
earlyprintk andearly_uartare hard coded to set DTR/RTS.Signed-off-by Yinghai Lu <[email protected]>Cc Russell King <[email protected]>Cc Andi Kleen <[email protected]>Cc Bjorn Helgaas <[email protected]>*diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c* index 48e259a..29c051c 100644
*--- a/drivers/serial/8250.c*
*+++ b/drivers/serial/8250.c*(quoted diff) +6
-0@@ -2154,6 +2154,12 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, } serial_outp(up, UART_FCR, fcr); /* set fcr */ } + + /* some uarts on other side don't support no flow control. So we set + * DTR in host uart to make them happy + */ + up->port.mctrl |= TIOCM_DTR; + serial8250_set_mctrl(&up->port, up->port.mctrl); spin_unlock_irqrestore(&up->port.lock, flags);}
Signature · 3 lines
Russell King Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/ maintainer of:
Re: [PATCH] serial: set RTS and DTR if flow is 'r' --- resend
Quoted 5 lines · Russell King
Still wrong, and unfortunately you haven't understood what I was saying at all because this is worse. ;(
Do not put the code in
serial8250_set_termios. It is the wrong place.
I don't want to put that there. the problem is serial8250_set_mctrl called by will clear DTR bit.
uart_set_options==>serial8250_set_termios ==> serial8250_set_mctrl will clear DTR bit
YH
static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl) {
struct uart_8250_port *up = (struct uart_8250_port *)port; unsigned char mcr = 0;
if (mctrl & TIOCM_RTS)
mcr |= UART_MCR_RTS;
if (mctrl & TIOCM_DTR)
mcr |= UART_MCR_DTR;
if (mctrl & TIOCM_OUT1)
mcr |= UART_MCR_OUT1;
if (mctrl & TIOCM_OUT2)
mcr |= UART_MCR_OUT2;
if (mctrl & TIOCM_LOOP)
mcr |= UART_MCR_LOOP;
mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
serial_out(up, UART_MCR, mcr);
}
Re: [PATCH] serial: set RTS and DTR if flow is 'r' --- resend
Quoted 9 lines · Yinghai Lu
Quoted 5 lines · Russell King
Still wrong, and unfortunately you haven't understood what I was saying at all because this is worse. ;(
Do not put the code in
serial8250_set_termios. It is the wrong place.I don't want to put that there. the problem is
serial8250_set_mctrlcalled by will clear DTR bit.
We're at a stalemate then.
Signature · 3 lines
Russell King Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/ maintainer of:
Re: [PATCH] serial: set RTS and DTR if flow is 'r' --- resend
Quoted 8 lines · Russell King
Quoted 2 lines · Yinghai Lu
I don't want to put that there. the problem is
serial8250_set_mctrlcalled by will clear DTR bit.We're at a stalemate then.
How about put that line intoserial8250_console_setup
orserial8250_isa_init_ports
YH
PATCH 1/1 serial: set DTR in uart for kernel serial console
In reply to Yinghai LuHope format is OK. Sending with KMail Message/Insert File
YH
[PATCH] serial: set DTR in uart for kernel serial console
Some UARTs on other side need host uart DTR is set, otherwise will not receive char from the host that kernel is runing during kernel boot stage.
BTW:
earlyprintk and early_uart are hard coded to set DTR/RTS.
drivers/serial/8250.c +5 -0
@@ -2397,6 +2397,11 @@ static void __init serial8250_isa_init_ports(void) up->mcr_force =ALPHA_KLUDGE_MCR ; up->port.ops = &serial8250_pops; + +/* some uarts on other side don't support no flow control. So we set +* DTR in host uart to make them happy --- YHLU +*/ + up->port.mctrl |=TIOCM_DTR ; } for (i = 0, up = serial8250_ports;
PATCH] serial: convert early_uart to earlycon for 8250
PATCH] serial: convert early_uart to earlycon for 8250
Beacuse SERIAL_PORT_DFNS is removed from include/asm-i386/serial.h and include/asm-x86_64/serial.h. the serial8250_ports need to be probed late in serial initializing stage. the console_init=>serial8250_console_init=> register_console=>serial8250_console_setup will return -ENDEV, and console ttyS0 can not be enabled at that time.
need to wait till uart_add_one_port in drivers/serial/serial_core.c to call register_console to get console ttyS0. that is too late.
Make early_uart to use early_param, so uart console can be used earlier. Make it to be bootconsole with CON_BOOT flag, so can use console handover feature. and it will switch to corresponding normal serial console automatically.
new command line will be:
console=uart8250,io,0x3f8,9600n8 console=uart8250,mmio,0xff5e0000,115200n8 or earlycon=uart8250,io,0x3f8,9600n8 earlycon=uart8250,mmio,0xff5e0000,115200n8
it will print in very early stage:
Early serial console at I/O port 0x3f8 (options '9600n8') console [uart0] enabled later for console it will print: console handover: boot [uart0] -> real [ttyS0]
Documentation/kernel-parameters.txt | 12 +++- arch/i386/kernel/head.S | 8 ++ arch/ia64/kernel/setup.c | 4 - arch/x86_64/kernel/head.S | 15 ++++- drivers/serial/8250.c | 26 +-------- drivers/serial/8250_early.c | 103 ++++++++++++++---------------------- drivers/serial/Kconfig | 8 ++ drivers/serial/serial_core.c | 5 + include/asm-i386/fixmap.h | 2 include/asm-i386/io.h | 13 ++++ include/asm-ia64/io.h | 4 + include/asm-x86_64/fixmap.h | 4 + include/asm-x86_64/io.h | 13 ++++ include/linux/console.h | 1 include/linux/serial.h | 6 -- include/linux/serial_8250.h | 3 + include/linux/serial_core.h | 5 + init/main.c | 5 + kernel/printk.c | 17 +++++ 19 files changed, 156 insertions(+), 98 deletions(-)
Documentation/kernel-parameters.txt +10 -2
@@ -444,8 +444,16 @@ and is between 256 and 4096 characters. It is defined in the file Documentation/networking/netconsole.txt for an alternative. - uart,io,<addr>[,options] - uart,mmio,<addr>[,options] + uart8250,io,<addr>[,options] + uart8250,mmio,<addr>[,options] + Start an early, polled-mode console on the 8250/16550 + UART at the specified I/O port or MMIO address, + switching to the matching ttyS device later. The + options are the same as for ttyS, above. + + earlycon= [KNL] Output early console device and options. + uart8250,io,<addr>[,options] + uart8250,mmio,<addr>[,options] Start an early, polled-mode console on the 8250/16550 UART at the specified I/O port or MMIO address, switching to the matching ttyS device later. The
arch/i386/kernel/head.S +8 -0
@@ -168,6 +168,12 @@ page_pde_offset = (__PAGE_OFFSET >> 20); .section .init.text,"ax",@progbits #endif + /* Do an early initialization of the fixmap area */ + movl $(swapper_pg_dir - __PAGE_OFFSET), %edx + movl $(swapper_pg_pmd - __PAGE_OFFSET), %eax + addl $0x007, %eax /* 0x007 = PRESENT+RW+USER */ + movl %eax, 4092(%edx) + #ifdef CONFIG_SMP ENTRY(startup_32_smp) cld
@@ -507,6 +513,8 @@ ENTRY(_stext) .section ".bss.page_aligned","w" ENTRY(swapper_pg_dir) .fill 1024,4,0 +ENTRY(swapper_pg_pmd) + .fill 1024,4,0 ENTRY(empty_zero_page) .fill 4096,1,0
arch/ia64/kernel/setup.c +0 -4
@@ -390,10 +390,6 @@ early_console_setup (char *cmdline)if (!efi_setup_pcdp_console (cmdline)) earlycons++;#endif -#ifdef CONFIG_SERIAL_8250_CONSOLE -if (!early_serial_console_init (cmdline)) - earlycons++; -#endif return (earlycons) ?0 :-1 ; }
arch/x86_64/kernel/head.S +14 -1
@@ -73,7 +73,11 @@ startup_64: addq %rbp, init_level4_pgt + (511*8)(%rip) addq %rbp, level3_ident_pgt + 0(%rip) + addq %rbp, level3_kernel_pgt + (510*8)(%rip) + addq %rbp, level3_kernel_pgt + (511*8)(%rip) + + addq %rbp, level2_fixmap_pgt + (506*8)(%rip) /* Add an Identity mapping if I am above 1G */ leaq _text(%rip), %rdi
@@ -314,7 +318,16 @@ NEXT_PAGE(level3_kernel_pgt) .fill 510,8,0 /* (2^48-(2*1024*1024*1024)-((2^39)*511))/(2^30) = 510 */ .quad level2_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE - .fill 1,8,0 + .quad level2_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE + +NEXT_PAGE(level2_fixmap_pgt) + .fill 506,8,0 + .quad level1_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE + /* 8MB reserved for vsyscalls + a 2MB hole = 4 + 1 entries */ + .fill 5,8,0 + +NEXT_PAGE(level1_fixmap_pgt) + .fill 512,8,0 NEXT_PAGE(level2_ident_pgt) /* Since I easily can, map the first 1G.
drivers/scsi/Kconfig +0 -0
drivers/serial/8250.c +5 -21
@@ -2367,6 +2367,9 @@ static struct uart_ops serial8250_pops = { .request_port = serial8250_request_port, .config_port = serial8250_config_port, .verify_port = serial8250_verify_port, +#ifdef CONFIG_SERIAL_8250_CONSOLE + .find_port_for_earlycon = serial8250_find_port_for_earlycon, +#endif };static struct uart_8250_port serial8250_ports[UART_NR ];
@@ -2402,6 +2405,7 @@ static void __init serial8250_isa_init_ports(void)for (i =0 , up = serial8250_ports; i <ARRAY_SIZE (old_serial_port) && i < nr_uarts; i++, up++) { +printk (KERN_INFO "serial8250_isa_init_ports 2 idx=%d\n" ,i); up->port.iobase = old_serial_port[i].port; up->port.irq =irq_canonicalize (old_serial_port[i].irq); up->port.uartclk = old_serial_port[i].baud_base *16 ;
@@ -2533,7 +2537,7 @@ static int __init serial8250_console_init(void) }console_initcall (serial8250_console_init); -static int __init find_port (struct uart_port *p) +int __init find_port_serial8250 (struct uart_port *p) {int line;struct uart_port *port;
@@ -2546,26 +2550,6 @@ static int __init find_port(struct uart_port *p) return -ENODEV; } -int __init serial8250_start_console (struct uart_port *port,char *options) -{ -int line; - - line =find_port (port); -if (line <0 ) -return -ENODEV ; - -add_preferred_console ("ttyS" , line, options); -printk ("Adding console on ttyS%d at %s 0x%lx (options '%s')\n" , - line, port->iotype ==UPIO_MEM ?"MMIO" :"I/O port" , - port->iotype ==UPIO_MEM ? (unsigned long ) port->mapbase : - (unsigned long ) port->iobase, options); -if (!(serial8250_console.flags &CON_ENABLED )) { - serial8250_console.flags &= ~CON_PRINTBUFFER ; -register_console (&serial8250_console); - } -return line; -} -#define SERIAL8250_CONSOLE &serial8250_console#else #define SERIAL8250_CONSOLE NULL
drivers/serial/8250_early.c +42 -61
178 lines not on this page · raw message
drivers/serial/Kconfig +8 -0
@@ -62,6 +62,14 @@ config SERIAL_8250_CONSOLE kernel will automatically use the first serial line, /dev/ttyS0, as system console. + you can set that using a kernel command line option such as + "earlycon=uart8250,io,0x3f8,9600n8" + "earlycon=uart8250,mmio,0xff5e0000,115200n8" or + "console=uart8250,io,0x3f8,9600n8" + "console=uart8250,mmio,0xff5e0000,115200n8". + and it will switch to normal serial console when correponding port is + ready. + If unsure, say N. config SERIAL_8250_GSC
drivers/serial/serial_core.c +4 -1
@@ -2303,8 +2303,11 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)* It may be that the port was not available. */ if (port->type !=PORT_UNKNOWN && - port->cons && !(port->cons->flags &CON_ENABLED )) + port->cons && !(port->cons->flags &CON_ENABLED )) { +if (port->ops && port->ops->find_port_for_earlycon) + port->ops->find_port_for_earlycon ();register_console (port->cons); + }/* * Ensure UPF_DEAD is not set.
include/asm-i386/fixmap.h +2 -0
@@ -54,6 +54,8 @@ extern unsigned long __FIXADDR_TOP;enum fixed_addresses {FIX_HOLE ,FIX_VDSO , +FIX_DBGP_BASE , +FIX_EARLYCON_MEM_BASE ,#ifdef CONFIG_X86_LOCAL_APIC FIX_APIC_BASE ,/* local (CPU) APIC) -- required for SMP or not */ #endif
include/asm-i386/io.h +13 -0
@@ -130,6 +130,19 @@ extern void iounmap(volatile void __iomem *addr);extern void *bt_ioremap (unsigned long offset,unsigned long size);extern void bt_iounmap (void *addr,unsigned long size); +#include <asm/pgtable.h> +#include <asm/fixmap.h> + +static inline void __iomem *fix_ioremap (unsigned idx,unsigned long phys) +{ +void __iomem * vaddr; +set_fixmap_nocache (idx, phys &PAGE_MASK ); + vaddr = (void __iomem *)__fix_to_virt (idx); + vaddr += phys & ~PAGE_MASK ; + +return vaddr; +} +/* Use early IO mappings for DMI because it's initialized early */ #define dmi_ioremap bt_ioremap#define dmi_iounmap bt_iounmap
include/asm-ia64/io.h +4 -0
@@ -423,6 +423,10 @@ extern void __iomem * ioremap(unsigned long offset, unsigned long size);extern void __iomem *ioremap_nocache (unsigned long offset,unsigned long size);extern void iounmap (volatile void __iomem *addr); +/* for console=uart8250,mmio,0xffe5000,9600n8 */ +#define FIX_EARLYCON_MEM_BASE 1 +#define fix_ioremap (idx, phys) ioremap(phys, 64) +/* Use normal IO mappings for DMI */ #define dmi_ioremap ioremap#define dmi_iounmap (x,l) iounmap(x)
include/asm-x86_64/fixmap.h +3 -1
@@ -35,6 +35,8 @@ enum fixed_addresses {VSYSCALL_LAST_PAGE ,VSYSCALL_FIRST_PAGE =VSYSCALL_LAST_PAGE + ((VSYSCALL_END -VSYSCALL_START ) >>PAGE_SHIFT ) -1 ,VSYSCALL_HPET , +FIX_DBGP_BASE , +FIX_EARLYCON_MEM_BASE ,FIX_HPET_BASE ,FIX_APIC_BASE ,/* local (CPU) APIC) -- required for SMP or not */ FIX_IO_APIC_BASE_0,
@@ -84,7 +86,7 @@ static __always_inline unsigned long fix_to_virt(const unsigned int idx)if (idx >= __end_of_fixed_addresses)__this_fixmap_does_not_exist (); - return __fix_to_virt(idx); + return __fix_to_virt(idx); }#endif
include/asm-x86_64/io.h +13 -0
@@ -145,6 +145,19 @@ extern void early_iounmap(void *addr, unsigned long size);extern void __iomem *ioremap_nocache (unsigned long offset,unsigned long size);extern void iounmap (volatile void __iomem *addr); +#include <asm/pgtable.h> +#include <asm/fixmap.h> + +static inline void __iomem *fix_ioremap (unsigned idx,unsigned long phys) +{ +void __iomem * vaddr; +set_fixmap_nocache (idx, phys &PAGE_MASK ); + vaddr = (void __iomem *)__fix_to_virt (idx); + vaddr += phys & ~PAGE_MASK ; + +return vaddr; +} +/* * ISA I/O bus memory addresses are 1:1 with the physical address. */
include/linux/console.h +1 -0
@@ -107,6 +107,7 @@ struct console { };extern int add_preferred_console (char *name,int idx,char *options); +extern int update_console_cmdline_console_index (char *name,int idx_old,int idx_new);extern void register_console (struct console *);extern int unregister_console (struct console *);extern struct console *console_drivers;
include/linux/serial.h +0 -6
@@ -177,11 +177,5 @@ struct serial_icounter_struct {#ifdef __KERNEL__#include <linux/compiler.h> -/* Allow architectures to override entries in serial8250_ports[] at run time: */ -struct uart_port ;/* forward declaration */ -extern int early_serial_setup (struct uart_port *port); -extern int early_serial_console_init (char *options); -extern int serial8250_start_console (struct uart_port *port,char *options); -#endif /* __KERNEL__ */ #endif /* _LINUX_SERIAL_H */
include/linux/serial_8250.h +3 -0
@@ -60,4 +60,7 @@ void serial8250_unregister_port(int line);void serial8250_suspend_port (int line);void serial8250_resume_port (int line); +extern int find_port_serial8250 (struct uart_port *p); +extern int serial8250_find_port_for_earlycon (void ); +#endif
include/linux/serial_core.h +5 -0
@@ -199,6 +199,11 @@ struct uart_ops {void (*config_port)(struct uart_port *,int );int (*verify_port)(struct uart_port *,struct serial_struct *);int (*ioctl)(struct uart_port *,unsigned int ,unsigned long ); + +/* +* for earlycon to console switch +*/ +int (*find_port_for_earlycon)(void ); };#define UART_CONFIG_TYPE (1 << 0)
init/main.c +4 -1
@@ -452,7 +452,10 @@ static int __init do_early_param(char *param, char *val)struct obs_kernel_param *p;for (p = __setup_start; p < __setup_end; p++) { -if (p->early &&strcmp (param, p->str) ==0 ) { +if ((p->early &&strcmp (param, p->str) ==0 ) || + (strcmp (param,"console" ) ==0 && +strcmp (p->str,"earlycon" ) ==0 ) + ) {if (p->setup_func (val) !=0 )printk (KERN_WARNING "Malformed early option '%s'\n" , param);
kernel/printk.c +17 -0
@@ -726,6 +726,20 @@ int __init add_preferred_console(char *name, int idx, char *options)return 0 ; } +int __init update_console_cmdline_console_index (char *name,int idx_old,int idx_new) +{ +int i; + +for (i =0 ; i <MAX_CMDLINECONSOLES && console_cmdline[i].name[0 ]; i++) +if (strcmp (console_cmdline[i].name, name) ==0 && + console_cmdline[i].index == idx_old) { + console_cmdline[i].index = idx_new; +return 0 ; + } + +return 0 ; +} +#ifndef CONFIG_DISABLE_CONSOLE_SUSPEND /** * suspend_console - suspend the console subsystem
@@ -991,6 +1005,9 @@ void register_console(struct console *console) console->name, console->index);unregister_console (bootconsole); console->flags &= ~CON_PRINTBUFFER ; + }else { +printk (KERN_INFO "console [%s%d] enabled\n" , + console->name, console->index); }/*
Re: PATCH] serial: convert early_uart to earlycon for 8250
I can't comment on the arch specific bits. As a general note, I think this is over complex. For instance, the additional hook in serial_core to call the find_port_for_earlycon method isn't needed because you can call serial8250_find_port_for_earlycon() from within serial8250_console_setup(). You can also modify co->index from within there without needing update_console_cmdline_console_index().
Bjorn needs to review the 8250_early changes.
Apart from that, two other comments:
drivers/serial/8250.c static void __init serial8250_isa_init_ports(void) · line 2408
Quoted 9 lines · Yinghai Lu
drivers/serial/8250.c +1
-0@@ -2402,6 +2405,7 @@ static void __init serial8250_isa_init_ports(void)for (i =0 , up = serial8250_ports; i <ARRAY_SIZE (old_serial_port) && i < nr_uarts; i++, up++) { +printk (KERN_INFO "serial8250_isa_init_ports 2 idx=%d\n" ,i);
Is this a debugging printk?
drivers/serial/8250.c static int __init serial8250_console_init(void) · line 2540
Quoted 9 lines
drivers/serial/8250.c +1
-1up->port.iobase = old_serial_port[i].port; up->port.irq =irq_canonicalize (old_serial_port[i].irq); up->port.uartclk = old_serial_port[i].baud_base *16 ;@@ -2533,7 +2537,7 @@ static int __init serial8250_console_init(void) }console_initcall (serial8250_console_init); -static int __init find_port (struct uart_port *p) +int __init find_port_serial8250 (struct uart_port *p)
If this is going to become globally visible, please name it serial8250_find_port to match the style of the rest of the file.
Quoted 9 lines
drivers/serial/8250.c +0
-0{int line;struct uart_port *port;include/linux/serial.h +0
-0@@ -177,11 +177,5 @@ struct serial_icounter_struct {#ifdef __KERNEL__
include/linux/serial.h struct serial_icounter_struct { · line 181
Quoted 10 lines
include/linux/serial.h +0
-6#include <linux/compiler.h> -/* Allow architectures to override entries in serial8250_ports[] at run time: */ -struct uart_port ;/* forward declaration */ -extern int early_serial_setup (struct uart_port *port); -extern int early_serial_console_init (char *options); -extern int serial8250_start_console (struct uart_port *port,char *options); -#endif /* __KERNEL__ */ #endif /* _LINUX_SERIAL_H */
Good - this needed to be killed.
Signature · 3 lines
Russell King Linux kernel 2.6 ARM Linux - http://www.arm.linux.org.uk/ maintainer of:
Re: PATCH] serial: convert early_uart to earlycon for 8250
Quoted 6 lines · Russell King
I can't comment on the arch specific bits. As a general note, I think this is over complex. For instance, the additional hook in
serial_coreto call thefind_port_for_earlyconmethod isn't needed because you can callserial8250_find_port_for_earlycon()from withinserial8250_console_setup(). You can also modifyco->indexfrom within there without needingupdate_console_cmdline_console_index().
Good point, I will try to remove that hook.
Quoted 6 lines
Bjorn needs to review the 8250_early changes.
Apart from that, two other comments:
On Tue, May 22, 2007 at 12:31:59PM -0700, Yinghai Lu wrote:
Quoted 11 lines
drivers/serial/8250.c static void __init serial8250_isa_init_ports(void) · line 2408
Quoted 9 lines
drivers/serial/8250.c +1
-0@@ -2402,6 +2405,7 @@ static void __init serial8250_isa_init_ports(void)for (i =0 , up = serial8250_ports; i <ARRAY_SIZE (old_serial_port) && i < nr_uarts; i++, up++) { +printk (KERN_INFO "serial8250_isa_init_ports 2 idx=%d\n" ,i);Is this a debugging printk?
Oh.
Quoted 8 lines
Quoted 8 lines
drivers/serial/8250.c +0
-0up->port.iobase = old_serial_port[i].port; up->port.irq =irq_canonicalize (old_serial_port[i].irq); up->port.uartclk = old_serial_port[i].baud_base *16 ;@@ -2533,7 +2537,7 @@ static int __init serial8250_console_init(void) }console_initcall (serial8250_console_init);
Quoted 5 lines
drivers/serial/8250.c static int __init serial8250_console_init(void) · line 2540
Quoted 2 lines
drivers/serial/8250.c +1
-1-static int __init find_port (struct uart_port *p) +int __init find_port_serial8250 (struct uart_port *p)If this is going to become globally visible, please name it
serial8250_find_portto match the style of the rest of the file.
I see.
YH