初期カーネルブートログのシリアルレートを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

その結果、何らかの理由でログが2つの部分に分割されます(オシロスコープを使用して確認したこともあります)。

  • 開始ログの最初の部分の速度は3000000です。
  • 開始ログの2番目の部分の速度は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

おすすめ記事