Skip to content

Commit 3181424

Browse files
Denis MukhinIngo Molnar
Denis Mukhin
authored and
Ingo Molnar
committed
x86/early_printk: Add support for MMIO-based UARTs
During the bring-up of an x86 board, the kernel was crashing before reaching the platform's console driver because of a bug in the firmware, leaving no trace of the boot progress. The only available method to debug the kernel boot process was via the platform's MMIO-based UART, as the board lacked an I/O port-based UART, PCI UART, or functional video output. Then it turned out that earlyprintk= does not have a knob to configure the MMIO-mapped UART. Extend the early printk facility to support platform MMIO-based UARTs on x86 systems, enabling debugging during the system bring-up phase. The command line syntax to enable platform MMIO-based UART is: earlyprintk=mmio,membase[,{nocfg|baudrate}][,keep] Note, the change does not integrate MMIO-based UART support to: arch/x86/boot/early_serial_console.c Also, update kernel parameters documentation with the new syntax and add the missing 'nocfg' setting to the PCI serial cards description. Signed-off-by: Denis Mukhin <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 2c118f5 commit 3181424

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

Documentation/admin-guide/kernel-parameters.txt

+8-1
Original file line numberDiff line numberDiff line change
@@ -1407,14 +1407,21 @@
14071407
earlyprintk=serial[,0x...[,baudrate]]
14081408
earlyprintk=ttySn[,baudrate]
14091409
earlyprintk=dbgp[debugController#]
1410-
earlyprintk=pciserial[,force],bus:device.function[,baudrate]
1410+
earlyprintk=pciserial[,force],bus:device.function[,{nocfg|baudrate}]
14111411
earlyprintk=xdbc[xhciController#]
14121412
earlyprintk=bios
1413+
earlyprintk=mmio,membase[,{nocfg|baudrate}]
14131414

14141415
earlyprintk is useful when the kernel crashes before
14151416
the normal console is initialized. It is not enabled by
14161417
default because it has some cosmetic problems.
14171418

1419+
Only 32-bit memory addresses are supported for "mmio"
1420+
and "pciserial" devices.
1421+
1422+
Use "nocfg" to skip UART configuration, assume
1423+
BIOS/firmware has configured UART correctly.
1424+
14181425
Append ",keep" to not disable it when the real console
14191426
takes over.
14201427

arch/x86/kernel/early_printk.c

+44-1
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,6 @@ static __init void early_serial_init(char *s)
190190
early_serial_hw_init(divisor);
191191
}
192192

193-
#ifdef CONFIG_PCI
194193
static __noendbr void mem32_serial_out(unsigned long addr, int offset, int value)
195194
{
196195
u32 __iomem *vaddr = (u32 __iomem *)addr;
@@ -207,6 +206,45 @@ static __noendbr unsigned int mem32_serial_in(unsigned long addr, int offset)
207206
}
208207
ANNOTATE_NOENDBR_SYM(mem32_serial_in);
209208

209+
/*
210+
* early_mmio_serial_init() - Initialize MMIO-based early serial console.
211+
* @s: MMIO-based serial specification.
212+
*/
213+
static __init void early_mmio_serial_init(char *s)
214+
{
215+
unsigned long baudrate;
216+
unsigned long membase;
217+
char *e;
218+
219+
if (*s == ',')
220+
s++;
221+
222+
if (!strncmp(s, "0x", 2)) {
223+
/* NB: only 32-bit addresses are supported. */
224+
membase = simple_strtoul(s, &e, 16);
225+
early_serial_base = (unsigned long)early_ioremap(membase, PAGE_SIZE);
226+
227+
static_call_update(serial_in, mem32_serial_in);
228+
static_call_update(serial_out, mem32_serial_out);
229+
230+
s += strcspn(s, ",");
231+
if (*s == ',')
232+
s++;
233+
}
234+
235+
if (!strncmp(s, "nocfg", 5)) {
236+
baudrate = 0;
237+
} else {
238+
baudrate = simple_strtoul(s, &e, 0);
239+
if (baudrate == 0 || s == e)
240+
baudrate = DEFAULT_BAUD;
241+
}
242+
243+
if (baudrate)
244+
early_serial_hw_init(115200 / baudrate);
245+
}
246+
247+
#ifdef CONFIG_PCI
210248
/*
211249
* early_pci_serial_init()
212250
*
@@ -351,6 +389,11 @@ static int __init setup_early_printk(char *buf)
351389
keep = (strstr(buf, "keep") != NULL);
352390

353391
while (*buf != '\0') {
392+
if (!strncmp(buf, "mmio", 4)) {
393+
early_mmio_serial_init(buf + 4);
394+
early_console_register(&early_serial_console, keep);
395+
buf += 4;
396+
}
354397
if (!strncmp(buf, "serial", 6)) {
355398
buf += 6;
356399
early_serial_init(buf);

0 commit comments

Comments
 (0)