Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/kexec: Add 8250 MMIO serial port output

This supports the same 32-bit MMIO-mapped 8250 as the early_printk code.

It's not clear why the early_printk code supports this form and only this
form; the actual runtime 8250_pci doesn't seem to support it. But having
hacked up QEMU to expose such a device, early_printk does work with it,
and now so does the kexec debug code.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20250326142404.256980-3-dwmw2@infradead.org

authored by

David Woodhouse and committed by
Ingo Molnar
7516e721 d358b451

+43
+1
arch/x86/include/asm/kexec.h
··· 65 65 extern gate_desc kexec_debug_idt[]; 66 66 extern unsigned char kexec_debug_exc_vectors[]; 67 67 extern uint16_t kexec_debug_8250_port; 68 + extern unsigned long kexec_debug_8250_mmio32; 68 69 #endif 69 70 70 71 /*
+3
arch/x86/kernel/early_printk.c
··· 333 333 /* WARNING! assuming the address is always in the first 4G */ 334 334 early_serial_base = 335 335 (unsigned long)early_ioremap(bar0 & PCI_BASE_ADDRESS_MEM_MASK, 0x10); 336 + #if defined(CONFIG_KEXEC_CORE) && defined(CONFIG_X86_64) 337 + kexec_debug_8250_mmio32 = bar0 & PCI_BASE_ADDRESS_MEM_MASK; 338 + #endif 336 339 write_pci_config(bus, slot, func, PCI_COMMAND, 337 340 cmdreg|PCI_COMMAND_MEMORY); 338 341 }
+17
arch/x86/kernel/machine_kexec_64.c
··· 76 76 static int map_acpi_tables(struct x86_mapping_info *info, pgd_t *level4p) { return 0; } 77 77 #endif 78 78 79 + static int map_mmio_serial(struct x86_mapping_info *info, pgd_t *level4p) 80 + { 81 + unsigned long mstart, mend; 82 + 83 + if (!kexec_debug_8250_mmio32) 84 + return 0; 85 + 86 + mstart = kexec_debug_8250_mmio32 & PAGE_MASK; 87 + mend = (kexec_debug_8250_mmio32 + PAGE_SIZE + 23) & PAGE_MASK; 88 + pr_info("Map PCI serial at %lx - %lx\n", mstart, mend); 89 + return kernel_ident_mapping_init(info, level4p, mstart, mend); 90 + } 91 + 79 92 #ifdef CONFIG_KEXEC_FILE 80 93 const struct kexec_file_ops * const kexec_file_loaders[] = { 81 94 &kexec_bzImage64_ops, ··· 295 282 return result; 296 283 297 284 result = map_acpi_tables(&info, image->arch.pgd); 285 + if (result) 286 + return result; 287 + 288 + result = map_mmio_serial(&info, image->arch.pgd); 298 289 if (result) 299 290 return result; 300 291
+22
arch/x86/kernel/relocate_kernel_64.S
··· 39 39 SYM_DATA(kexec_pa_table_page, .quad 0) 40 40 SYM_DATA(kexec_pa_swap_page, .quad 0) 41 41 SYM_DATA_LOCAL(pa_backup_pages_map, .quad 0) 42 + SYM_DATA(kexec_debug_8250_mmio32, .quad 0) 42 43 SYM_DATA(kexec_debug_8250_port, .word 0) 43 44 44 45 .balign 16 ··· 414 413 ret 415 414 SYM_CODE_END(pr_char_8250) 416 415 416 + SYM_CODE_START_LOCAL_NOALIGN(pr_char_8250_mmio32) 417 + UNWIND_HINT_FUNC 418 + ANNOTATE_NOENDBR 419 + .Lxmtrdy_loop_mmio: 420 + movb (LSR*4)(%rdx), %ah 421 + testb $XMTRDY, %ah 422 + jnz .Lready_mmio 423 + rep nop 424 + jmp .Lxmtrdy_loop_mmio 425 + 426 + .Lready_mmio: 427 + movb %al, (%rdx) 428 + ANNOTATE_UNRET_SAFE 429 + ret 430 + SYM_CODE_END(pr_char_8250_mmio32) 431 + 417 432 /* 418 433 * Load pr_char function pointer into %rsi and load %rdx with whatever 419 434 * that function wants to see there (typically port/MMIO address). ··· 438 421 leaq pr_char_8250(%rip), %rsi 439 422 movw kexec_debug_8250_port(%rip), %dx 440 423 testw %dx, %dx 424 + jnz 1f 425 + 426 + leaq pr_char_8250_mmio32(%rip), %rsi 427 + movq kexec_debug_8250_mmio32(%rip), %rdx 428 + testq %rdx, %rdx 441 429 jnz 1f 442 430 443 431 leaq pr_char_null(%rip), %rsi