From patchwork Fri Jun 29 13:11:05 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [3/5] acpi: acpidump: dump out the DMAR table From: Colin King X-Patchwork-Id: 168072 Message-Id: <1340975467-23977-4-git-send-email-colin.king@canonical.com> To: fwts-devel@lists.ubuntu.com Date: Fri, 29 Jun 2012 14:11:05 +0100 From: Colin Ian King The DMAR table is fairly well described so lets also dump this one out in an annotated form too. Signed-off-by: Colin Ian King --- src/acpi/acpidump/acpidump.c | 117 ++++++++++++++++++++++++++++++++++++++++++ src/lib/include/fwts_acpi.h | 53 +++++++++++++++++++ 2 files changed, 170 insertions(+) diff --git a/src/acpi/acpidump/acpidump.c b/src/acpi/acpidump/acpidump.c index 3ff3e75..79d4c4d 100644 --- a/src/acpi/acpidump/acpidump.c +++ b/src/acpi/acpidump/acpidump.c @@ -1202,6 +1202,122 @@ static void acpidump_asf(fwts_framework *fw, fwts_acpi_table_info *table) } } +/* + * acpidump_dmar() + * dump out DMAR + * http://download.intel.com/technology/computing/vptech/Intel(r)_VT_for_Direct_IO.pdf + */ +static void acpidump_dmar(fwts_framework *fw, fwts_acpi_table_info *table) +{ + uint8_t *data = (uint8_t *)table->data; + size_t length = table->length; + uint8_t *ptr = data; + size_t device_scope_length; + + static fwts_acpidump_field dmar_fields[] = { + FIELD_UINT("Host Address Width", fwts_acpi_table_dmar, host_addr_width), + FIELD_UINT("Flags", fwts_acpi_table_dmar, flags), + FIELD_UINT("Reserved", fwts_acpi_table_dmar, reserved), + FIELD_END + }; + + static fwts_acpidump_field dmar_header_fields[] = { + FIELD_UINT("Type", fwts_acpi_table_dmar_header, type), + FIELD_UINT("Length", fwts_acpi_table_dmar_header, length), + FIELD_END + }; + + static fwts_acpidump_field dmar_hardware_unit_fields[] = { + FIELD_UINT("Flags", fwts_acpi_table_dmar_hardware_unit, flags), + FIELD_UINT("Reserved", fwts_acpi_table_dmar_hardware_unit, reserved), + FIELD_UINT("Segment Number", fwts_acpi_table_dmar_hardware_unit, segment_number), + FIELD_UINT("Register Base Address", fwts_acpi_table_dmar_hardware_unit, register_base_addr), + FIELD_UINT("Device Scope", fwts_acpi_table_dmar_hardware_unit, device_scope), + FIELD_END + }; + + static fwts_acpidump_field dmar_reserved_memory_fields[] = { + FIELD_UINT("Reserved", fwts_acpi_table_dmar_reserved_memory, reserved), + FIELD_UINT("Segment", fwts_acpi_table_dmar_reserved_memory, segment), + FIELD_UINT("Base Address", fwts_acpi_table_dmar_reserved_memory, base_address), + FIELD_UINT("End Address", fwts_acpi_table_dmar_reserved_memory, end_address), + + FIELD_END + }; + + static fwts_acpidump_field dmar_atsr_fields[] = { + FIELD_UINT("Flags", fwts_acpi_table_dmar_atsr, flags), + FIELD_UINT("Reserved", fwts_acpi_table_dmar_atsr, reserved), + FIELD_UINT("Segment", fwts_acpi_table_dmar_atsr, segment), + FIELD_END + }; + + static fwts_acpidump_field dmar_device_scope_fields[] = { + FIELD_UINT("Type", fwts_acpi_table_dmar_device_scope, type), + FIELD_UINT("Length", fwts_acpi_table_dmar_device_scope, length), + FIELD_UINT("Reserved", fwts_acpi_table_dmar_device_scope, reserved), + FIELD_UINT("Enumeration ID", fwts_acpi_table_dmar_device_scope, enumeration_id), + FIELD_UINT("Start Bus Number", fwts_acpi_table_dmar_device_scope, start_bus_number), + FIELD_END + }; + + __acpi_dump_table_fields(fw, ptr, dmar_fields, ptr - data); + + ptr += sizeof(fwts_acpi_table_dmar); + + while (ptr < data + length) { + uint8_t *tmpptr; + fwts_acpi_table_dmar_header *header = + (fwts_acpi_table_dmar_header *)ptr; + + fwts_log_nl(fw); + + switch (header->type) { + case 0: + fwts_log_info_verbatum(fw, "Hardware Unit Definition:"); + __acpi_dump_table_fields(fw, ptr, dmar_header_fields, ptr - data); + __acpi_dump_table_fields(fw, ptr, dmar_hardware_unit_fields, ptr - data); + device_scope_length = (size_t)header->length - sizeof(fwts_acpi_table_dmar_hardware_unit); + tmpptr = ptr + sizeof(fwts_acpi_table_dmar_hardware_unit); + + /* Parse through multiple device scopes */ + while (device_scope_length > 0) { + int i; + + fwts_acpi_table_dmar_device_scope *device_scope = + (fwts_acpi_table_dmar_device_scope *)tmpptr; + __acpi_dump_table_fields(fw, tmpptr, dmar_device_scope_fields, tmpptr - data); + /* + * The device scope has a variable length path, + * so just dump this raw data out for now. + */ + for (i=0; i < device_scope->length - sizeof(fwts_acpi_table_dmar_device_scope); i++) { + uint8_t val8 = device_scope->path[i]; + fwts_log_info_verbatum(fw, "%s 0x%2.2x [%d]", acpi_dump_field_info("Path", 1, (tmpptr - data) + sizeof(fwts_acpi_table_dmar_device_scope) + i), val8, i); + } + tmpptr += device_scope->length; + device_scope_length -= device_scope->length; + } + break; + case 1: + fwts_log_info_verbatum(fw, "Reserved Memory Definition:"); + __acpi_dump_table_fields(fw, ptr, dmar_header_fields, ptr - data); + __acpi_dump_table_fields(fw, ptr, dmar_reserved_memory_fields, ptr - data); + break; + case 2: + fwts_log_info_verbatum(fw, "Root Port ATS Capability Reporting Structure:"); + __acpi_dump_table_fields(fw, ptr, dmar_header_fields, ptr - data); + __acpi_dump_table_fields(fw, ptr, dmar_atsr_fields, ptr - data); + break; + default: + /* and anything else */ + break; + } + + ptr += header->length; + } +} + typedef struct { char *name; void (*func)(fwts_framework *fw, fwts_acpi_table_info *table); @@ -1220,6 +1336,7 @@ static acpidump_table_vec table_vec[] = { { "BOOT", acpidump_boot, 1 }, { "CPEP", acpidump_cpep, 1 }, { "DSDT", acpidump_amlcode, 1 }, + { "DMAR", acpidump_dmar, 1 }, { "ECDT", acpidump_ecdt, 1 }, { "EINJ", acpidump_einj, 1 }, { "ERST", acpidump_erst, 1 }, diff --git a/src/lib/include/fwts_acpi.h b/src/lib/include/fwts_acpi.h index 03f7c2e..ef25ef5 100644 --- a/src/lib/include/fwts_acpi.h +++ b/src/lib/include/fwts_acpi.h @@ -504,6 +504,59 @@ typedef struct { uint8_t fwts_acpi_table_asf_addr_element[0]; } __attribute__ ((packed)) fwts_acpi_table_asf_addr; +/* + * DMAR + * See http://download.intel.com/technology/computing/vptech/Intel(r)_VT_for_Direct_IO.pdf + */ +typedef struct { + fwts_acpi_table_header header; + uint8_t host_addr_width; + uint8_t flags; + uint8_t reserved[10]; +} __attribute__ ((packed)) fwts_acpi_table_dmar; + +typedef struct { + uint16_t type; + uint16_t length; +} __attribute__ ((packed)) fwts_acpi_table_dmar_header; + +/* DMA remapping hardware unit definition structure */ +typedef struct { + fwts_acpi_table_dmar_header header; + uint8_t flags; + uint8_t reserved; + uint16_t segment_number; + uint64_t register_base_addr; + uint8_t device_scope[0]; +} __attribute__ ((packed)) fwts_acpi_table_dmar_hardware_unit; + +/* Reserved Memory Defininition */ +typedef struct { + fwts_acpi_table_dmar_header header; + uint16_t reserved; + uint16_t segment; + uint64_t base_address; + uint64_t end_address; +} __attribute__ ((packed)) fwts_acpi_table_dmar_reserved_memory; + +/* Root Port ATS capability reporting structure */ +typedef struct { + fwts_acpi_table_dmar_header header; + uint8_t flags; + uint8_t reserved; + uint16_t segment; +} __attribute__ ((packed)) fwts_acpi_table_dmar_atsr; + +/* DMA remapping device scope entries */ +typedef struct { + uint8_t type; + uint8_t length; + uint8_t reserved[2]; + uint8_t enumeration_id; + uint8_t start_bus_number; + uint8_t path[0]; +} __attribute__ ((packed)) fwts_acpi_table_dmar_device_scope; + void fwts_acpi_table_get_header(fwts_acpi_table_header *hdr, uint8_t *data); #endif