Module Name: src Committed By: msaitoh Date: Sun Dec 2 10:51:07 UTC 2018
Modified Files: src/usr.sbin/acpitools/acpidump: acpi.c acpidump.8 Log Message: Decode IO Remapping Table. To generate a diff of this commit: cvs rdiff -u -r1.41 -r1.42 src/usr.sbin/acpitools/acpidump/acpi.c cvs rdiff -u -r1.14 -r1.15 src/usr.sbin/acpitools/acpidump/acpidump.8 Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.sbin/acpitools/acpidump/acpi.c diff -u src/usr.sbin/acpitools/acpidump/acpi.c:1.41 src/usr.sbin/acpitools/acpidump/acpi.c:1.42 --- src/usr.sbin/acpitools/acpidump/acpi.c:1.41 Sun Nov 11 00:24:01 2018 +++ src/usr.sbin/acpitools/acpidump/acpi.c Sun Dec 2 10:51:07 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: acpi.c,v 1.41 2018/11/11 00:24:01 maya Exp $ */ +/* $NetBSD: acpi.c,v 1.42 2018/12/02 10:51:07 msaitoh Exp $ */ /*- * Copyright (c) 1998 Doug Rabson @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: acpi.c,v 1.41 2018/11/11 00:24:01 maya Exp $"); +__RCSID("$NetBSD: acpi.c,v 1.42 2018/12/02 10:51:07 msaitoh Exp $"); #include <sys/param.h> #include <sys/endian.h> @@ -96,6 +96,7 @@ static void acpi_handle_einj(ACPI_TABLE_ static void acpi_handle_erst(ACPI_TABLE_HEADER *sdp); static void acpi_handle_gtdt(ACPI_TABLE_HEADER *sdp); static void acpi_handle_hest(ACPI_TABLE_HEADER *sdp); +static void acpi_handle_iort(ACPI_TABLE_HEADER *sdp); static void acpi_handle_lpit(ACPI_TABLE_HEADER *sdp); static void acpi_handle_madt(ACPI_TABLE_HEADER *sdp); static void acpi_handle_msct(ACPI_TABLE_HEADER *sdp); @@ -2063,6 +2064,320 @@ acpi_handle_hpet(ACPI_TABLE_HEADER *sdp) printf(END_COMMENT); } +/* + * IORT + * I/O Remapping Table + */ + +static void acpi_print_iort_its_group(ACPI_IORT_NODE *); +static void acpi_print_iort_named_component(ACPI_IORT_NODE *); +static void acpi_print_iort_root_complex(ACPI_IORT_NODE *); +static void acpi_print_iort_smmuv1v2(ACPI_IORT_NODE *); +static void acpi_print_iort_smmuv3(ACPI_IORT_NODE *); + +struct iort_node_list { + uint8_t Type; + const char *gname; + void (*func)(ACPI_IORT_NODE *); +} iort_node_list [] = { +#define NDMAC(name) ACPI_IORT_NODE_## name +#define PRFN(name) acpi_print_iort_## name + { NDMAC(ITS_GROUP), "ITS group", PRFN(its_group)}, + { NDMAC(NAMED_COMPONENT), "Named component", PRFN(named_component)}, + { NDMAC(PCI_ROOT_COMPLEX), "Root complex", PRFN(root_complex)}, + { NDMAC(SMMU), "SMMUv1 or v2", PRFN(smmuv1v2)}, + { NDMAC(SMMU_V3), "SMMUv3", PRFN(smmuv3)}, + { 255, NULL, NULL}, +#undef NDMAC +#undef PRFN +}; + +static void +acpi_print_iort_memory_access(ACPI_IORT_MEMORY_ACCESS *memacc) +{ + + printf("\tMemory Access={\n"); + printf("\t\tCacheCoherency="); + switch (memacc->CacheCoherency) { + case ACPI_IORT_NODE_COHERENT: + printf("Fully coherent\n"); + break; + case ACPI_IORT_NODE_NOT_COHERENT: + printf("Not coherent\n"); + break; + default: + printf("resrved (%u)\n", memacc->CacheCoherency); + break; + } + printf("\t\tAllocation Hints="); +#define PRINTFLAG(var, flag) printflag((var), ACPI_IORT_HT_## flag, #flag) + PRINTFLAG(memacc->Hints, TRANSIENT); + PRINTFLAG(memacc->Hints, WRITE); + PRINTFLAG(memacc->Hints, READ); + PRINTFLAG(memacc->Hints, OVERRIDE); + PRINTFLAG_END(); +#undef PRINTFLAG + printf("\t\tMemory Access Flags="); +#define PRINTFLAG(var, flag) printflag((var), ACPI_IORT_MF_## flag, #flag) + PRINTFLAG(memacc->MemoryFlags, COHERENCY); + PRINTFLAG(memacc->MemoryFlags, ATTRIBUTES); + PRINTFLAG_END(); +#undef PRINTFLAG + printf("\t}\n"); +} + +static void +acpi_print_iort_its_group(ACPI_IORT_NODE *node) +{ + ACPI_IORT_ITS_GROUP *itsg = (ACPI_IORT_ITS_GROUP *)node->NodeData; + uint32_t *idp; + unsigned int i; + + idp = itsg->Identifiers; + for (i = 0; i < itsg->ItsCount; i++) + printf("\tGIC ITS ID=%d\n", idp[i]); +} + +static void +acpi_print_iort_named_component(ACPI_IORT_NODE *node) +{ + ACPI_IORT_NAMED_COMPONENT *ncomp + = (ACPI_IORT_NAMED_COMPONENT *)node->NodeData; + +#define PRINTFLAG(var, flag) printflag((var), ACPI_IORT_NC_## flag, #flag) + printf("\tNode Flags={PASID_BITS=%u", + (ncomp->NodeFlags & ACPI_IORT_NC_PASID_BITS) >> 1); + pf_sep = ','; + PRINTFLAG(ncomp->NodeFlags, STALL_SUPPORTED); + PRINTFLAG_END(); +#undef PRINTFLAG + acpi_print_iort_memory_access( + (ACPI_IORT_MEMORY_ACCESS *)&ncomp->MemoryProperties); + printf("\tMemory address size=%hhu\n", ncomp->MemoryAddressLimit); + printf("\tDevice object Name=%s\n", ncomp->DeviceName); +} + +static void +acpi_print_iort_root_complex(ACPI_IORT_NODE *node) +{ + ACPI_IORT_ROOT_COMPLEX *rcmp + = (ACPI_IORT_ROOT_COMPLEX *)node->NodeData; + + acpi_print_iort_memory_access( + (ACPI_IORT_MEMORY_ACCESS *)&rcmp->MemoryProperties); + printf("\tATS Attribute=%s\n", + (rcmp->AtsAttribute & ACPI_IORT_ATS_SUPPORTED) + ? "supported" : "not supported"); + printf("\tPCI Segment=%u\n", rcmp->PciSegmentNumber); + printf("\tMemory address size limit=%hhu\n", rcmp->MemoryAddressLimit); +} + +static void +acpi_print_iort_smmuv1v2_intflags(uint32_t flags) +{ + + printf("{Mode="); + if (flags & 0x01) + printf("edge"); + else + printf("level"); + printf("}\n"); +} + +static void +acpi_print_iort_smmuv1v2(ACPI_IORT_NODE *node) +{ + ACPI_IORT_SMMU *smmu = (ACPI_IORT_SMMU *)node->NodeData; + ACPI_IORT_SMMU_GSI *gsi; + uint64_t *iarray; + unsigned int i; + + printf("\tBase Address=%016jx\n", (uintmax_t)smmu->BaseAddress); + printf("\tSpan=%016jx\n", (uintmax_t)smmu->Span); + printf("\tModel="); + switch (smmu->Model) { + case ACPI_IORT_SMMU_V1: + printf("Generic SMMUv1\n"); + break; + case ACPI_IORT_SMMU_V2: + printf("Generic SMMUv2\n"); + break; + case ACPI_IORT_SMMU_CORELINK_MMU400: + printf("Arm Corelink MMU-400\n"); + break; + case ACPI_IORT_SMMU_CORELINK_MMU500: + printf("Arm Corelink MMU-500\n"); + break; + case ACPI_IORT_SMMU_CORELINK_MMU401: + printf("Arm Corelink MMU-401\n"); + break; + case ACPI_IORT_SMMU_CAVIUM_THUNDERX: + printf("Cavium ThunderX SMMUv2\n"); + break; + default: + printf("reserved (%u)\n", smmu->Model); + break; + } +#define PRINTFLAG(var, flag) printflag((var), ACPI_IORT_SMMU_## flag, #flag) + printf("\tFlags="); + PRINTFLAG(smmu->Flags, DVM_SUPPORTED); + PRINTFLAG(smmu->Flags, COHERENT_WALK); + PRINTFLAG_END(); +#undef PRINTFLAG + + gsi = (ACPI_IORT_SMMU_GSI *)((vaddr_t)node + + smmu->GlobalInterruptOffset); + printf("\tNSgIrpt=%u\n", gsi->NSgIrpt); + printf("\tNSgIrptFlags="); + acpi_print_iort_smmuv1v2_intflags(gsi->NSgIrptFlags); + printf("\tNSgCfgIrpt=%u\n", gsi->NSgCfgIrpt); + printf("\tNSgCfgIrptFlags="); + acpi_print_iort_smmuv1v2_intflags(gsi->NSgCfgIrptFlags); + + if (smmu->ContextInterruptCount != 0) { + iarray = (uint64_t *)((vaddr_t)node + + smmu->ContextInterruptOffset); + printf("\tContext Interrupts={\n"); + for (i = 0; i < smmu->ContextInterruptCount; i++) { + printf("\t\tGSIV=%u\n", + (uint32_t)(iarray[i] & 0xffffffff)); + printf("\t\tFlags=%u\n", (uint32_t)(iarray[i] >> 32)); + } + } + if (smmu->PmuInterruptCount != 0) { + iarray = (uint64_t *)((vaddr_t)node + + smmu->PmuInterruptOffset); + printf("\tPmu Interrupts={\n"); + for (i = 0; i < smmu->PmuInterruptCount; i++) { + printf("\t\tGSIV=%u\n", + (uint32_t)(iarray[i] & 0xffffffff)); + printf("\t\tFlags=%u\n", (uint32_t)(iarray[i] >> 32)); + } + } +} + +static void +acpi_print_iort_smmuv3(ACPI_IORT_NODE *node) +{ + ACPI_IORT_SMMU_V3 *smmu = (ACPI_IORT_SMMU_V3 *)node->NodeData; + uint8_t httuo; + + printf("\tBase Address=%016jx\n", (uintmax_t)smmu->BaseAddress); +#define PRINTFLAG(var, flag) printflag((var), ACPI_IORT_SMMU_V3_## flag, \ + #flag) + httuo = __SHIFTOUT(smmu->Flags, ACPI_IORT_SMMU_V3_HTTU_OVERRIDE); + printf("\tFlags={HTTU Override=%hhx", httuo); + pf_sep = ','; + PRINTFLAG(smmu->Flags, HTTU_OVERRIDE); + PRINTFLAG(smmu->Flags, COHACC_OVERRIDE); + PRINTFLAG(smmu->Flags, PXM_VALID); + PRINTFLAG_END(); +#undef PRINTFLAG + printf("\tVATOS Address=%016jx\n", (uintmax_t)smmu->VatosAddress); + printf("\tModel="); + switch (smmu->Model) { + case ACPI_IORT_SMMU_V3_GENERIC: + printf("Generic SMMUv3\n"); + break; + case ACPI_IORT_SMMU_V3_HISILICON_HI161X: + printf("HiSilicon Hi161x SMMU-v3\n"); + break; + case ACPI_IORT_SMMU_V3_CAVIUM_CN99XX: + printf("Cavium CN99xx SMMU-v3\n"); + break; + default: + printf("reserved (%u)\n", smmu->Model); + break; + } + + printf("\tEvent GSIV=%u\n", smmu->EventGsiv); + printf("\tPRI GSIV=%u\n", smmu->PriGsiv); + printf("\tGERR GSIV=%u\n", smmu->GerrGsiv); + printf("\tSync GSIV=%u\n", smmu->SyncGsiv); + printf("\tProximity domain=%u\n", smmu->Pxm); + + /* XXX should we print the refered contents? */ + printf("\tDevice ID mapping index=%u\n", smmu->IdMappingIndex); +} + +static void +acpi_print_iort_node(ACPI_IORT_NODE *node) +{ + ACPI_IORT_ID_MAPPING *mapping; + uint32_t offset; + int datasize; + bool dodump = false; + struct iort_node_list *list; + unsigned int i; + + printf("\tLength=%hu\n", node->Length); + printf("\tRevision=%hhu\n", node->Revision); + printf("\tType="); + + datasize = node->MappingOffset - offsetof(ACPI_IORT_NODE, NodeData); + if (datasize != 0) + dodump = true; + + for (list = iort_node_list; list->gname != NULL; list++) { + if (node->Type == list->Type) { + printf("%s\n", list->gname); + if (dodump) + (*list->func)(node); + break; + } + } + if (list->gname == NULL) + printf("reserved (0x%hhx)\n", node->Type); + + printf("\tMappingCount=%u\n", node->MappingCount); + if (node->MappingCount == 0) + return; + + offset = node->MappingOffset; + printf("\tMapping offset=%u\n", offset); + for (i = 0; i < node->MappingCount; i++) { + mapping = (ACPI_IORT_ID_MAPPING *)((vaddr_t)node + offset); + printf("\tMapping={\n"); + printf("\t\tInput base=%u\n", mapping->InputBase); + printf("\t\tCount=%u\n", mapping->IdCount); + printf("\t\tOutput base=%u\n", mapping->OutputBase); + printf("\t\tOutput reference offset=%u\n", + mapping->OutputReference); +#define PRINTFLAG(var, flag) printflag((var), ACPI_IORT_ID_## flag, #flag) + printf("\t\tFlags="); + PRINTFLAG(mapping->Flags, SINGLE_MAPPING); + PRINTFLAG_END(); +#undef PRINTFLAG + printf("\t}\n"); + offset += sizeof(ACPI_IORT_ID_MAPPING); + } +} + +static void +acpi_handle_iort(ACPI_TABLE_HEADER *sdp) +{ + ACPI_TABLE_IORT *iort; + ACPI_IORT_NODE *node; + unsigned int i; + + printf(BEGIN_COMMENT); + acpi_print_sdt(sdp); + iort = (ACPI_TABLE_IORT *)sdp; + printf("\tIORT Nodes=%u\n", iort->NodeCount); + printf("\tNode offset=%u\n", iort->NodeOffset); + + node = (ACPI_IORT_NODE *)((vaddr_t)iort + iort->NodeOffset); + for (i = 0; i < iort->NodeCount; i++) { + printf("\n"); + acpi_print_iort_node(node); + + /* Next */ + node = (ACPI_IORT_NODE *)((vaddr_t)node + node->Length); + } + + printf(END_COMMENT); +} + static void acpi_print_native_lpit(ACPI_LPIT_NATIVE *nl) { @@ -3956,6 +4271,8 @@ acpi_handle_rsdt(ACPI_TABLE_HEADER *rsdp acpi_handle_hest(sdp); else if (!memcmp(sdp->Signature, ACPI_SIG_HPET, 4)) acpi_handle_hpet(sdp); + else if (!memcmp(sdp->Signature, ACPI_SIG_IORT, 4)) + acpi_handle_iort(sdp); else if (!memcmp(sdp->Signature, ACPI_SIG_ECDT, 4)) acpi_handle_ecdt(sdp); else if (!memcmp(sdp->Signature, ACPI_SIG_LPIT, 4)) Index: src/usr.sbin/acpitools/acpidump/acpidump.8 diff -u src/usr.sbin/acpitools/acpidump/acpidump.8:1.14 src/usr.sbin/acpitools/acpidump/acpidump.8:1.15 --- src/usr.sbin/acpitools/acpidump/acpidump.8:1.14 Mon Nov 5 07:39:57 2018 +++ src/usr.sbin/acpitools/acpidump/acpidump.8 Sun Dec 2 10:51:07 2018 @@ -1,4 +1,4 @@ -.\" $NetBSD: acpidump.8,v 1.14 2018/11/05 07:39:57 msaitoh Exp $ +.\" $NetBSD: acpidump.8,v 1.15 2018/12/02 10:51:07 msaitoh Exp $ .\" ACPI (ACPI Package) .\" .\" Copyright (c) 1999 Doug Rabson <d...@freebsd.org> @@ -30,7 +30,7 @@ .\" .\" $FreeBSD: head/usr.sbin/acpi/acpidump/acpidump.8 267668 2014-06-20 09:57:27Z bapt $ .\" -.Dd November 5, 2018 +.Dd December 2, 2018 .Dt ACPIDUMP 8 .Os .Sh NAME @@ -113,6 +113,7 @@ utility dumps contents of the following .It GTDT .It HEST .It HPET +.It IORT .It LPIT .It MADT .It MCFG