parent
3789a75ed6
commit
74e89727ee
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
/* base includes */
|
/* base includes */
|
||||||
#include <io_mem_session/connection.h>
|
#include <io_mem_session/connection.h>
|
||||||
|
#include <util/mmio.h>
|
||||||
|
|
||||||
/* os includes */
|
/* os includes */
|
||||||
#include <os/reporter.h>
|
#include <os/reporter.h>
|
||||||
|
@ -72,7 +73,6 @@ struct Apic_override : Apic_struct
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct Dmar_struct_header;
|
struct Dmar_struct_header;
|
||||||
struct Dmar_struct;
|
|
||||||
|
|
||||||
/* ACPI spec 5.2.6 */
|
/* ACPI spec 5.2.6 */
|
||||||
struct Generic
|
struct Generic
|
||||||
|
@ -97,16 +97,21 @@ struct Generic
|
||||||
Mcfg_struct *mcfg_struct() { return reinterpret_cast<Mcfg_struct *>(&creator_rev + 3); }
|
Mcfg_struct *mcfg_struct() { return reinterpret_cast<Mcfg_struct *>(&creator_rev + 3); }
|
||||||
Mcfg_struct *mcfg_end() { return reinterpret_cast<Mcfg_struct *>(signature + size); }
|
Mcfg_struct *mcfg_end() { return reinterpret_cast<Mcfg_struct *>(signature + size); }
|
||||||
|
|
||||||
/* DMAR Intel VT-d structures */
|
|
||||||
Dmar_struct_header *dmar_header() { return reinterpret_cast<Dmar_struct_header *>(this); }
|
Dmar_struct_header *dmar_header() { return reinterpret_cast<Dmar_struct_header *>(this); }
|
||||||
Dmar_struct *dmar_struct() { return reinterpret_cast<Dmar_struct *>(&creator_rev + 4); }
|
|
||||||
Dmar_struct *dmar_end() { return reinterpret_cast<Dmar_struct *>(signature + size); }
|
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
|
||||||
/**
|
struct Dmar_common : Genode::Mmio
|
||||||
* DMA Remapping structures
|
{
|
||||||
*/
|
struct Type : Register<0x0, 16> {
|
||||||
|
enum { DRHD= 0U, RMRR = 0x1U, ATSR = 0x2U, RHSA = 0x3U }; };
|
||||||
|
struct Length : Register<0x2, 16> { };
|
||||||
|
|
||||||
|
Dmar_common(addr_t mmio) : Genode::Mmio(mmio) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* DMA Remapping Reporting Structure - Intel VT-d IO Spec - 8.1. */
|
||||||
struct Dmar_struct_header : Generic
|
struct Dmar_struct_header : Generic
|
||||||
{
|
{
|
||||||
enum { INTR_REMAP_MASK = 0x1U };
|
enum { INTR_REMAP_MASK = 0x1U };
|
||||||
|
@ -114,37 +119,96 @@ struct Dmar_struct_header : Generic
|
||||||
uint8_t width;
|
uint8_t width;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
uint8_t reserved[10];
|
uint8_t reserved[10];
|
||||||
|
|
||||||
|
/* DMAR Intel VT-d structures */
|
||||||
|
addr_t dmar_entry_start() { return reinterpret_cast<addr_t>(&creator_rev + 4); }
|
||||||
|
addr_t dmar_entry_end() { return reinterpret_cast<addr_t>(signature + size); }
|
||||||
|
|
||||||
|
template <typename FUNC>
|
||||||
|
void apply(FUNC const &func = [] () { } )
|
||||||
|
{
|
||||||
|
addr_t addr = dmar_entry_start();
|
||||||
|
do {
|
||||||
|
Dmar_common dmar(addr);
|
||||||
|
|
||||||
|
func(dmar);
|
||||||
|
|
||||||
|
addr = dmar.base + dmar.read<Dmar_common::Length>();
|
||||||
|
} while (addr < dmar_entry_end());
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Dmar_struct_header * clone()
|
||||||
|
{
|
||||||
|
size_t const size = dmar_entry_end() - reinterpret_cast<addr_t>(this);
|
||||||
|
char * clone = new (env()->heap()) char[size];
|
||||||
|
memcpy(clone, this, size);
|
||||||
|
|
||||||
|
return reinterpret_cast<Dmar_struct_header *>(clone);
|
||||||
|
}
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
/* Reserved Memory Region Reporting structure - Intel VT-d IO Spec - 8.4. */
|
|
||||||
struct Rmrr_struct
|
/* Intel VT-d IO Spec - 8.3.1. */
|
||||||
|
struct Device_scope : Genode::Mmio
|
||||||
{
|
{
|
||||||
uint16_t type;
|
Device_scope(addr_t a) : Genode::Mmio(a) { }
|
||||||
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 Type : Register<0x0, 8> { enum { PCI_END_POINT = 0x1 }; };
|
||||||
struct Dmar_struct
|
struct Length : Register<0x1, 8> { };
|
||||||
|
struct Bus : Register<0x5, 8> { };
|
||||||
|
|
||||||
|
struct Path : Register_array<0x6, 8, 1, 16> {
|
||||||
|
struct Dev : Bitfield<0,8> { };
|
||||||
|
struct Func : Bitfield<8,8> { };
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned count() const { return (read<Length>() - 6) / 2; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* DMA Remapping Reporting structure - Intel VT-d IO Spec - 8.3. */
|
||||||
|
struct Dmar_rmrr : Genode::Mmio
|
||||||
{
|
{
|
||||||
enum { DRHD= 0U, RMRR = 0x1U, ATSR = 0x2U, RHSA = 0x3U };
|
struct Length : Register<0x02, 16> { };
|
||||||
uint16_t type;
|
struct Base : Register<0x08, 64> { };
|
||||||
uint16_t length;
|
struct Limit : Register<0x10, 64> { };
|
||||||
uint8_t flags;
|
|
||||||
uint8_t reserved;
|
|
||||||
uint16_t pci_segment;
|
|
||||||
uint64_t base;
|
|
||||||
uint64_t limit;
|
|
||||||
|
|
||||||
Dmar_struct *next() {
|
Dmar_rmrr(addr_t a) : Genode::Mmio(a) { }
|
||||||
return reinterpret_cast<Dmar_struct *>((uint8_t *)this + length); }
|
|
||||||
|
|
||||||
Rmrr_struct *rmrr() { return reinterpret_cast<Rmrr_struct *>(&base + 1); }
|
template <typename FUNC>
|
||||||
} __attribute__((packed));
|
void apply(FUNC const &func = [] () { } )
|
||||||
|
{
|
||||||
|
addr_t addr = base + 24;
|
||||||
|
do {
|
||||||
|
Device_scope scope(addr);
|
||||||
|
|
||||||
|
func(scope);
|
||||||
|
|
||||||
|
addr = scope.base + scope.read<Device_scope::Length>();
|
||||||
|
} while (addr < base + read<Length>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Dmar_entry : public List<Dmar_entry>::Element
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
Dmar_struct_header *_header;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Dmar_entry(Dmar_struct_header * h) : _header(h) { }
|
||||||
|
|
||||||
|
template <typename FUNC>
|
||||||
|
void apply(FUNC const &func = [] () { } ) { _header->apply(func); }
|
||||||
|
|
||||||
|
static List<Dmar_entry> *list()
|
||||||
|
{
|
||||||
|
static List<Dmar_entry> _list;
|
||||||
|
return &_list;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List that holds interrupt override information
|
* List that holds interrupt override information
|
||||||
|
@ -319,11 +383,11 @@ class Table_wrapper
|
||||||
head->flags & Dmar_struct_header::INTR_REMAP_MASK ?
|
head->flags & Dmar_struct_header::INTR_REMAP_MASK ?
|
||||||
" , IRQ remapping supported" : "");
|
" , IRQ remapping supported" : "");
|
||||||
|
|
||||||
Dmar_struct *dmar = _table->dmar_struct();
|
head->apply([&] (Dmar_common const &dmar) {
|
||||||
for (; dmar < _table->dmar_end(); dmar = dmar->next())
|
PLOG("DMA remapping structure type=%u", dmar.read<Dmar_common::Type>());
|
||||||
if (dmar->type == Dmar_struct::RMRR)
|
});
|
||||||
PLOG("RMRR: [0x%llx,0x%llx] - DMA region reported by BIOS",
|
|
||||||
dmar->base, dmar->limit);
|
Dmar_entry::list()->insert(new (env()->heap()) Dmar_entry(head->clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Table_wrapper(addr_t base) : _base(base), _table(0)
|
Table_wrapper(addr_t base) : _base(base), _table(0)
|
||||||
|
@ -1228,6 +1292,50 @@ void Acpi::generate_report()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* lambda definition for scope evaluation in rmrr */
|
||||||
|
auto func_scope = [&] (Device_scope const &scope)
|
||||||
|
{
|
||||||
|
xml.node("scope", [&] () {
|
||||||
|
char number[8];
|
||||||
|
Genode::snprintf(number, sizeof(number), "%u",
|
||||||
|
scope.read<Device_scope::Bus>());
|
||||||
|
xml.attribute("bus_start", number);
|
||||||
|
for (unsigned j = 0 ; j < scope.count(); j++) {
|
||||||
|
xml.node("path", [&] () {
|
||||||
|
char number[8];
|
||||||
|
Genode::snprintf(number, sizeof(number), "0x%x",
|
||||||
|
scope.read<Device_scope::Path::Dev>(j));
|
||||||
|
xml.attribute("dev", number);
|
||||||
|
Genode::snprintf(number, sizeof(number), "0x%x",
|
||||||
|
scope.read<Device_scope::Path::Func>(j));
|
||||||
|
xml.attribute("func", number);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
for (Dmar_entry *entry = Dmar_entry::list()->first();
|
||||||
|
entry; entry = entry->next()) {
|
||||||
|
|
||||||
|
entry->apply([&] (Dmar_common const &dmar) {
|
||||||
|
if (dmar.read<Dmar_common::Type>() != Dmar_common::Type::RMRR)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Dmar_rmrr rmrr(dmar.base);
|
||||||
|
|
||||||
|
xml.node("rmrr", [&] () {
|
||||||
|
char number[20];
|
||||||
|
Genode::snprintf(number, sizeof(number), "0x%llx",
|
||||||
|
rmrr.read<Dmar_rmrr::Base>());
|
||||||
|
xml.attribute("start", number);
|
||||||
|
Genode::snprintf(number, sizeof(number), "0x%llx",
|
||||||
|
rmrr.read<Dmar_rmrr::Limit>());
|
||||||
|
xml.attribute("end", number);
|
||||||
|
|
||||||
|
rmrr.apply(func_scope);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
{
|
{
|
||||||
Element *e = Element::list()->first();
|
Element *e = Element::list()->first();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue