diff --git a/os/src/drivers/acpi/acpi.cc b/os/src/drivers/acpi/acpi.cc index 9b64e415c..20998e2b6 100644 --- a/os/src/drivers/acpi/acpi.cc +++ b/os/src/drivers/acpi/acpi.cc @@ -65,6 +65,8 @@ struct Apic_override : Apic_struct uint16_t flags; } __attribute__((packed)); +struct Dmar_struct_header; +struct Dmar_struct; /* ACPI spec 5.2.6 */ struct Generic @@ -81,13 +83,59 @@ struct Generic uint8_t const *data() { return reinterpret_cast(this); } - /* MADT acpi structures */ + /* MADT ACPI structure */ Apic_struct *apic_struct() { return reinterpret_cast(&creator_rev + 3); } Apic_struct *end() { return reinterpret_cast(signature + size); } - /* MCFG ACPI stucture */ + /* MCFG ACPI structure */ Mcfg_struct *mcfg_struct() { return reinterpret_cast(&creator_rev + 3); } Mcfg_struct *mcfg_end() { return reinterpret_cast(signature + size); } + + /* DMAR Intel VT-d structures */ + Dmar_struct_header *dmar_header() { return reinterpret_cast(this); } + Dmar_struct *dmar_struct() { return reinterpret_cast(&creator_rev + 4); } + Dmar_struct *dmar_end() { return reinterpret_cast(signature + size); } +} __attribute__((packed)); + + +/** + * DMA Remapping structures + */ +struct Dmar_struct_header : Generic +{ + enum { INTR_REMAP_MASK = 0x1U }; + + uint8_t width; + uint8_t flags; + uint8_t reserved[10]; +} __attribute__((packed)); + +/* Reserved Memory Region Reporting structure - Intel VT-d IO Spec - 8.4. */ +struct Rmrr_struct +{ + uint16_t type; + uint16_t length; + uint16_t reserved; + uint16_t pci_segment; + uint64_t start; + uint64_t end; +} __attribute__((packed)); + +/* DMA Remapping Reporting structure - Intel VT-d IO Spec - 8.1. */ +struct Dmar_struct +{ + enum { DRHD= 0U, RMRR = 0x1U, ATSR = 0x2U, RHSA = 0x3U }; + uint16_t type; + uint16_t length; + uint8_t flags; + uint8_t reserved; + uint16_t pci_segment; + uint64_t base; + + Dmar_struct *next() { + return reinterpret_cast((uint8_t *)this + length); } + + Rmrr_struct *rmrr() { return reinterpret_cast(&base + 1); } } __attribute__((packed)); @@ -240,6 +288,11 @@ class Table_wrapper */ bool is_searched() const { return _cmp("DSDT") || _cmp("SSDT"); } + /** + * Is this a DMAR table + */ + bool is_dmar() { return _cmp("DMAR"); } + /** * Parse override structures */ @@ -276,6 +329,19 @@ class Table_wrapper } } + void parse_dmar() const + { + Dmar_struct_header *head = _table->dmar_header(); + PLOG("%u bit DMA physical addressable %s\n", head->width + 1, + head->flags & Dmar_struct_header::INTR_REMAP_MASK ? + ", IRQ remapping supported" : ""); + + Dmar_struct *dmar = _table->dmar_struct(); + for (; dmar < _table->dmar_end(); dmar = dmar->next()) + if (dmar->type == Dmar_struct::RMRR) + PLOG("RMRR: 0x%llx - DMA region reported by BIOS", dmar->base); + } + Table_wrapper(addr_t base) : _base(base), _io_mem(0), _table(0) { /* @@ -1054,6 +1120,11 @@ class Acpi_table table.parse_mcfg(); } + if (table.is_dmar()) { + PDBG("Found DMAR"); + + table.parse_dmar(); + } } if (dsdt) {