From bcd247376633b0fb4f1dbfbf8c2e02d2c926adec Mon Sep 17 00:00:00 2001 From: Shuo Liu Date: Tue, 25 Jun 2024 19:04:11 +0800 Subject: acpi: Add support for DRHD size reporting VT-d spec 4.0 supports size definition for DRHD BAR to support DRHD sizes larger than 4KB. If the value in the field is N, the size of the register set is 2^N 4 KB pages. Some latest OS (e.g. Linux kernel 6.5) will have VTd driver trying to use the beyond 4KB part of the DRHD BAR if they exist. They need the DRHD size field to set up page mapping before access those registers. Re-add acpi_create_dmar_drhd with a size parameter to support the needs. TEST=Build and boot on intel/archercity CRB Change-Id: I49dd5de2eca257a5f6240e36d05755cabca96d1c Signed-off-by: Shuo Liu Signed-off-by: Gang Chen Signed-off-by: Jincheng Li Reviewed-on: https://review.coreboot.org/c/coreboot/+/82429 Reviewed-by: Nico Huber Reviewed-by: Angel Pons Tested-by: build bot (Jenkins) --- src/acpi/acpi_dmar.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'src/acpi/acpi_dmar.c') diff --git a/src/acpi/acpi_dmar.c b/src/acpi/acpi_dmar.c index 20a100d337..67bca5592d 100644 --- a/src/acpi/acpi_dmar.c +++ b/src/acpi/acpi_dmar.c @@ -2,7 +2,9 @@ #include #include +#include #include +#include #include void acpi_create_dmar(acpi_dmar_t *dmar, enum dmar_flags flags, @@ -37,8 +39,23 @@ void acpi_create_dmar(acpi_dmar_t *dmar, enum dmar_flags flags, } unsigned long acpi_create_dmar_drhd_4k(unsigned long current, u8 flags, - u16 segment, u64 bar) + u16 segment, u64 bar) { + return acpi_create_dmar_drhd(current, flags, segment, bar, 4 * KiB); +} + +unsigned long acpi_create_dmar_drhd(unsigned long current, u8 flags, + u16 segment, u64 bar, size_t size) +{ + /* + * Refer to IntelĀ® Virtualization Technology for Directed I/O + * Architecture Specification Revision 4.1, + * size is at least 1 page and max 2^15 pages, 4 KiB each, and the bar + * should be aligned with size. + */ + assert(4 * KiB <= size && size <= (1 << 15) * 4 * KiB && IS_POWER_OF_2(size)); + assert(IS_ALIGNED(bar, size)); + dmar_entry_t *drhd = (dmar_entry_t *)current; memset(drhd, 0, sizeof(*drhd)); drhd->type = DMAR_DRHD; @@ -46,6 +63,7 @@ unsigned long acpi_create_dmar_drhd_4k(unsigned long current, u8 flags, drhd->flags = flags; drhd->segment = segment; drhd->bar = bar; + drhd->size = log2_64(size) - 12; return drhd->length; } -- cgit v1.2.3