1 /*
2 * SPDX-License-Identifier: Apache-2.0
3 * Copyright (c) 2019 Intel Corp.
4 */
5
6 #include <zephyr/kernel.h>
7 #include <zephyr/acpi/acpi.h>
8
get_dmar_scope_type(int type)9 static const char *get_dmar_scope_type(int type)
10 {
11 switch (type) {
12 case ACPI_DMAR_SCOPE_TYPE_ENDPOINT:
13 return "PCI Endpoint";
14 case ACPI_DMAR_SCOPE_TYPE_BRIDGE:
15 return "PCI Sub-hierarchy";
16 case ACPI_DMAR_SCOPE_TYPE_IOAPIC:
17 return "IOAPIC";
18 case ACPI_DMAR_SCOPE_TYPE_HPET:
19 return "MSI Capable HPET";
20 case ACPI_DMAR_SCOPE_TYPE_NAMESPACE:
21 return "ACPI name-space enumerated";
22 default:
23 return "unknown";
24 }
25 }
26
dmar_devsope_handler(ACPI_DMAR_DEVICE_SCOPE * devscope,void * arg)27 static void dmar_devsope_handler(ACPI_DMAR_DEVICE_SCOPE *devscope, void *arg)
28 {
29 ARG_UNUSED(arg);
30
31 printk("\t\t\t. Scope type %s\n", get_dmar_scope_type(devscope->EntryType));
32 printk("\t\t\t. Enumeration ID %u\n", devscope->EnumerationId);
33
34 if (devscope->EntryType < ACPI_DMAR_SCOPE_TYPE_RESERVED) {
35 ACPI_DMAR_PCI_PATH *devpath;
36 int num_path = (devscope->Length - 6u) / 2u;
37 int i = 0;
38
39 devpath = ACPI_ADD_PTR(ACPI_DMAR_PCI_PATH, devscope,
40 sizeof(ACPI_DMAR_DEVICE_SCOPE));
41
42 while (num_path--) {
43 printk("\t\t\t. PCI Path %02x:%02x.%02x\n", devscope->Bus,
44 devpath[i].Device, devpath[i].Function);
45 }
46 }
47 }
48
vtd_drhd_info(ACPI_DMAR_HEADER * subtable)49 static void vtd_drhd_info(ACPI_DMAR_HEADER *subtable)
50 {
51 struct acpi_dmar_hardware_unit *drhd = (void *)subtable;
52 static int unit;
53
54 printk("\t\t[ Hardware Unit Definition %d ]\n", unit++);
55
56 if (drhd->Flags & ACPI_DRHD_FLAG_INCLUDE_PCI_ALL) {
57 printk("\t\t- Includes all PCI devices");
58 } else {
59 printk("\t\t- Includes only listed PCI devices");
60 }
61
62 printk(" under given Segment\n");
63
64 printk("\t\t- Segment number %u\n", drhd->Segment);
65 printk("\t\t- Base Address 0x%llx\n", drhd->Address);
66
67 printk("\t\t- Device Scopes:\n");
68
69 acpi_dmar_foreach_devscope(drhd, dmar_devsope_handler, NULL);
70 }
71
dmar_subtable_handler(ACPI_DMAR_HEADER * subtable,void * arg)72 static void dmar_subtable_handler(ACPI_DMAR_HEADER *subtable, void *arg)
73 {
74 ARG_UNUSED(arg);
75
76 if (subtable->Type != ACPI_DMAR_TYPE_HARDWARE_UNIT) {
77 return;
78 }
79
80 vtd_drhd_info(subtable);
81 }
82
vtd_info(void)83 static void vtd_info(void)
84 {
85 struct acpi_table_dmar *dmar;
86
87 dmar = acpi_table_get("DMAR", 0);
88 if (dmar == NULL) {
89 printk("\tIntel VT-D not supported or exposed\n");
90 return;
91 }
92
93 printk("\tIntel VT-D Supported:\n");
94
95 printk("\t-> X2APIC ");
96 if (dmar->Flags & ACPI_DMAR_FLAG_X2APIC_OPT_OUT) {
97 printk("should be opted out\n");
98 } else {
99 printk("does not need to be opted out\n");
100 }
101
102 if (dmar->Flags & ACPI_DMAR_FLAG_INTR_REMAP) {
103 printk("\t-> Interrupt remapping supported\n");
104 acpi_dmar_foreach_subtable(dmar, dmar_subtable_handler, NULL);
105 } else {
106 printk("\t-> Interrupt remapping not supported\n");
107 }
108 }
109
acpi(void)110 void acpi(void)
111 {
112 int nr_cpus;
113
114 for (nr_cpus = 0; acpi_local_apic_get(nr_cpus); ++nr_cpus) {
115 /* count number of CPUs present */
116 }
117
118 if (nr_cpus == 0) {
119 printk("ACPI: no RSDT/MADT found\n\n");
120 } else {
121 printk("ACPI: %d CPU%s found\n", nr_cpus, nr_cpus == 1 ? "" : "s");
122
123 for (int i = 0; i < nr_cpus; ++i) {
124 struct acpi_madt_local_apic *cpu = acpi_local_apic_get(i);
125
126 printk("\tCPU #%d: APIC ID 0x%02x\n", i, cpu->Id);
127 }
128 }
129
130 printk("\n");
131
132 vtd_info();
133
134 printk("\n");
135 }
136