x86: support very early printk() if desired
Adapted from similar code in the x86_64 port. Useful when debugging boot problems on actual x86 hardware if a JTAG isn't handy or feasible. Turn this on for qemu_x86. Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
parent
14db558939
commit
bd709c7322
5 changed files with 83 additions and 0 deletions
|
@ -108,6 +108,17 @@ endif # X86_MULTIBOOT_FRAMEBUF
|
|||
|
||||
endif # X86_MULTIBOOT
|
||||
|
||||
config X86_VERY_EARLY_CONSOLE
|
||||
bool "Support very early boot printk"
|
||||
depends on PRINTK
|
||||
help
|
||||
Non-emulated X86 devices often require special hardware to attach
|
||||
a debugger, which may not be easily available. This option adds a
|
||||
very minimal serial driver which gets initialized at the very
|
||||
beginning of z_cstart(), via kernel_arch_init(). This driver enables
|
||||
printk to emit messages to the 16550 UART port 0 instance in device
|
||||
tree. This mini-driver assumes I/O to the UART is done via ports.
|
||||
|
||||
source "arch/x86/core/Kconfig.ia32"
|
||||
source "arch/x86/core/Kconfig.x64"
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ zephyr_compile_options_ifdef(CONFIG_COVERAGE_GCOV
|
|||
zephyr_library_sources_if_kconfig(pcie.c)
|
||||
zephyr_library_sources_if_kconfig(reboot_rst_cnt.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_X86_MULTIBOOT multiboot.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_X86_VERY_EARLY_CONSOLE early_serial.c)
|
||||
|
||||
if(CONFIG_X86_LONGMODE)
|
||||
include(x64.cmake)
|
||||
|
|
61
arch/x86/core/early_serial.c
Normal file
61
arch/x86/core/early_serial.c
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <generated_dts_board.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <misc/util.h>
|
||||
|
||||
/* Super-primitive 8250/16550 serial output-only driver, 115200 8n1 */
|
||||
|
||||
#define PORT ((io_port_t)DT_UART_NS16550_PORT_0_BASE_ADDR)
|
||||
|
||||
#define REG_IER 0x01 /* Interrupt enable reg. */
|
||||
#define REG_LCR 0x03 /* Line control reg. */
|
||||
#define REG_MCR 0x04 /* Modem control reg. */
|
||||
#define REG_LSR 0x05 /* Line status reg. */
|
||||
#define REG_DL_LO 0x00 /* Divisor latch low byte */
|
||||
#define REG_DL_HI 0x01 /* Divisor latch high byte */
|
||||
|
||||
#define IER_DISABLE 0x00
|
||||
#define LCR_8N1 (BIT(0) | BIT(1))
|
||||
#define LCR_DLAB_SELECT BIT(7)
|
||||
#define MCR_DTR BIT(0)
|
||||
#define MCR_RTS BIT(1)
|
||||
#define LCR_THRE BIT(5)
|
||||
|
||||
static void serout(int c)
|
||||
{
|
||||
while (!(sys_in8(PORT + REG_LSR) & LCR_THRE)) {
|
||||
}
|
||||
sys_out8(c, PORT);
|
||||
}
|
||||
|
||||
static int console_out(int c)
|
||||
{
|
||||
if (c == '\n') {
|
||||
serout('\r');
|
||||
}
|
||||
serout(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
extern void __printk_hook_install(int (*fn)(int));
|
||||
|
||||
void z_x86_early_serial_init(void)
|
||||
{
|
||||
/* In fact Qemu already has most of this set up and works by
|
||||
* default
|
||||
*/
|
||||
sys_out8(IER_DISABLE, PORT + REG_IER); /* Disable interrupts */
|
||||
sys_out8(LCR_DLAB_SELECT, PORT + REG_LCR); /* DLAB select */
|
||||
sys_out8(1, PORT + REG_DL_LO); /* Baud divisor = 1 */
|
||||
sys_out8(0, PORT + REG_DL_HI);
|
||||
sys_out8(LCR_8N1, PORT + REG_LCR); /* LCR = 8n1 + DLAB off */
|
||||
sys_out8(MCR_DTR | MCR_RTS, PORT + REG_MCR);
|
||||
|
||||
/* Will be replaced later when a real serial driver comes up */
|
||||
__printk_hook_install(console_out);
|
||||
}
|
|
@ -23,6 +23,11 @@ extern "C" {
|
|||
|
||||
extern K_THREAD_STACK_DEFINE(_interrupt_stack, CONFIG_ISR_STACK_SIZE);
|
||||
|
||||
#ifdef CONFIG_X86_VERY_EARLY_CONSOLE
|
||||
/* Setup ultra-minimal serial driver for printk() */
|
||||
void z_x86_early_serial_init(void);
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Performs architecture-specific initialization
|
||||
|
@ -38,6 +43,10 @@ static inline void kernel_arch_init(void)
|
|||
_kernel.nested = 0;
|
||||
_kernel.irq_stack = Z_THREAD_STACK_BUFFER(_interrupt_stack) +
|
||||
CONFIG_ISR_STACK_SIZE;
|
||||
|
||||
#ifdef CONFIG_X86_VERY_EARLY_CONSOLE
|
||||
z_x86_early_serial_init();
|
||||
#endif
|
||||
#if CONFIG_X86_STACK_PROTECTION
|
||||
z_x86_mmu_set_flags(&z_x86_kernel_pdpt, _interrupt_stack, MMU_PAGE_SIZE,
|
||||
MMU_ENTRY_NOT_PRESENT, MMU_PTE_P_MASK);
|
||||
|
|
|
@ -18,3 +18,4 @@ CONFIG_X86_MMU=y
|
|||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_SCHED_SCALABLE=y
|
||||
CONFIG_WAITQ_SCALABLE=y
|
||||
CONFIG_X86_VERY_EARLY_CONSOLE=y
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue