[PATCH] iommu: Refine VT-d RMRR region check for BIOS reservation

From: NOMURA JUNICHI(野村 淳一)
Date: Thu Feb 27 2020 - 03:27:19 EST


arch_rmrr_sanity_check() was introduced by commit f036c7fa0ab6 ("iommu/vt-d:
Check VT-d RMRR region in BIOS is reported as reserved") to detect RMRR
pointing to the area that might be used by OS as free memory. However the
check was based on E820_TYPE_RESERVED coverage and raised false alarms if
BIOS reported the area as other reservation types.

Example of warning looks like this:

DMAR: [Firmware Bug]: No firmware reserved region can cover this RMRR [0x00000000a2290000-0x00000000a2292fff], contact BIOS vendor for fixes
------------[ cut here ]------------
Your BIOS is broken; bad RMRR [0x00000000a2290000-0x00000000a2292fff]
WARNING: CPU: 0 PID: 0 at drivers/iommu/intel-iommu.c:4470 dmar_parse_one_rmrr+0x9a/0x14f
CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.6.0-rc3-00069-g91ad64a #1
RIP: 0010:dmar_parse_one_rmrr+0x9a/0x14f
Code: 00 48 89 c3 e8 f0 a0 03 ff 49 8b 54 24 10 49 8b 74 24 08 48 89 c1 4d 89 e9 49 89 d8 48 c7 c7 10 18 76 a1 31 c0 e8 2f f9 9d fe <0f> 0b 48 8b 3d 46 c4 af ff ba 38 00 00 00 be c0 0d 00 00 e8 67 6a
RSP: 0000:ffffffffa1a03d68 EFLAGS: 00010286
RAX: 0000000000000000 RBX: ffffffffa2400004 RCX: ffffffffa1a67708
RDX: 0000000000000001 RSI: 0000000000000082 RDI: 0000000000000246
RBP: ffffffffa1a03d80 R08: 000000000000020d R09: 000000000000020d
R10: 50203b313355203a R11: 726556203b43454e R12: ffffad5f00042180
R13: ffffffffa14f9258 R14: ffffffffa1a03dc8 R15: ffff9f39fffc0bc0
FS: 0000000000000000(0000) GS:ffff9f219f600000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: ffff9f39ffdff000 CR3: 000000279f40a001 CR4: 00000000000606b0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
dmar_walk_remapping_entries+0xa1/0x1e0
dmar_table_init+0xda/0x16c
intel_prepare_irq_remapping+0x3e/0x244
irq_remapping_prepare+0x1b/0x6d
enable_IR_x2apic+0x2d/0x16e
default_setup_apic_routing+0x16/0x75
apic_intr_mode_init+0xe7/0x10c
x86_late_time_init+0x24/0x2b
start_kernel+0x5a7/0x66b
x86_64_start_reservations+0x24/0x26
x86_64_start_kernel+0x8a/0x8d
secondary_startup_64+0xb6/0xc0
---[ end trace b61aef72ecd09def ]---

In this case, though, 0x00000000a2290000-0x00000000a2292fff is inside the
area reported as ACPI NVS by BIOS and won't be used as free memory pool:

BIOS-e820: [mem 0x00000000a067a000-0x00000000a2a79fff] ACPI NVS

Refine the check to detect if any part of the area is reported by BIOS
as OS-usable region.

Fixes: f036c7fa0ab60 ("iommu/vt-d: Check VT-d RMRR region in BIOS is reported as reserved")
Signed-off-by: Jun'ichi Nomura <junichi.nomura@xxxxxxx>
Cc: Yian Chen <yian.chen@xxxxxxxxx>
Cc: Joerg Roedel <jroedel@xxxxxxx>

diff --git a/arch/x86/include/asm/iommu.h b/arch/x86/include/asm/iommu.h
index bf1ed2d..5629ff2e 100644
--- a/arch/x86/include/asm/iommu.h
+++ b/arch/x86/include/asm/iommu.h
@@ -18,12 +18,15 @@
u64 start = rmrr->base_address;
u64 end = rmrr->end_address + 1;

- if (e820__mapped_all(start, end, E820_TYPE_RESERVED))
- return 0;
+ if (e820__mapped_any(start, end, E820_TYPE_RAM) ||
+ e820__mapped_any(start, end, E820_TYPE_RESERVED_KERN)) {
+ pr_err(FW_BUG "OS usable region overwraps with this RMRR [%#018Lx-%#018Lx], contact BIOS vendor for fixes\n",
+ start, end - 1);
+ return -EINVAL;
+ }
+
+ 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;
}

#endif /* _ASM_X86_IOMMU_H */