초기 커널 부팅 로그를 위해 직렬 속도를 MMIO UART로 설정할 수 있습니까?

초기 커널 부팅 로그를 위해 직렬 속도를 MMIO UART로 설정할 수 있습니까?

Linux 부팅 로그에 다음과 같이 나타나는 UART가 있습니다.

AMDI0020:01: ttyS5 at MMIO 0xfedca000 (irq = 4, base_baud = 3000000) is a 16550A

이 UART 포트에 대해 Linux 커널 부팅 로깅을 활성화하고 싶습니다. 이를 위해 커널 부팅 매개변수를 추가합니다.

console=uart,mmio32,0xfedca000,115200n8

결과적으로 어떤 이유로 로그가 두 부분으로 분할됩니다(오실로스코프를 사용하여 확인하기도 했습니다).

  • 시작 로그의 첫 번째 부분의 속도는 3000000입니다.
  • 시작 로그의 두 번째 부분의 속도는 115200입니다.

아마도 분할은 ttyS5가 초기화될 때 바로 발생합니다.

나는 글쓰기가 전부라고 생각한다.

console=uart,mmio32,0xfedca000,115200n8

바꾸다

console=ttyS5,115200n8

실제 드라이버 초기화 전에 작동하는 UART를 얻는 것입니다.

하지만 어떤 이유에서인지 uart,mmio32,0xfedca000,115200n8매개변수는 애초에 속도를 설정하지 않습니다.

초기 커널 부팅 로그를 위해 직렬 속도를 MMIO UART로 설정할 수 있습니까?

내 OS가 다음과 같은 경우를 대비해

~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.4 LTS
Release:        18.04
Codename:       bionic
~$ uname -a
Linux ermak-Diesel 5.4.0-65-generic #73~18.04.1-Ubuntu SMP Tue Jan 19 09:02:24 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

답변1

제 경우에는 비표준 UART 시계로 인해 문제가 발생했습니다.

earlycon드라이버는 UART 클록을 이 값으로 설정합니다.BASE_BAUD * 16

https://github.com/torvalds/linux/blob/2a987e65025e2b79c6d453b78cb5985ac6e5eb26/drivers/tty/serial/earlycon.c#L142

static int __init register_earlycon(char *buf, const struct earlycon_id *match)
{
 ...
 port->uartclk = BASE_BAUD * 16;
 ...
}

x86의 경우 아치가 BASE_BAUD 파일에 정의되어 있습니다.https://github.com/torvalds/linux/blob/master/arch/x86/include/asm/serial.h

/*
 * This assumes you have a 1.8432 MHz clock for your UART.
 *
 * It'd be nice if someone built a serial card with a 24.576 MHz
 * clock, since the 16550A is capable of handling a top speed of 1.5
 * megabits/second; but this requires a faster clock.
 */
#define BASE_BAUD (1843200/16)

하지만 제 경우에는 AMDI0020UART가 표준 1.8432MHz 클럭을 사용하지 않고 48MHz 클럭을 사용합니다.

이것이 base_baud = 3000000인쇄가 표준 115200에 위배되는 이유입니다.

 1 843 200 / 16 =   115 200
48 000 000 / 16 = 3 000 000
AMDI0020:01: ttyS5 at MMIO 0xfedca000 (irq = 4, base_baud = 3000000) is a 16550A

드라이버에서 다른 시계를 설정할 가능성이 없습니다. 하지만 다른 느린 전송 속도를 설정하여 속일 수 있습니다.

115 200 * (1 843 200 / 48 000 000) = 4 423,68

이 설정은 초기 부팅 단계에서 올바른 출력을 제공했습니다.

console=uart,mmio32,0xfedca000,4423

하지만 이 접근 방식은 이상적이지 않습니다. 잘못된 전송 속도로 인해 후속 커널 부팅 단계가 올바르게 인쇄되지 않기 때문입니다( AMDI0020드라이버가 인계되면(https://github.com/torvalds/linux/blob/master/drivers/tty/serial/8250/8250_dw.c)).

BIOS/GRUB 단계에서 UART가 올바른 속도로 설정된 경우 전송 속도 설정을 생략할 수 있습니다.

console=uart,mmio32,0xfedca000

이렇게 하면 모든 커널 로그가 올바르게 인쇄됩니다.

그러나 올바른 해결책은 물론 earlycon드라이버에 필요한 지원을 추가하는 것입니다.

현재 AMDI0020이 드라이버에서 시계를 가져오는 중:https://github.com/torvalds/linux/blob/master/drivers/acpi/acpi_apd.c

static const struct apd_device_desc cz_uart_desc = {
    .setup = acpi_apd_setup,
    .fixed_clk_rate = 48000000,
    .properties = uart_properties,
};

...

static const struct acpi_device_id acpi_apd_device_ids[] = {
  ...
  { "AMDI0020", APD_ADDR(cz_uart_desc) },
  ...
}

ACPI가 구문 분석되기 전에 설정 되므로 earlycon문제를 해결하는 유일한 방법은 다음과 같이 콘솔에 대한 사용자 정의 시계를 전달할 가능성을 추가하는 것 같습니다.

console=uart,mmio32,0xfedca000,115200,48000000

관련 정보