blob: 4271710ba22a39f50e1fc460e5e874ad559411dd [file] [log] [blame]
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright (c) 2019 Intel Corp.
*/
#include <zephyr/kernel.h>
#include <zephyr/acpi/acpi.h>
static const uint32_t dmar_scope[] = {ACPI_DMAR_SCOPE_TYPE_ENDPOINT, ACPI_DMAR_SCOPE_TYPE_BRIDGE,
ACPI_DMAR_SCOPE_TYPE_IOAPIC, ACPI_DMAR_SCOPE_TYPE_HPET,
ACPI_DMAR_SCOPE_TYPE_NAMESPACE};
static void vtd_dev_scope_info(int type, struct acpi_dmar_device_scope *dev_scope,
union acpi_dmar_id *dmar_id, int num_inst)
{
int i = 0;
printk("\t\t\t. Type: ");
switch (type) {
case ACPI_DMAR_SCOPE_TYPE_ENDPOINT:
printk("PCI Endpoint");
break;
case ACPI_DMAR_SCOPE_TYPE_BRIDGE:
printk("PCI Sub-hierarchy");
break;
case ACPI_DMAR_SCOPE_TYPE_IOAPIC:
break;
case ACPI_DMAR_SCOPE_TYPE_HPET:
printk("MSI Capable HPET");
break;
case ACPI_DMAR_SCOPE_TYPE_NAMESPACE:
printk("ACPI name-space enumerated");
break;
default:
printk("unknown\n");
return;
}
printk("\n");
printk("\t\t\t. Enumeration ID %u\n", dev_scope->EnumerationId);
printk("\t\t\t. PCI Bus %u\n", dev_scope->Bus);
for (; num_inst > 0; num_inst--, i++) {
printk("Info: Bus: %d, dev:%d, fun:%d\n", dmar_id[i].bits.bus,
dmar_id[i].bits.device, dmar_id[i].bits.function);
}
printk("\n");
}
static void vtd_drhd_info(struct acpi_dmar_hardware_unit *drhd)
{
struct acpi_dmar_device_scope dev_scope;
union acpi_dmar_id dmar_id[4];
int num_inst, i;
if (drhd->Flags & ACPI_DRHD_FLAG_INCLUDE_PCI_ALL) {
printk("\t\t- Includes all PCI devices");
} else {
printk("\t\t- Includes only listed PCI devices");
}
printk(" under given Segment\n");
printk("\t\t- Segment number %u\n", drhd->Segment);
printk("\t\t- Base Address 0x%llx\n", drhd->Address);
printk("\t\t- Device Scopes:\n");
for (i = 0; i < 5; i++) {
if (acpi_drhd_get(dmar_scope[i], &dev_scope, dmar_id, &num_inst, 4u)) {
printk(" No DRHD entry found for scope type:%d\n", dmar_scope[i]);
continue;
}
printk("Found DRHD entry: %d\n", i);
vtd_dev_scope_info(dmar_scope[i], &dev_scope, dmar_id, num_inst);
}
printk("\n");
}
static void vtd_info(void)
{
struct acpi_table_dmar *dmar;
struct acpi_dmar_hardware_unit *drhd;
dmar = acpi_table_get("DMAR", 0);
if (dmar == NULL) {
printk("\tIntel VT-D not supported or exposed\n");
return;
}
printk("\tIntel VT-D Supported:\n");
printk("\t-> X2APIC ");
if (dmar->Flags & ACPI_DMAR_FLAG_X2APIC_OPT_OUT) {
printk("should be opted out\n");
} else {
printk("does not need to be opted out\n");
}
if (dmar->Flags & ACPI_DMAR_FLAG_INTR_REMAP) {
printk("\t-> Interrupt remapping supported\n");
if (acpi_dmar_entry_get(ACPI_DMAR_TYPE_HARDWARE_UNIT,
(struct acpi_subtable_header **)&drhd)) {
printk("error in retrieve DHRD!!\n");
return;
}
vtd_drhd_info(drhd);
} else {
printk("\t-> Interrupt remapping not supported\n");
}
}
void acpi(void)
{
int nr_cpus = 0, i, inst_cnt;
struct acpi_madt_local_apic *lapic;
if (acpi_madt_entry_get(ACPI_MADT_TYPE_LOCAL_APIC, (ACPI_SUBTABLE_HEADER **)&lapic,
&inst_cnt)) {
printk("error on get MAD table\n");
return;
}
/* count number of CPUs present which are enabled*/
for (i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) {
if (lapic[i].LapicFlags & 1u) {
nr_cpus++;
}
}
if (nr_cpus == 0) {
printk("ACPI: no RSDT/MADT found\n\n");
} else {
printk("ACPI: %d CPUs found\n", nr_cpus);
for (i = 0; i < CONFIG_MP_MAX_NUM_CPUS; ++i) {
printk("\tCPU #%d: APIC ID 0x%02x\n", i, lapic[i].Id);
}
}
printk("\n");
vtd_info();
printk("\n");
}