The branch stable/13 has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=f95a254aa7226160d41768112fd714a5c16bae61

commit f95a254aa7226160d41768112fd714a5c16bae61
Author:     Konstantin Belousov <k...@freebsd.org>
AuthorDate: 2024-03-31 23:30:37 +0000
Commit:     Konstantin Belousov <k...@freebsd.org>
CommitDate: 2024-04-17 08:13:18 +0000

    acpidump: dump AMD IVRS table describing IOMMU layout
    
    (cherry picked from commit 6d789b6126afe1c23b65eef2c5cf4c6bd258c26f)
---
 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 ec7bd65b14c9..d4ab70c9ca86 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)
 {
@@ -2086,6 +2456,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))

Reply via email to