pl011
AMBA 是片上总线架构,PL011 是具体的 UART 控制器。
为什么 arm 虚拟机不需要配置console=ttyAMA0 默认就有输出
固件提供的 ACPI SPCR 表指定了串口 console,因此不需要显式配置 console=ttyAMA0。
guest 内核是 6.14.0-63.fc42.aarch64,启动日志明确记录:
ACPI: SPCR: console: pl011,mmio32,0x9000000,9600
ACPI: Use ACPI SPCR as default console: Yes
ARMH0011:00: ttyAMA0 at MMIO 0x9000000 ...
printk: legacy console [ttyAMA0] enabled
/proc/consoles 和 /sys/class/tty/console/active 也确认当前 console 是 ttyAMA0。对应源码路径是:
-
arch/arm64/kernel/acpi.c 中的 acpi_boot_table_init() 默认启用 SPCR console。源码 (https://github.com/torvalds/linux/blob/v6.14/arch/arm64/kernel/acpi.c)
-
drivers/acpi/spcr.c 中的 acpi_parse_spcr() 读取串口类型、地址和波特率,通过 add_preferred_console() 添加 console。源码 (https://github.com/torvalds/linux/blob/v6.14/drivers/acpi/spcr.c)
-
PL011 驱动的 pl011_console_match() 按地址 0x9000000 匹配到 ttyAMA0。源码 (https://github.com/torvalds/linux/blob/v6.14/drivers/tty/serial/amba-pl011.c)
PL011 注册时匹配不上这个名字,register_console() 会继续尝试平台默认配置,于是匹配到了 SPCR 指定的串口。源码中的 register_console() (https://github.com/torvalds/linux/blob/v6.14/kernel/printk/printk.c)
基本初始化的过程
drivers/tty/serial/amba-pl010.c
static struct console amba_console = {
.name = "ttyAMA",
.device = uart_console_device,
.setup = pl011_console_setup,
.match = pl011_console_match,
.write_atomic = pl011_console_write_atomic,
.write_thread = pl011_console_write_thread,
.device_lock = pl011_console_device_lock,
.device_unlock = pl011_console_device_unlock,
.flags = CON_PRINTBUFFER | CON_ANYTIME | CON_NBCON,
.index = -1,
.data = &amba_reg,
};
sbsa_uart_probe() → pl011_register_port() → uart_add_one_port() → serial_ctrl_register_port() → serial_core_register_port() → serial_core_add_one_port() → uart_configure_port() → register_console(port->cons)
drivers/tty/serial/8250/8250_core.c
static struct console univ8250_console = {
.name = "ttyS",
.write = univ8250_console_write,
.device = uart_console_device,
.setup = univ8250_console_setup,
.exit = univ8250_console_exit,
.match = univ8250_console_match,
.flags = CON_PRINTBUFFER | CON_ANYTIME,
.index = -1,
.data = &serial8250_reg,
};
static int __init univ8250_console_init(void)
{
if (nr_uarts == 0)
return -ENODEV;
serial8250_isa_init_ports();
register_console(&univ8250_console);
return 0;
}
console_initcall(univ8250_console_init);
本站所有文章转发 CSDN 将按侵权追究法律责任,其它情况随意。