git: 6d789b6126af - main - acpidump: dump AMD IVRS table describing IOMMU layout
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 05 Apr 2024 15:18:06 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=6d789b6126afe1c23b65eef2c5cf4c6bd258c26f
commit 6d789b6126afe1c23b65eef2c5cf4c6bd258c26f
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2024-03-31 23:30:37 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2024-04-05 15:17:55 +0000
acpidump: dump AMD IVRS table describing IOMMU layout
Reviewed by: markj
Sponsored by: Advanced Micro Devices (AMD)
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D44634
---
usr.sbin/acpi/acpidump/acpi.c | 372 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 372 insertions(+)
diff --git a/usr.sbin/acpi/acpidump/acpi.c b/usr.sbin/acpi/acpidump/acpi.c
index 322fcaed2dc0..e3e426758025 100644
--- a/usr.sbin/acpi/acpidump/acpi.c
+++ b/usr.sbin/acpi/acpidump/acpi.c
@@ -36,6 +36,7 @@
#include <err.h>
#include <fcntl.h>
#include <paths.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
@@ -1496,6 +1497,375 @@ acpi_handle_dmar(ACPI_TABLE_HEADER *sdp)
printf(END_COMMENT);
}
+static void
+acpi_handle_ivrs_ivhd_header(ACPI_IVRS_HEADER *addr)
+{
+ printf("\n\tIVHD Type=%#x IOMMUId=%x\n\tFlags=",
+ addr->Type, addr->DeviceId);
+#define PRINTFLAG(flag, name) printflag(addr->Flags, flag, #name)
+ PRINTFLAG(ACPI_IVHD_TT_ENABLE, HtTunEn);
+ PRINTFLAG(ACPI_IVHD_ISOC, PassPW);
+ PRINTFLAG(ACPI_IVHD_RES_PASS_PW, ResPassPW);
+ PRINTFLAG(ACPI_IVHD_ISOC, Isoc);
+ PRINTFLAG(ACPI_IVHD_TT_ENABLE, IotlbSup);
+ PRINTFLAG((1 << 5), Coherent);
+ PRINTFLAG((1 << 6), PreFSup);
+ PRINTFLAG((1 << 7), PPRSup);
+#undef PRINTFLAG
+ PRINTFLAG_END();
+}
+
+static void
+acpi_handle_ivrs_ivhd_dte(UINT8 dte)
+{
+ if (dte == 0) {
+ printf("\n");
+ return;
+ }
+ printf(" DTE=");
+#define PRINTFLAG(flag, name) printflag(dte, flag, #name)
+ PRINTFLAG(ACPI_IVHD_INIT_PASS, INITPass);
+ PRINTFLAG(ACPI_IVHD_EINT_PASS, EIntPass);
+ PRINTFLAG(ACPI_IVHD_NMI_PASS, NMIPass);
+ PRINTFLAG(ACPI_IVHD_SYSTEM_MGMT, SysMgtPass);
+ PRINTFLAG(ACPI_IVHD_LINT0_PASS, Lint0Pass);
+ PRINTFLAG(ACPI_IVHD_LINT1_PASS, Lint1Pass);
+#undef PRINTFLAG
+ PRINTFLAG_END();
+}
+
+static void
+acpi_handle_ivrs_ivhd_edte(UINT32 edte)
+{
+ if (edte == 0)
+ return;
+ printf("\t\t ExtDTE=");
+#define PRINTFLAG(flag, name) printflag(edte, flag, #name)
+ PRINTFLAG(ACPI_IVHD_ATS_DISABLED, AtsDisabled);
+#undef PRINTFLAG
+ PRINTFLAG_END();
+}
+
+static const char *
+acpi_handle_ivrs_ivhd_variety(UINT8 v)
+{
+ switch (v) {
+ case ACPI_IVHD_IOAPIC:
+ return ("IOAPIC");
+ case ACPI_IVHD_HPET:
+ return ("HPET");
+ default:
+ return ("UNKNOWN");
+ }
+}
+
+static void
+acpi_handle_ivrs_ivhd_devs(ACPI_IVRS_DE_HEADER *d, char *de)
+{
+ char *db;
+ ACPI_IVRS_DEVICE4 *d4;
+ ACPI_IVRS_DEVICE8A *d8a;
+ ACPI_IVRS_DEVICE8B *d8b;
+ ACPI_IVRS_DEVICE8C *d8c;
+ ACPI_IVRS_DEVICE_HID *dh;
+ size_t len;
+ UINT32 x32;
+
+ for (; (char *)d < de; d = (ACPI_IVRS_DE_HEADER *)(db + len)) {
+ db = (char *)d;
+ if (d->Type == ACPI_IVRS_TYPE_PAD4) {
+ len = sizeof(*d4);
+ } else if (d->Type == ACPI_IVRS_TYPE_ALL) {
+ d4 = (ACPI_IVRS_DEVICE4 *)db;
+ len = sizeof(*d4);
+ printf("\t\tDev Type=%#x Id=ALL", d4->Header.Type);
+ acpi_handle_ivrs_ivhd_dte(d4->Header.DataSetting);
+ } else if (d->Type == ACPI_IVRS_TYPE_SELECT) {
+ d4 = (ACPI_IVRS_DEVICE4 *)db;
+ len = sizeof(*d4);
+ printf("\t\tDev Type=%#x Id=%#06x", d4->Header.Type,
+ d4->Header.Id);
+ acpi_handle_ivrs_ivhd_dte(d4->Header.DataSetting);
+ } else if (d->Type == ACPI_IVRS_TYPE_START) {
+ d4 = (ACPI_IVRS_DEVICE4 *)db;
+ len = 2 * sizeof(*d4);
+ printf("\t\tDev Type=%#x Id=%#06x-%#06x",
+ d4->Header.Type,
+ d4->Header.Id, (d4 + 1)->Header.Id);
+ acpi_handle_ivrs_ivhd_dte(d4->Header.DataSetting);
+ } else if (d->Type == ACPI_IVRS_TYPE_END) {
+ d4 = (ACPI_IVRS_DEVICE4 *)db;
+ len = 2 * sizeof(*d4);
+ printf("\t\tDev Type=%#x Id=%#06x BIOS BUG\n",
+ d4->Header.Type, d4->Header.Id);
+ } else if (d->Type == ACPI_IVRS_TYPE_PAD8) {
+ len = sizeof(*d8a);
+ } else if (d->Type == ACPI_IVRS_TYPE_ALIAS_SELECT) {
+ d8a = (ACPI_IVRS_DEVICE8A *)db;
+ len = sizeof(*d8a);
+ printf("\t\tDev Type=%#x Id=%#06x AliasId=%#06x",
+ d8a->Header.Type, d8a->Header.Id, d8a->UsedId);
+ acpi_handle_ivrs_ivhd_dte(d8a->Header.DataSetting);
+ } else if (d->Type == ACPI_IVRS_TYPE_ALIAS_START) {
+ d8a = (ACPI_IVRS_DEVICE8A *)db;
+ d4 = (ACPI_IVRS_DEVICE4 *)(db + sizeof(*d8a));
+ len = sizeof(*d8a) + sizeof(*d4);
+ printf("\t\tDev Type=%#x Id=%#06x-%#06x AliasId=%#06x",
+ d8a->Header.Type, d8a->Header.Id, d4->Header.Id,
+ d8a->UsedId);
+ acpi_handle_ivrs_ivhd_dte(d8a->Header.DataSetting);
+ } else if (d->Type == ACPI_IVRS_TYPE_EXT_SELECT) {
+ d8b = (ACPI_IVRS_DEVICE8B *)db;
+ len = sizeof(*d8b);
+ printf("\t\tDev Type=%#x Id=%#06x",
+ d8a->Header.Type, d8a->Header.Id);
+ acpi_handle_ivrs_ivhd_dte(d8b->Header.DataSetting);
+ printf("\t\t");
+ acpi_handle_ivrs_ivhd_edte(d8b->ExtendedData);
+ } else if (d->Type == ACPI_IVRS_TYPE_EXT_START) {
+ d8b = (ACPI_IVRS_DEVICE8B *)db;
+ len = sizeof(*d8b);
+ d4 = (ACPI_IVRS_DEVICE4 *)(db + sizeof(*d8a));
+ len = sizeof(*d8a) + sizeof(*d4);
+ printf("\t\tDev Type=%#x Id=%#06x-%#06x",
+ d8a->Header.Type, d8a->Header.Id, d4->Header.Id);
+ acpi_handle_ivrs_ivhd_dte(d8b->Header.DataSetting);
+ acpi_handle_ivrs_ivhd_edte(d8b->ExtendedData);
+ } else if (d->Type == ACPI_IVRS_TYPE_SPECIAL) {
+ d8c = (ACPI_IVRS_DEVICE8C *)db;
+ len = sizeof(*d8c);
+ printf("\t\tDev Type=%#x Id=%#06x Handle=%#x "
+ "Variety=%d(%s)",
+ d8c->Header.Type, d8c->UsedId, d8c->Handle,
+ d8c->Variety,
+ acpi_handle_ivrs_ivhd_variety(d8c->Variety));
+ acpi_handle_ivrs_ivhd_dte(d8c->Header.DataSetting);
+ } else if (d->Type == ACPI_IVRS_TYPE_HID) {
+ dh = (ACPI_IVRS_DEVICE_HID *)db;
+ len = sizeof(*dh) + dh->UidLength;
+ printf("\t\tDev Type=%#x Id=%#06x HID=",
+ dh->Header.Type, dh->Header.Id);
+ acpi_print_string((char *)&dh->AcpiHid,
+ sizeof(dh->AcpiHid));
+ printf(" CID=");
+ acpi_print_string((char *)&dh->AcpiCid,
+ sizeof(dh->AcpiCid));
+ printf(" UID=");
+ switch (dh->UidType) {
+ case ACPI_IVRS_UID_NOT_PRESENT:
+ default:
+ printf("none");
+ break;
+ case ACPI_IVRS_UID_IS_INTEGER:
+ memcpy(&x32, dh + 1, sizeof(x32));
+ printf("%#x", x32);
+ break;
+ case ACPI_IVRS_UID_IS_STRING:
+ acpi_print_string((char *)(dh + 1),
+ dh->UidLength);
+ break;
+ }
+ acpi_handle_ivrs_ivhd_dte(dh->Header.DataSetting);
+ } else {
+ printf("\t\tDev Type=%#x Unknown\n", d->Type);
+ if (d->Type <= 63)
+ len = sizeof(*d4);
+ else if (d->Type <= 127)
+ len = sizeof(*d8a);
+ else {
+ printf("Abort, cannot advance iterator.\n");
+ return;
+ }
+ }
+ }
+}
+
+static void
+acpi_handle_ivrs_ivhd_10(ACPI_IVRS_HARDWARE1 *addr, bool efrsup)
+{
+ acpi_handle_ivrs_ivhd_header(&addr->Header);
+ printf("\tCapOffset=%#x Base=%#jx PCISeg=%#x Unit=%#x MSIlog=%d\n",
+ addr->CapabilityOffset, (uintmax_t)addr->BaseAddress,
+ addr->PciSegmentGroup, (addr->Info & ACPI_IVHD_UNIT_ID_MASK) >> 8,
+ addr->Info & ACPI_IVHD_MSI_NUMBER_MASK);
+ if (efrsup) {
+#define PRINTFLAG(flag, name) printflag(addr->FeatureReporting, flag, #name)
+#define PRINTFIELD(lbit, hbit, name) \
+ printfield(addr->FeatureReporting, lbit, hbit, #name)
+ PRINTFIELD(30, 31, HATS);
+ PRINTFIELD(28, 29, GATS);
+ PRINTFIELD(23, 27, MsiNumPPR);
+ PRINTFIELD(17, 22, PNBanks);
+ PRINTFIELD(13, 16, PNCounters);
+ PRINTFIELD(8, 12, PASmax);
+ PRINTFLAG(1 << 7, HESup);
+ PRINTFLAG(1 << 6, GASup);
+ PRINTFLAG(1 << 5, UASup);
+ PRINTFIELD(3, 2, GLXSup);
+ PRINTFLAG(1 << 1, NXSup);
+ PRINTFLAG(1 << 0, XTSup);
+#undef PRINTFLAG
+#undef PRINTFIELD
+ PRINTFLAG_END();
+ }
+ acpi_handle_ivrs_ivhd_devs((ACPI_IVRS_DE_HEADER *)(addr + 1),
+ (char *)addr + addr->Header.Length);
+}
+
+static void
+acpi_handle_ivrs_ivhd_info_11(ACPI_IVRS_HARDWARE2 *addr)
+{
+ acpi_handle_ivrs_ivhd_header(&addr->Header);
+ printf("\tCapOffset=%#x Base=%#jx PCISeg=%#x Unit=%#x MSIlog=%d\n",
+ addr->CapabilityOffset, (uintmax_t)addr->BaseAddress,
+ addr->PciSegmentGroup, (addr->Info >> 8) & 0x1f,
+ addr->Info & 0x5);
+ printf("\tAttr=");
+#define PRINTFIELD(lbit, hbit, name) \
+ printfield(addr->Attributes, lbit, hbit, #name)
+ PRINTFIELD(23, 27, MsiNumPPR);
+ PRINTFIELD(17, 22, PNBanks);
+ PRINTFIELD(13, 16, PNCounters);
+#undef PRINTFIELD
+ PRINTFLAG_END();
+}
+
+static void
+acpi_handle_ivrs_ivhd_11(ACPI_IVRS_HARDWARE2 *addr)
+{
+ acpi_handle_ivrs_ivhd_info_11(addr);
+ printf("\tEFRreg=%#018jx\n", (uintmax_t)addr->EfrRegisterImage);
+ acpi_handle_ivrs_ivhd_devs((ACPI_IVRS_DE_HEADER *)(addr + 1),
+ (char *)addr + addr->Header.Length);
+}
+
+static void
+acpi_handle_ivrs_ivhd_40(ACPI_IVRS_HARDWARE2 *addr)
+{
+ acpi_handle_ivrs_ivhd_info_11(addr);
+ printf("\tEFRreg=%#018jx EFR2reg=%#018jx\n",
+ (uintmax_t)addr->EfrRegisterImage, (uintmax_t)addr->Reserved);
+ acpi_handle_ivrs_ivhd_devs((ACPI_IVRS_DE_HEADER *)(addr + 1),
+ (char *)addr + addr->Header.Length);
+}
+
+static const char *
+acpi_handle_ivrs_ivmd_type(ACPI_IVRS_MEMORY *addr)
+{
+ switch (addr->Header.Type) {
+ case ACPI_IVRS_TYPE_MEMORY1:
+ return ("ALL");
+ case ACPI_IVRS_TYPE_MEMORY2:
+ return ("specified");
+ case ACPI_IVRS_TYPE_MEMORY3:
+ return ("range");
+ default:
+ return ("unknown");
+ }
+}
+
+static void
+acpi_handle_ivrs_ivmd(ACPI_IVRS_MEMORY *addr)
+{
+ printf("\tMem Type=%#x(%s) ",
+ addr->Header.Type, acpi_handle_ivrs_ivmd_type(addr));
+ switch (addr->Header.Type) {
+ case ACPI_IVRS_TYPE_MEMORY2:
+ printf("Id=%#06x PCISeg=%#x ", addr->Header.DeviceId,
+ *(UINT16 *)&addr->Reserved);
+ break;
+ case ACPI_IVRS_TYPE_MEMORY3:
+ printf("Id=%#06x-%#06x PCISeg=%#x", addr->Header.DeviceId,
+ addr->AuxData, *(UINT16 *)&addr->Reserved);
+ break;
+ }
+ printf("Start=%#18jx Length=%#jx Flags=",
+ (uintmax_t)addr->StartAddress, (uintmax_t)addr->MemoryLength);
+#define PRINTFLAG(flag, name) printflag(addr->Header.Flags, flag, #name)
+ PRINTFLAG(ACPI_IVMD_EXCLUSION_RANGE, ExclusionRange);
+ PRINTFLAG(ACPI_IVMD_WRITE, IW);
+ PRINTFLAG(ACPI_IVMD_READ, IR);
+ PRINTFLAG(ACPI_IVMD_UNITY, Unity);
+#undef PRINTFLAG
+ PRINTFLAG_END();
+}
+
+static int
+acpi_handle_ivrs_blocks(void *addr, int remaining, bool efrsup)
+{
+ ACPI_IVRS_HEADER *hdr = addr;
+
+ if (remaining < (int)sizeof(ACPI_IVRS_HEADER))
+ return (-1);
+
+ if (remaining < hdr->Length)
+ return (-1);
+
+ switch (hdr->Type) {
+ case ACPI_IVRS_TYPE_HARDWARE1:
+ acpi_handle_ivrs_ivhd_10(addr, efrsup);
+ break;
+ case ACPI_IVRS_TYPE_HARDWARE2:
+ if (!efrsup)
+ printf("\t!! Found IVHD block 0x11 but !EFRsup\n");
+ acpi_handle_ivrs_ivhd_11(addr);
+ break;
+ case ACPI_IVRS_TYPE_HARDWARE3:
+ if (!efrsup)
+ printf("\t!! Found IVHD block 0x40 but !EFRsup\n");
+ acpi_handle_ivrs_ivhd_40(addr);
+ break;
+ case ACPI_IVRS_TYPE_MEMORY1:
+ case ACPI_IVRS_TYPE_MEMORY2:
+ case ACPI_IVRS_TYPE_MEMORY3:
+ acpi_handle_ivrs_ivmd(addr);
+ break;
+ default:
+ printf("\n");
+ printf("\tType=%d\n", hdr->Type);
+ printf("\tLength=%d\n", hdr->Length);
+ break;
+ }
+ return (hdr->Length);
+}
+
+#define ACPI_IVRS_DMAREMAP 0x00000002
+#define ACPI_IVRS_EFRSUP 0x00000001
+#define ACPI_IVRS_GVA_SIZE 0x000000e0
+
+static void
+acpi_handle_ivrs(ACPI_TABLE_HEADER *sdp)
+{
+ ACPI_TABLE_IVRS *ivrs;
+ char *cp;
+ int remaining, consumed;
+ bool efrsup;
+
+ printf(BEGIN_COMMENT);
+ acpi_print_sdt(sdp);
+ ivrs = (ACPI_TABLE_IVRS *)sdp;
+ efrsup = (ivrs->Info & ACPI_IVRS_EFRSUP) != 0;
+ printf("\tVAsize=%d PAsize=%d GVAsize=%d\n",
+ (ivrs->Info & ACPI_IVRS_VIRTUAL_SIZE) >> 15,
+ (ivrs->Info & ACPI_IVRS_PHYSICAL_SIZE) >> 8,
+ (ivrs->Info & ACPI_IVRS_GVA_SIZE) >> 5);
+ printf("\tATS_resp_res=%d DMA_preboot_remap=%d EFRsup=%d\n",
+ (ivrs->Info & ACPI_IVRS_ATS_RESERVED) != 0,
+ (ivrs->Info & ACPI_IVRS_DMAREMAP) != 0, efrsup);
+
+ remaining = sdp->Length - sizeof(ACPI_TABLE_IVRS);
+ while (remaining > 0) {
+ cp = (char *)sdp + sdp->Length - remaining;
+ consumed = acpi_handle_ivrs_blocks(cp, remaining, efrsup);
+ if (consumed <= 0)
+ break;
+ else
+ remaining -= consumed;
+ }
+
+ printf(END_COMMENT);
+}
+
static void
acpi_print_srat_memory(ACPI_SRAT_MEM_AFFINITY *mp)
{
@@ -2084,6 +2454,8 @@ acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp)
acpi_handle_tcpa(sdp);
else if (!memcmp(sdp->Signature, ACPI_SIG_DMAR, 4))
acpi_handle_dmar(sdp);
+ else if (!memcmp(sdp->Signature, ACPI_SIG_IVRS, 4))
+ acpi_handle_ivrs(sdp);
else if (!memcmp(sdp->Signature, ACPI_SIG_NFIT, 4))
acpi_handle_nfit(sdp);
else if (!memcmp(sdp->Signature, ACPI_SIG_WDDT, 4))