acpi: Add support for DMAR tables (Intel IOMMU support)
Adds lowlevel handling of DMAR tables for use by mainboards' ACPI code. Not much automagic (yet). Change-Id: Ia86e950dfcc5b9994202ec0e2f6d9a2912c74ad8 Signed-off-by: Patrick Georgi <patrick.georgi@secunet.com> Reviewed-on: http://review.coreboot.org/1654 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
parent
a93c3fe7f0
commit
3b590ffeb4
|
@ -334,6 +334,71 @@ void acpi_create_srat(acpi_srat_t *srat)
|
||||||
header->checksum = acpi_checksum((void *)srat, header->length);
|
header->checksum = acpi_checksum((void *)srat, header->length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned long __attribute__((weak)) acpi_fill_dmar(unsigned long current)
|
||||||
|
{
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
void acpi_create_dmar(acpi_dmar_t *dmar)
|
||||||
|
{
|
||||||
|
acpi_header_t *header = &(dmar->header);
|
||||||
|
unsigned long current = (unsigned long)dmar + sizeof(acpi_dmar_t);
|
||||||
|
|
||||||
|
memset((void *)dmar, 0, sizeof(acpi_dmar_t));
|
||||||
|
|
||||||
|
/* Fill out header fields. */
|
||||||
|
memcpy(header->signature, "DMAR", 4);
|
||||||
|
memcpy(header->oem_id, OEM_ID, 6);
|
||||||
|
memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
|
||||||
|
memcpy(header->asl_compiler_id, ASLC, 4);
|
||||||
|
|
||||||
|
header->length = sizeof(acpi_dmar_t);
|
||||||
|
header->revision = 1;
|
||||||
|
|
||||||
|
dmar->host_address_width = 40 - 1; /* FIXME: == MTRR size? */
|
||||||
|
dmar->flags = 0;
|
||||||
|
|
||||||
|
current = acpi_fill_dmar(current);
|
||||||
|
|
||||||
|
/* (Re)calculate length and checksum. */
|
||||||
|
header->length = current - (unsigned long)dmar;
|
||||||
|
header->checksum = acpi_checksum((void *)dmar, header->length);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long acpi_create_dmar_drhd(unsigned long current, u8 flags,
|
||||||
|
u16 segment, u32 bar)
|
||||||
|
{
|
||||||
|
dmar_entry_t *drhd = (dmar_entry_t *)current;
|
||||||
|
memset(drhd, 0, sizeof(*drhd));
|
||||||
|
drhd->type = DMAR_DRHD;
|
||||||
|
drhd->length = sizeof(*drhd); /* will be fixed up later */
|
||||||
|
drhd->flags = flags;
|
||||||
|
drhd->segment = segment;
|
||||||
|
drhd->bar = bar;
|
||||||
|
|
||||||
|
return drhd->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void acpi_dmar_drhd_fixup(unsigned long base, unsigned long current)
|
||||||
|
{
|
||||||
|
dmar_entry_t *drhd = (dmar_entry_t *)base;
|
||||||
|
drhd->length = current - base;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long acpi_create_dmar_drhd_ds_pci(unsigned long current, u8 segment,
|
||||||
|
u8 dev, u8 fn)
|
||||||
|
{
|
||||||
|
dev_scope_t *ds = (dev_scope_t *)current;
|
||||||
|
memset(ds, 0, sizeof(*ds));
|
||||||
|
ds->type = SCOPE_PCI_ENDPOINT;
|
||||||
|
ds->length = sizeof(*ds) + 2; /* we don't support longer paths yet */
|
||||||
|
ds->start_bus = segment;
|
||||||
|
ds->path[0].dev = dev;
|
||||||
|
ds->path[0].fn = fn;
|
||||||
|
|
||||||
|
return ds->length;
|
||||||
|
}
|
||||||
|
|
||||||
/* http://h21007.www2.hp.com/portal/download/files/unprot/Itanium/slit.pdf */
|
/* http://h21007.www2.hp.com/portal/download/files/unprot/Itanium/slit.pdf */
|
||||||
void acpi_create_slit(acpi_slit_t *slit)
|
void acpi_create_slit(acpi_slit_t *slit)
|
||||||
{
|
{
|
||||||
|
|
|
@ -187,6 +187,54 @@ typedef struct acpi_madt {
|
||||||
u32 flags; /* Multiple APIC flags */
|
u32 flags; /* Multiple APIC flags */
|
||||||
} __attribute__ ((packed)) acpi_madt_t;
|
} __attribute__ ((packed)) acpi_madt_t;
|
||||||
|
|
||||||
|
enum dev_scope_type {
|
||||||
|
SCOPE_PCI_ENDPOINT = 1,
|
||||||
|
SCOPE_PCI_SUB = 2,
|
||||||
|
SCOPE_IOAPIC = 3,
|
||||||
|
SCOPE_MSI_HPET = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct dev_scope {
|
||||||
|
u8 type;
|
||||||
|
u8 length;
|
||||||
|
u8 reserved[2];
|
||||||
|
u8 enumeration;
|
||||||
|
u8 start_bus;
|
||||||
|
struct {
|
||||||
|
u8 dev;
|
||||||
|
u8 fn;
|
||||||
|
} __attribute__((packed)) path[0];
|
||||||
|
} __attribute__ ((packed)) dev_scope_t;
|
||||||
|
|
||||||
|
enum dmar_type {
|
||||||
|
DMAR_DRHD = 0,
|
||||||
|
DMAR_RMRR = 1,
|
||||||
|
DMAR_ATSR = 2,
|
||||||
|
DMAR_RHSA = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DRHD_INCLUDE_PCI_ALL = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct dmar_entry {
|
||||||
|
u16 type;
|
||||||
|
u16 length;
|
||||||
|
u8 flags;
|
||||||
|
u8 reserved;
|
||||||
|
u16 segment;
|
||||||
|
u64 bar;
|
||||||
|
} __attribute__ ((packed)) dmar_entry_t;
|
||||||
|
|
||||||
|
/* DMAR (DMA Remapping Reporting Structure) */
|
||||||
|
typedef struct acpi_dmar {
|
||||||
|
struct acpi_table_header header;
|
||||||
|
u8 host_address_width;
|
||||||
|
u8 flags;
|
||||||
|
u8 reserved[10];
|
||||||
|
dmar_entry_t structure[0];
|
||||||
|
} __attribute__ ((packed)) acpi_dmar_t;
|
||||||
|
|
||||||
/* MADT: APIC Structure Types */
|
/* MADT: APIC Structure Types */
|
||||||
/* TODO: Convert to ALLCAPS. */
|
/* TODO: Convert to ALLCAPS. */
|
||||||
enum acpi_apic_types {
|
enum acpi_apic_types {
|
||||||
|
@ -483,6 +531,15 @@ void acpi_create_mcfg(acpi_mcfg_t *mcfg);
|
||||||
|
|
||||||
void acpi_create_facs(acpi_facs_t *facs);
|
void acpi_create_facs(acpi_facs_t *facs);
|
||||||
|
|
||||||
|
void acpi_create_dmar(acpi_dmar_t *dmar);
|
||||||
|
unsigned long acpi_create_dmar_drhd(unsigned long current, u8 flags,
|
||||||
|
u16 segment, u32 bar);
|
||||||
|
void acpi_dmar_drhd_fixup(unsigned long base, unsigned long current);
|
||||||
|
unsigned long acpi_create_dmar_drhd_ds_pci(unsigned long current, u8 segment,
|
||||||
|
u8 dev, u8 fn);
|
||||||
|
|
||||||
|
unsigned long acpi_fill_dmar(unsigned long);
|
||||||
|
|
||||||
#if CONFIG_HAVE_ACPI_SLIC
|
#if CONFIG_HAVE_ACPI_SLIC
|
||||||
unsigned long acpi_create_slic(unsigned long current);
|
unsigned long acpi_create_slic(unsigned long current);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue