summaryrefslogtreecommitdiff
path: root/usr.sbin/acpitools
diff options
context:
space:
mode:
authormsaitoh <msaitoh@NetBSD.org>2018-12-02 10:51:07 +0000
committermsaitoh <msaitoh@NetBSD.org>2018-12-02 10:51:07 +0000
commitdf2dfd53df9a453d6d06b7eafa95d9c07421fb87 (patch)
tree6edee3a70f053cc1ab0432d66e7e1d265f4788d6 /usr.sbin/acpitools
parent161ff65de510ec5a668bfedd3178bf806bc975e7 (diff)
Decode IO Remapping Table.
Diffstat (limited to 'usr.sbin/acpitools')
-rw-r--r--usr.sbin/acpitools/acpidump/acpi.c321
-rw-r--r--usr.sbin/acpitools/acpidump/acpidump.85
2 files changed, 322 insertions, 4 deletions
diff --git a/usr.sbin/acpitools/acpidump/acpi.c b/usr.sbin/acpitools/acpidump/acpi.c
index 0e6a55eb088..1a6d09fd383 100644
--- a/usr.sbin/acpitools/acpidump/acpi.c
+++ b/usr.sbin/acpitools/acpidump/acpi.c
@@ -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_HEADER *sdp);
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))
diff --git a/usr.sbin/acpitools/acpidump/acpidump.8 b/usr.sbin/acpitools/acpidump/acpidump.8
index 256d7fc12c6..917d3480fa8 100644
--- a/usr.sbin/acpitools/acpidump/acpidump.8
+++ b/usr.sbin/acpitools/acpidump/acpidump.8
@@ -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 <dfr@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 tables:
.It GTDT
.It HEST
.It HPET
+.It IORT
.It LPIT
.It MADT
.It MCFG