On Thursday, March 13th, 2025 at 5:04 PM, Randy Dunlap <rdunlap@xxxxxxxxxxxxx> wrote: > > > Hi, > > On 3/13/25 4:45 PM, Denis Mukhin via B4 Relay wrote: > > > From: Denis Mukhin dmukhin@xxxxxxxx > > > > 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. > > > > It was discovered that 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 > > > > Signed-off-by: Denis Mukhin dmukhin@xxxxxxxx > > --- > > Documentation/admin-guide/kernel-parameters.txt | 4 +++ > > arch/x86/kernel/early_printk.c | 45 ++++++++++++++++++++++++- > > 2 files changed, 48 insertions(+), 1 deletion(-) > > > > diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt > > index fb8752b42ec8582b8750d7e014c4d76166fa2fc1..bee9ee18a506d019dc3d330268e3e1c83434ebba 100644 > > --- a/Documentation/admin-guide/kernel-parameters.txt > > +++ b/Documentation/admin-guide/kernel-parameters.txt > > @@ -1414,11 +1414,15 @@ > > earlyprintk=pciserial[,force],bus:device.function[,baudrate] > > earlyprintk=xdbc[xhciController#] > > earlyprintk=bios > > + earlyprintk=mmio,membase[,{nocfg|baudrate}][,keep] > > > > earlyprintk is useful when the kernel crashes before > > the normal console is initialized. It is not enabled by > > default because it has some cosmetic problems. > > > > + Use "nocfg" to skip UART configuration, assume > > + BIOS/firmware has configured UART correctly. > > + > > Append ",keep" to not disable it when the real console > > takes over. > > > > diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c > > index 44f937015e1e25bf41532eb7e1031a6be32a6523..19248c73b5b0950e9edf1a60ba67829f1cd3279e 100644 > > --- a/arch/x86/kernel/early_printk.c > > +++ b/arch/x86/kernel/early_printk.c > > @@ -191,7 +191,6 @@ static __init void early_serial_init(char *s) > > early_serial_hw_init(divisor); > > } > > > > -#ifdef CONFIG_PCI > > static void mem32_serial_out(unsigned long addr, int offset, int value) > > { > > u32 __iomem *vaddr = (u32 __iomem *)addr; > > @@ -206,6 +205,45 @@ static unsigned int mem32_serial_in(unsigned long addr, int offset) > > return readl(vaddr + offset); > > } > > > > +/* > > + * early_mmio_serial_init() - Initialize MMIO-based early serial console. > > + * @membase: UART base address. > > + * @nocfg: Skip configuration, assume BIOS has configured UART correctly. > > + * @baudrate (int): Baud rate. > > > Looks like unsigned long to me. > > > + * @keep: Keep after the real driver is available. > > > These 4 "parameters" are not the function arguments. > @s is the function argument. > > You could say in a comment that @s is scanned to obtain > these 4 parameters or something like that. Sorry, I messed the description. These 4 parameters meant to describe the arguments of the string to parse: membase[,{nocfg|baudrate}][,keep] I will update. Thanks! > > > + */ > > +static __init void early_mmio_serial_init(char *s) > > +{ > > + unsigned long baudrate; > > + unsigned long membase; > > + char *e; > > + > > + if (*s == ',') > > + s++; > > + > > + if (!strncmp(s, "0x", 2)) { > > + membase = simple_strtoul(s, &e, 16); > > + early_serial_base = (unsigned long)early_ioremap(membase, PAGE_SIZE); > > + serial_in = mem32_serial_in; > > + serial_out = mem32_serial_out; > > + > > + s += strcspn(s, ","); > > + if (s == ',') > > + s++; > > + } > > + > > + if (!strncmp(s, "nocfg", 5)) > > + baudrate = 0; > > + else { > > + baudrate = simple_strtoul(s, &e, 0); > > + if (baudrate == 0 || s == e) > > + baudrate = DEFAULT_BAUD; > > + } > > + if (baudrate) > > + early_serial_hw_init(115200 / baudrate); > > +} > > + > > +#ifdef CONFIG_PCI > > / > > * early_pci_serial_init() > > * > > @@ -352,6 +390,11 @@ static int __init setup_early_printk(char *buf) > > keep = (strstr(buf, "keep") != NULL); > > > > while (*buf != '\0') { > > + if (!strncmp(buf, "mmio", 4)) { > > + early_mmio_serial_init(buf + 4); > > + early_console_register(&early_serial_console, keep); > > + buf += 4; > > + } > > if (!strncmp(buf, "serial", 6)) { > > buf += 6; > > early_serial_init(buf); > > > > --- > > > > -- > ~Randy