mirror of https://gitee.com/openkylin/qemu.git
intel-iommu: add DMAR table to ACPI tables
Expose Intel IOMMU to the BIOS. If object of TYPE_INTEL_IOMMU_DEVICE exists, add DMAR table to ACPI RSDT table. For now the DMAR table indicates that there is only one hardware unit without INTR_REMAP capability on the platform. Signed-off-by: Le Tan <tamlokveer@gmail.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
1da12ec4c8
commit
d4eb911935
|
@ -49,6 +49,7 @@
|
||||||
#include "hw/i386/ich9.h"
|
#include "hw/i386/ich9.h"
|
||||||
#include "hw/pci/pci_bus.h"
|
#include "hw/pci/pci_bus.h"
|
||||||
#include "hw/pci-host/q35.h"
|
#include "hw/pci-host/q35.h"
|
||||||
|
#include "hw/i386/intel_iommu.h"
|
||||||
|
|
||||||
#include "hw/i386/q35-acpi-dsdt.hex"
|
#include "hw/i386/q35-acpi-dsdt.hex"
|
||||||
#include "hw/i386/acpi-dsdt.hex"
|
#include "hw/i386/acpi-dsdt.hex"
|
||||||
|
@ -1387,6 +1388,30 @@ build_mcfg_q35(GArray *table_data, GArray *linker, AcpiMcfgInfo *info)
|
||||||
build_header(linker, table_data, (void *)mcfg, sig, len, 1);
|
build_header(linker, table_data, (void *)mcfg, sig, len, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
build_dmar_q35(GArray *table_data, GArray *linker)
|
||||||
|
{
|
||||||
|
int dmar_start = table_data->len;
|
||||||
|
|
||||||
|
AcpiTableDmar *dmar;
|
||||||
|
AcpiDmarHardwareUnit *drhd;
|
||||||
|
|
||||||
|
dmar = acpi_data_push(table_data, sizeof(*dmar));
|
||||||
|
dmar->host_address_width = VTD_HOST_ADDRESS_WIDTH - 1;
|
||||||
|
dmar->flags = 0; /* No intr_remap for now */
|
||||||
|
|
||||||
|
/* DMAR Remapping Hardware Unit Definition structure */
|
||||||
|
drhd = acpi_data_push(table_data, sizeof(*drhd));
|
||||||
|
drhd->type = cpu_to_le16(ACPI_DMAR_TYPE_HARDWARE_UNIT);
|
||||||
|
drhd->length = cpu_to_le16(sizeof(*drhd)); /* No device scope now */
|
||||||
|
drhd->flags = ACPI_DMAR_INCLUDE_PCI_ALL;
|
||||||
|
drhd->pci_segment = cpu_to_le16(0);
|
||||||
|
drhd->address = cpu_to_le64(Q35_HOST_BRIDGE_IOMMU_ADDR);
|
||||||
|
|
||||||
|
build_header(linker, table_data, (void *)(table_data->data + dmar_start),
|
||||||
|
"DMAR", table_data->len - dmar_start, 1);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
build_dsdt(GArray *table_data, GArray *linker, AcpiMiscInfo *misc)
|
build_dsdt(GArray *table_data, GArray *linker, AcpiMiscInfo *misc)
|
||||||
{
|
{
|
||||||
|
@ -1508,6 +1533,16 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool acpi_has_iommu(void)
|
||||||
|
{
|
||||||
|
bool ambiguous;
|
||||||
|
Object *intel_iommu;
|
||||||
|
|
||||||
|
intel_iommu = object_resolve_path_type("", TYPE_INTEL_IOMMU_DEVICE,
|
||||||
|
&ambiguous);
|
||||||
|
return intel_iommu && !ambiguous;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
|
void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
|
||||||
{
|
{
|
||||||
|
@ -1584,6 +1619,10 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
|
||||||
acpi_add_table(table_offsets, tables->table_data);
|
acpi_add_table(table_offsets, tables->table_data);
|
||||||
build_mcfg_q35(tables->table_data, tables->linker, &mcfg);
|
build_mcfg_q35(tables->table_data, tables->linker, &mcfg);
|
||||||
}
|
}
|
||||||
|
if (acpi_has_iommu()) {
|
||||||
|
acpi_add_table(table_offsets, tables->table_data);
|
||||||
|
build_dmar_q35(tables->table_data, tables->linker);
|
||||||
|
}
|
||||||
|
|
||||||
/* Add tables supplied by user (if any) */
|
/* Add tables supplied by user (if any) */
|
||||||
for (u = acpi_table_first(); u; u = acpi_table_next(u)) {
|
for (u = acpi_table_first(); u; u = acpi_table_next(u)) {
|
||||||
|
|
|
@ -325,4 +325,44 @@ struct Acpi20Tcpa {
|
||||||
} QEMU_PACKED;
|
} QEMU_PACKED;
|
||||||
typedef struct Acpi20Tcpa Acpi20Tcpa;
|
typedef struct Acpi20Tcpa Acpi20Tcpa;
|
||||||
|
|
||||||
|
/* DMAR - DMA Remapping table r2.2 */
|
||||||
|
struct AcpiTableDmar {
|
||||||
|
ACPI_TABLE_HEADER_DEF
|
||||||
|
uint8_t host_address_width; /* Maximum DMA physical addressability */
|
||||||
|
uint8_t flags;
|
||||||
|
uint8_t reserved[10];
|
||||||
|
} QEMU_PACKED;
|
||||||
|
typedef struct AcpiTableDmar AcpiTableDmar;
|
||||||
|
|
||||||
|
/* Masks for Flags field above */
|
||||||
|
#define ACPI_DMAR_INTR_REMAP 1
|
||||||
|
#define ACPI_DMAR_X2APIC_OPT_OUT (1 << 1)
|
||||||
|
|
||||||
|
/* Values for sub-structure type for DMAR */
|
||||||
|
enum {
|
||||||
|
ACPI_DMAR_TYPE_HARDWARE_UNIT = 0, /* DRHD */
|
||||||
|
ACPI_DMAR_TYPE_RESERVED_MEMORY = 1, /* RMRR */
|
||||||
|
ACPI_DMAR_TYPE_ATSR = 2, /* ATSR */
|
||||||
|
ACPI_DMAR_TYPE_HARDWARE_AFFINITY = 3, /* RHSR */
|
||||||
|
ACPI_DMAR_TYPE_ANDD = 4, /* ANDD */
|
||||||
|
ACPI_DMAR_TYPE_RESERVED = 5 /* Reserved for furture use */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sub-structures for DMAR
|
||||||
|
*/
|
||||||
|
/* Type 0: Hardware Unit Definition */
|
||||||
|
struct AcpiDmarHardwareUnit {
|
||||||
|
uint16_t type;
|
||||||
|
uint16_t length;
|
||||||
|
uint8_t flags;
|
||||||
|
uint8_t reserved;
|
||||||
|
uint16_t pci_segment; /* The PCI Segment associated with this unit */
|
||||||
|
uint64_t address; /* Base address of remapping hardware register-set */
|
||||||
|
} QEMU_PACKED;
|
||||||
|
typedef struct AcpiDmarHardwareUnit AcpiDmarHardwareUnit;
|
||||||
|
|
||||||
|
/* Masks for Flags field above */
|
||||||
|
#define ACPI_DMAR_INCLUDE_PCI_ALL 1
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue