意外删除 EFI 分区后出现“没有固件保留区域可以覆盖此 RMRR”

意外删除 EFI 分区后出现“没有固件保留区域可以覆盖此 RMRR”

我曾经双启动 Windows 和 Debian Linux,后来决定删除 Windows。在此过程中,我还意外删除了 EFI 分区,我设法修复了这个问题,但现在每次启动 Linux 时,以下消息都会在屏幕上停留 10 秒钟,然后才能继续启动:(复制自journalctl -b

DMAR: [Firmware Bug]: No firmware reserved region can cover this RMRR [0x00000000c9000000-0x00000000cb7fffff], contact BIOS vendor for fixes
DMAR: [Firmware Bug]: Your BIOS is broken; bad RMRR [0x00000000c9000000-0x00000000cb7fffff]
BIOS vendor: FUJITSU // Insyde Software Corp.; Ver: Version 1.22; Product Version: 10601736746

经过一番谷歌搜索后,我认为这个错误既无法修复又不重要,但如果是这样的话,我希望有一种方法来隐藏它。

更多系统信息:

OS: Debian GNU/Linux 11 (bullseye) x86_64
Host: LIFEBOOK E756 10601736746 
Kernel: 5.10.0-13-amd64 

编辑:查看dmesg与错误消息中的内存区域重叠的内存区域的输出后,我发现了这一点:

[    0.022014] Reserving Intel graphics memory at [mem 0xc9800000-0xcb7fffff]

编辑2:这是dmesg日志。

答案1

使用运行带内核的 AlmaLinux 8.7 的 HP Z4 G44.18.0-425.3.1.el8.x86_64在 dmesg 中看到以下错误:

[    0.001029] DMAR: RMRR base: 0x0000006c30a000 end: 0x0000006c30cfff
[    0.001030] DMAR: [Firmware Bug]: No firmware reserved region can cover this RMRR [0x000000006c30a000-0x000000006c30cfff], contact BIOS vendor for fixes
[    0.001035] DMAR: [Firmware Bug]: Your BIOS is broken; bad RMRR [0x000000006c30a000-0x000000006c30cfff]
               BIOS vendor: HP; Ver: P61 v02.86; Product Version: 

BIOS 版本是 HP 的最新版本,发布时间不到一个月。也就是说,在这种情况下,无需尝试 BIOS 更新。

经调查发现,固件错误的报告导致内核受到污染:

$ cat /proc/sys/kernel/tainted 
2048
$  ~/Downloads/kernel-chktaint 
Kernel is "tainted" for the following reasons:
 * workaround for bug in platform firmware applied (#11)
For a more detailed explanation of the various taint flags see
 Documentation/admin-guide/tainted-kernels.rst in the Linux kernel sources
 or https://kernel.org/doc/html/latest/admin-guide/tainted-kernels.html
Raw taint value as int/string: 2048/'G        

arch/x86/include/asm/iommu.h内核源文件中报告了以下固件错误:

static inline int __init
arch_rmrr_sanity_check(struct acpi_dmar_reserved_memory *rmrr)
{
    u64 start = rmrr->base_address;
    u64 end = rmrr->end_address + 1;

    if (e820__mapped_all(start, end, E820_TYPE_RESERVED))
        return 0;

    pr_err(FW_BUG "No firmware reserved region can cover this RMRR [%#018Lx-%#018Lx], contact BIOS vendor for fixes\n",
           start, end - 1);
    return -EINVAL;
}

dmar_parse_one_rmrr中的函数drivers/iommu/intel/iommu.c调用arch_rmrr_sanity_check

    if (rmrr_sanity_check(rmrr)) {
        pr_warn(FW_BUG
               "Your BIOS is broken; bad RMRR [%#018Lx-%#018Lx]\n"
               "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
               rmrr->base_address, rmrr->end_address,
               dmi_get_system_info(DMI_BIOS_VENDOR),
               dmi_get_system_info(DMI_BIOS_VERSION),
               dmi_get_system_info(DMI_PRODUCT_VERSION));
        add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
    }

arch_rmrr_sanity_check失败解释了No firmware reserved region can cover this RMRRYour BIOS is broken; bad RMRR消息以及内核被污染了。

dmesg 显示 BIOS 提供的物理 RAM 映射如下:

[    0.000000] BIOS-provided physical RAM map:
[    0.000000] BIOS-e820: [mem 0x0000000000000000-0x0000000000087fff] usable
[    0.000000] BIOS-e820: [mem 0x0000000000088000-0x0000000000088fff] reserved
[    0.000000] BIOS-e820: [mem 0x0000000000089000-0x000000000009dfff] usable
[    0.000000] BIOS-e820: [mem 0x000000000009e000-0x00000000000fffff] reserved
[    0.000000] BIOS-e820: [mem 0x0000000000100000-0x000000006bc6ffff] usable
[    0.000000] BIOS-e820: [mem 0x000000006bc70000-0x000000006c143fff] reserved
[    0.000000] BIOS-e820: [mem 0x000000006c144000-0x000000006cb76fff] ACPI NVS
[    0.000000] BIOS-e820: [mem 0x000000006cb77000-0x000000006cc52fff] ACPI data
[    0.000000] BIOS-e820: [mem 0x000000006cc53000-0x000000006fffffff] usable
[    0.000000] BIOS-e820: [mem 0x0000000070000000-0x000000008fffffff] reserved
[    0.000000] BIOS-e820: [mem 0x00000000fe010000-0x00000000fe010fff] reserved
[    0.000000] BIOS-e820: [mem 0x00000000ff000000-0x00000000ffffffff] reserved
[    0.000000] BIOS-e820: [mem 0x0000000100000000-0x000000047fffffff] usable

BIOS 内存映射中的区域与ACPI NVSRMRR 重叠。

如上所述,如果 BIOS 提供的物理 RAM 映射未将 RMRR 的内存区域标记为保留,则内核arch_rmrr_sanity_check中的函数4.18.0-425.3.1.el8.x86_64会导致报告固件错误。发现iommu/vt-d:允许 arch_rmrr_sanity_check() 中的 NVS 区域提交修改 arch_rmrr_sanity_check 函数,以允许将 RMRR 区域标记为预订的或者ACPI 网络接口控制器在 BIOS 提供的物理 RAM 映射中。尚未检查提交出现在哪个主线内核版本中,也未检查该版本是否已被 RHEL 反向移植。

作为一种解决方法,在启动时将其memmap=10444K%0x6c144000-4+2添加到命令行。这样做的目的是在启动初期将 ACPI NVS 区域的类型从E820_TYPE_NVS(4) 更改为E820_TYPE_RESERVED(2),因此到调用时,arch_rmrr_sanity_checkRMRR 内存区域被视为保留,并且健全性检查通过。

所用选项的语法memmap来自内核参数.txt

    memmap=<size>%<offset>-<oldtype>+<newtype>
            [KNL,ACPI] Convert memory within the specified region
            from <oldtype> to <newtype>. If "-<oldtype>" is left
            out, the whole region will be marked as <newtype>,
            even if previously unavailable. If "+<newtype>" is left
            out, matching memory will be removed. Types are
            specified as e820 types, e.g., 1 = RAM, 2 = reserved,
            3 = ACPI, 12 = PRAM.

在哪里:

  • 10444K是从 dmesg 输出的条目中<size>获取的ACPI NVSBIOS-provided physical RAM map
  • 0x6c144000是从 dmesg 输出的条目开始<offset>ACPI NVSBIOS-provided physical RAM map
  • -4是内核源代码中的<oldtype>E820_TYPE_NVS
  • +2是内核源代码中的<newtype>E820_TYPE_RESERVED

结果,No firmware reserved region can cover this RMRRYour BIOS is broken; bad RMRR消息不再被报告,并且内核不再被污染:

$ ~/Downloads/kernel-chktaint 
Kernel not Tainted

最初通过停止 grub 并编辑命令行来临时测试更改。当此方法有效时,通过使用grubby编辑命令行使更改永久生效:

$ sudo grubby --update-kernel=DEFAULT --args=memmap=10444K%0x6c144000-4+2

虽然上述添加memmap=10444K%0x6c144000特定于特定型号的 PC/BIOS,但希望它能提供一些有关如何抑制固件错误消息的指导。

上述分析还发现arch_rmrr_sanity_check内核源代码中对该函数的提交应该可以避免这种解决方法,而无需更改 BIOS。不确定内核更改何时会进入不同的发行版。

更新:使用内核的 AlmaLinux 8.9 更新后,4.18.0-513.5.1.el8_9.x86_64不再需要应用解决方法。即,当BIOS 报告的位于某个区域内memmap时,较新的内核不再报告固件错误。在RMRRACPI NVS内核更新已删除固件错误报告确认 BIOS 的行为没有改变。

相关内容