Attention is currently required from: Chen, Gang C, Cliff Huang, Jincheng Li, Lance Zhao, Tim Wawrzynczak.
Hello Chen, Gang C, Jincheng Li,
I'd like you to do a code review. Please visit
https://review.coreboot.org/c/coreboot/+/83203?usp=email
to review the following change.
Change subject: acpi: Add support for DRHD size reporting ......................................................................
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: I8749b96325807960a1859a39f6348d227b040970 Signed-off-by: Shuo Liu shuo.liu@intel.com Signed-off-by: Gang Chen gang.c.chen@intel.com Signed-off-by: Jincheng Li jincheng.li@intel.com --- M src/acpi/acpi_dmar.c M src/include/acpi/acpi.h 2 files changed, 23 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/03/83203/1
diff --git a/src/acpi/acpi_dmar.c b/src/acpi/acpi_dmar.c index 20a100d..b5c8efc 100644 --- a/src/acpi/acpi_dmar.c +++ b/src/acpi/acpi_dmar.c @@ -2,7 +2,9 @@
#include <acpi/acpi.h> #include <arch/ioapic.h> +#include <assert.h> #include <cpu/cpu.h> +#include <lib.h> #include <version.h>
void acpi_create_dmar(acpi_dmar_t *dmar, enum dmar_flags flags, @@ -39,6 +41,12 @@ unsigned long acpi_create_dmar_drhd_4k(unsigned long current, u8 flags, u16 segment, u64 bar) { + return acpi_create_dmar_drhd(current, flags, segment, bar, 1); +} + +unsigned long acpi_create_dmar_drhd(unsigned long current, u8 flags, + u16 segment, u64 bar, u32 size) +{ dmar_entry_t *drhd = (dmar_entry_t *)current; memset(drhd, 0, sizeof(*drhd)); drhd->type = DMAR_DRHD; @@ -46,6 +54,18 @@ drhd->flags = flags; drhd->segment = segment; drhd->bar = bar; + drhd->size = log2(size) - 12; + + /* + * Refer to chapter 8.3 of https://cdrdv2.intel.com/v1/dl/getContent/671081 + * max 2^15 pages, 4 KiB each. + */ + assert(size <= (1 << 15) * (4 * KiB)); + /* + * drhd->bar must be aligned according to the size of the register set size + * reported in the drhd->size. + */ + assert(!(drhd->bar & ((1 << (drhd->size + 12)) - 1)));
return drhd->length; } diff --git a/src/include/acpi/acpi.h b/src/include/acpi/acpi.h index 469d672..77c1ec6 100644 --- a/src/include/acpi/acpi.h +++ b/src/include/acpi/acpi.h @@ -638,7 +638,7 @@ u16 type; u16 length; u8 flags; - u8 reserved; + u8 size; u16 segment; u64 bar; } __packed dmar_entry_t; @@ -1851,6 +1851,8 @@ unsigned long (*acpi_fill_dmar)(unsigned long)); unsigned long acpi_create_dmar_drhd_4k(unsigned long current, u8 flags, u16 segment, u64 bar); +unsigned long acpi_create_dmar_drhd(unsigned long current, u8 flags, + u16 segment, u64 bar, u32 size); unsigned long acpi_create_dmar_rmrr(unsigned long current, u16 segment, u64 bar, u64 limit); unsigned long acpi_create_dmar_atsr(unsigned long current, u8 flags,