summaryrefslogtreecommitdiffstats
path: root/hw/i386
diff options
context:
space:
mode:
Diffstat (limited to 'hw/i386')
-rw-r--r--hw/i386/acpi-build.c52
-rw-r--r--hw/i386/amd_iommu.c2
-rw-r--r--hw/i386/intel_iommu.c72
-rw-r--r--hw/i386/intel_iommu_internal.h3
-rw-r--r--hw/i386/pc.c4
-rw-r--r--hw/i386/pc_piix.c72
-rw-r--r--hw/i386/pc_q35.c4
-rw-r--r--hw/i386/trace-events6
-rw-r--r--hw/i386/x86-iommu.c18
9 files changed, 101 insertions, 132 deletions
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 236a20eaa8..14f757fc36 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -2426,7 +2426,7 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linker)
IntelIOMMUState *intel_iommu = INTEL_IOMMU_DEVICE(iommu);
assert(iommu);
- if (iommu->intr_supported) {
+ if (x86_iommu_ir_supported(iommu)) {
dmar_flags |= 0x1; /* Flags: 0x1: INT_REMAP */
}
@@ -2499,7 +2499,7 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker)
* When interrupt remapping is supported, we add a special IVHD device
* for type IO-APIC.
*/
- if (x86_iommu_get_default()->intr_supported) {
+ if (x86_iommu_ir_supported(x86_iommu_get_default())) {
ivhd_table_len += 8;
}
/* IVHD length */
@@ -2535,7 +2535,7 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker)
* Linux IOMMU driver checks for the special IVHD device (type IO-APIC).
* See Linux kernel commit 'c2ff5cf5294bcbd7fa50f7d860e90a66db7e5059'
*/
- if (x86_iommu_get_default()->intr_supported) {
+ if (x86_iommu_ir_supported(x86_iommu_get_default())) {
build_append_int_noprefix(table_data,
(0x1ull << 56) | /* type IOAPIC */
(IOAPIC_SB_DEVID << 40) | /* IOAPIC devid */
@@ -2547,32 +2547,6 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker)
"IVRS", table_data->len - iommu_start, 1, NULL, NULL);
}
-static GArray *
-build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset)
-{
- AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof *rsdp);
- unsigned rsdt_pa_size = sizeof(rsdp->rsdt_physical_address);
- unsigned rsdt_pa_offset =
- (char *)&rsdp->rsdt_physical_address - rsdp_table->data;
-
- bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, rsdp_table, 16,
- true /* fseg memory */);
-
- memcpy(&rsdp->signature, "RSD PTR ", 8);
- memcpy(rsdp->oem_id, ACPI_BUILD_APPNAME6, 6);
- /* Address to be filled by Guest linker */
- bios_linker_loader_add_pointer(linker,
- ACPI_BUILD_RSDP_FILE, rsdt_pa_offset, rsdt_pa_size,
- ACPI_BUILD_TABLE_FILE, rsdt_tbl_offset);
-
- /* Checksum to be filled by Guest linker */
- bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
- (char *)rsdp - rsdp_table->data, sizeof *rsdp,
- (char *)&rsdp->checksum - rsdp_table->data);
-
- return rsdp_table;
-}
-
typedef
struct AcpiBuildState {
/* Copy of table in RAM (for patching). */
@@ -2729,7 +2703,25 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
slic_oem.id, slic_oem.table_id);
/* RSDP is in FSEG memory, so allocate it separately */
- build_rsdp(tables->rsdp, tables->linker, rsdt);
+ {
+ AcpiRsdpData rsdp_data = {
+ .revision = 0,
+ .oem_id = ACPI_BUILD_APPNAME6,
+ .xsdt_tbl_offset = NULL,
+ .rsdt_tbl_offset = &rsdt,
+ };
+ build_rsdp(tables->rsdp, tables->linker, &rsdp_data);
+ if (!pcmc->rsdp_in_ram) {
+ /* We used to allocate some extra space for RSDP revision 2 but
+ * only used the RSDP revision 0 space. The extra bytes were
+ * zeroed out and not used.
+ * Here we continue wasting those extra 16 bytes to make sure we
+ * don't break migration for machine types 2.2 and older due to
+ * RSDP blob size mismatch.
+ */
+ build_append_int_noprefix(tables->rsdp, 0, 16);
+ }
+ }
/* We'll expose it all to Guest so we want to reduce
* chance of size changes.
diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index 353a810e6b..8ad707aba0 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -1233,7 +1233,7 @@ static int amdvi_int_remap_msi(AMDVIState *iommu,
}
/* validate that we are configure with intremap=on */
- if (!X86_IOMMU_DEVICE(iommu)->intr_supported) {
+ if (!x86_iommu_ir_supported(X86_IOMMU_DEVICE(iommu))) {
trace_amdvi_err("Interrupt remapping is enabled in the guest but "
"not in the host. Use intremap=on to enable interrupt "
"remapping in amd-iommu.");
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index d97bcbc2f7..8b72735650 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -524,7 +524,6 @@ static int vtd_get_root_entry(IntelIOMMUState *s, uint8_t index,
addr = s->root + index * sizeof(*re);
if (dma_memory_read(&address_space_memory, addr, re, sizeof(*re))) {
- trace_vtd_re_invalid(re->rsvd, re->val);
re->val = 0;
return -VTD_FR_ROOT_TABLE_INV;
}
@@ -545,7 +544,6 @@ static int vtd_get_context_entry_from_root(VTDRootEntry *root, uint8_t index,
/* we have checked that root entry is present */
addr = (root->val & VTD_ROOT_ENTRY_CTP) + index * sizeof(*ce);
if (dma_memory_read(&address_space_memory, addr, ce, sizeof(*ce))) {
- trace_vtd_re_invalid(root->rsvd, root->val);
return -VTD_FR_CONTEXT_TABLE_INV;
}
ce->lo = le64_to_cpu(ce->lo);
@@ -630,16 +628,20 @@ static inline bool vtd_ce_type_check(X86IOMMUState *x86_iommu,
break;
case VTD_CONTEXT_TT_DEV_IOTLB:
if (!x86_iommu->dt_supported) {
+ error_report_once("%s: DT specified but not supported", __func__);
return false;
}
break;
case VTD_CONTEXT_TT_PASS_THROUGH:
if (!x86_iommu->pt_supported) {
+ error_report_once("%s: PT specified but not supported", __func__);
return false;
}
break;
default:
/* Unknwon type */
+ error_report_once("%s: unknown ce type: %"PRIu32, __func__,
+ vtd_ce_get_type(ce));
return false;
}
return true;
@@ -1003,7 +1005,9 @@ static int vtd_dev_to_context_entry(IntelIOMMUState *s, uint8_t bus_num,
}
if (re.rsvd || (re.val & VTD_ROOT_ENTRY_RSVD(s->aw_bits))) {
- trace_vtd_re_invalid(re.rsvd, re.val);
+ error_report_once("%s: invalid root entry: rsvd=0x%"PRIx64
+ ", val=0x%"PRIx64" (reserved nonzero)",
+ __func__, re.rsvd, re.val);
return -VTD_FR_ROOT_ENTRY_RSVD;
}
@@ -1020,19 +1024,23 @@ static int vtd_dev_to_context_entry(IntelIOMMUState *s, uint8_t bus_num,
if ((ce->hi & VTD_CONTEXT_ENTRY_RSVD_HI) ||
(ce->lo & VTD_CONTEXT_ENTRY_RSVD_LO(s->aw_bits))) {
- trace_vtd_ce_invalid(ce->hi, ce->lo);
+ error_report_once("%s: invalid context entry: hi=%"PRIx64
+ ", lo=%"PRIx64" (reserved nonzero)",
+ __func__, ce->hi, ce->lo);
return -VTD_FR_CONTEXT_ENTRY_RSVD;
}
/* Check if the programming of context-entry is valid */
if (!vtd_is_level_supported(s, vtd_ce_get_level(ce))) {
- trace_vtd_ce_invalid(ce->hi, ce->lo);
+ error_report_once("%s: invalid context entry: hi=%"PRIx64
+ ", lo=%"PRIx64" (level %d not supported)",
+ __func__, ce->hi, ce->lo, vtd_ce_get_level(ce));
return -VTD_FR_CONTEXT_ENTRY_INV;
}
/* Do translation type check */
if (!vtd_ce_type_check(x86_iommu, ce)) {
- trace_vtd_ce_invalid(ce->hi, ce->lo);
+ /* Errors dumped in vtd_ce_type_check() */
return -VTD_FR_CONTEXT_ENTRY_INV;
}
@@ -1878,7 +1886,9 @@ static bool vtd_process_wait_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc)
{
if ((inv_desc->hi & VTD_INV_DESC_WAIT_RSVD_HI) ||
(inv_desc->lo & VTD_INV_DESC_WAIT_RSVD_LO)) {
- trace_vtd_inv_desc_wait_invalid(inv_desc->hi, inv_desc->lo);
+ error_report_once("%s: invalid wait desc: hi=%"PRIx64", lo=%"PRIx64
+ " (reserved nonzero)", __func__, inv_desc->hi,
+ inv_desc->lo);
return false;
}
if (inv_desc->lo & VTD_INV_DESC_WAIT_SW) {
@@ -1901,7 +1911,9 @@ static bool vtd_process_wait_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc)
/* Interrupt flag */
vtd_generate_completion_event(s);
} else {
- trace_vtd_inv_desc_wait_invalid(inv_desc->hi, inv_desc->lo);
+ error_report_once("%s: invalid wait desc: hi=%"PRIx64", lo=%"PRIx64
+ " (unknown type)", __func__, inv_desc->hi,
+ inv_desc->lo);
return false;
}
return true;
@@ -1913,7 +1925,9 @@ static bool vtd_process_context_cache_desc(IntelIOMMUState *s,
uint16_t sid, fmask;
if ((inv_desc->lo & VTD_INV_DESC_CC_RSVD) || inv_desc->hi) {
- trace_vtd_inv_desc_cc_invalid(inv_desc->hi, inv_desc->lo);
+ error_report_once("%s: invalid cc inv desc: hi=%"PRIx64", lo=%"PRIx64
+ " (reserved nonzero)", __func__, inv_desc->hi,
+ inv_desc->lo);
return false;
}
switch (inv_desc->lo & VTD_INV_DESC_CC_G) {
@@ -1932,7 +1946,9 @@ static bool vtd_process_context_cache_desc(IntelIOMMUState *s,
break;
default:
- trace_vtd_inv_desc_cc_invalid(inv_desc->hi, inv_desc->lo);
+ error_report_once("%s: invalid cc inv desc: hi=%"PRIx64", lo=%"PRIx64
+ " (invalid type)", __func__, inv_desc->hi,
+ inv_desc->lo);
return false;
}
return true;
@@ -1946,7 +1962,9 @@ static bool vtd_process_iotlb_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc)
if ((inv_desc->lo & VTD_INV_DESC_IOTLB_RSVD_LO) ||
(inv_desc->hi & VTD_INV_DESC_IOTLB_RSVD_HI)) {
- trace_vtd_inv_desc_iotlb_invalid(inv_desc->hi, inv_desc->lo);
+ error_report_once("%s: invalid iotlb inv desc: hi=0x%"PRIx64
+ ", lo=0x%"PRIx64" (reserved bits unzero)\n",
+ __func__, inv_desc->hi, inv_desc->lo);
return false;
}
@@ -1965,14 +1983,20 @@ static bool vtd_process_iotlb_desc(IntelIOMMUState *s, VTDInvDesc *inv_desc)
addr = VTD_INV_DESC_IOTLB_ADDR(inv_desc->hi);
am = VTD_INV_DESC_IOTLB_AM(inv_desc->hi);
if (am > VTD_MAMV) {
- trace_vtd_inv_desc_iotlb_invalid(inv_desc->hi, inv_desc->lo);
+ error_report_once("%s: invalid iotlb inv desc: hi=0x%"PRIx64
+ ", lo=0x%"PRIx64" (am=%u > VTD_MAMV=%u)\n",
+ __func__, inv_desc->hi, inv_desc->lo,
+ am, (unsigned)VTD_MAMV);
return false;
}
vtd_iotlb_page_invalidate(s, domain_id, addr, am);
break;
default:
- trace_vtd_inv_desc_iotlb_invalid(inv_desc->hi, inv_desc->lo);
+ error_report_once("%s: invalid iotlb inv desc: hi=0x%"PRIx64
+ ", lo=0x%"PRIx64" (type mismatch: 0x%llx)\n",
+ __func__, inv_desc->hi, inv_desc->lo,
+ inv_desc->lo & VTD_INV_DESC_IOTLB_G);
return false;
}
return true;
@@ -2012,7 +2036,9 @@ static bool vtd_process_device_iotlb_desc(IntelIOMMUState *s,
if ((inv_desc->lo & VTD_INV_DESC_DEVICE_IOTLB_RSVD_LO) ||
(inv_desc->hi & VTD_INV_DESC_DEVICE_IOTLB_RSVD_HI)) {
- trace_vtd_inv_desc_iotlb_invalid(inv_desc->hi, inv_desc->lo);
+ error_report_once("%s: invalid dev-iotlb inv desc: hi=%"PRIx64
+ ", lo=%"PRIx64" (reserved nonzero)", __func__,
+ inv_desc->hi, inv_desc->lo);
return false;
}
@@ -2103,7 +2129,9 @@ static bool vtd_process_inv_desc(IntelIOMMUState *s)
break;
default:
- trace_vtd_inv_desc_invalid(inv_desc.hi, inv_desc.lo);
+ error_report_once("%s: invalid inv desc: hi=%"PRIx64", lo=%"PRIx64
+ " (unknown type)", __func__, inv_desc.hi,
+ inv_desc.lo);
return false;
}
s->iq_head++;
@@ -2540,7 +2568,7 @@ static IOMMUTLBEntry vtd_iommu_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
__func__, pci_bus_num(vtd_as->bus),
VTD_PCI_SLOT(vtd_as->devfn),
VTD_PCI_FUNC(vtd_as->devfn),
- iotlb.iova);
+ addr);
}
return iotlb;
@@ -2628,9 +2656,10 @@ static Property vtd_properties[] = {
DEFINE_PROP_ON_OFF_AUTO("eim", IntelIOMMUState, intr_eim,
ON_OFF_AUTO_AUTO),
DEFINE_PROP_BOOL("x-buggy-eim", IntelIOMMUState, buggy_eim, false),
- DEFINE_PROP_UINT8("x-aw-bits", IntelIOMMUState, aw_bits,
+ DEFINE_PROP_UINT8("aw-bits", IntelIOMMUState, aw_bits,
VTD_HOST_ADDRESS_WIDTH),
DEFINE_PROP_BOOL("caching-mode", IntelIOMMUState, caching_mode, FALSE),
+ DEFINE_PROP_BOOL("dma-drain", IntelIOMMUState, dma_drain, true),
DEFINE_PROP_END_OF_LIST(),
};
@@ -3119,6 +3148,9 @@ static void vtd_init(IntelIOMMUState *s)
s->cap = VTD_CAP_FRO | VTD_CAP_NFR | VTD_CAP_ND |
VTD_CAP_MAMV | VTD_CAP_PSI | VTD_CAP_SLLPS |
VTD_CAP_SAGAW_39bit | VTD_CAP_MGAW(s->aw_bits);
+ if (s->dma_drain) {
+ s->cap |= VTD_CAP_DRAIN;
+ }
if (s->aw_bits == VTD_HOST_AW_48BIT) {
s->cap |= VTD_CAP_SAGAW_48bit;
}
@@ -3137,7 +3169,7 @@ static void vtd_init(IntelIOMMUState *s)
vtd_paging_entry_rsvd_field[7] = VTD_SPTE_LPAGE_L3_RSVD_MASK(s->aw_bits);
vtd_paging_entry_rsvd_field[8] = VTD_SPTE_LPAGE_L4_RSVD_MASK(s->aw_bits);
- if (x86_iommu->intr_supported) {
+ if (x86_iommu_ir_supported(x86_iommu)) {
s->ecap |= VTD_ECAP_IR | VTD_ECAP_MHMV;
if (s->intr_eim == ON_OFF_AUTO_ON) {
s->ecap |= VTD_ECAP_EIM;
@@ -3238,14 +3270,14 @@ static bool vtd_decide_config(IntelIOMMUState *s, Error **errp)
{
X86IOMMUState *x86_iommu = X86_IOMMU_DEVICE(s);
- if (s->intr_eim == ON_OFF_AUTO_ON && !x86_iommu->intr_supported) {
+ if (s->intr_eim == ON_OFF_AUTO_ON && !x86_iommu_ir_supported(x86_iommu)) {
error_setg(errp, "eim=on cannot be selected without intremap=on");
return false;
}
if (s->intr_eim == ON_OFF_AUTO_AUTO) {
s->intr_eim = (kvm_irqchip_in_kernel() || s->buggy_eim)
- && x86_iommu->intr_supported ?
+ && x86_iommu_ir_supported(x86_iommu) ?
ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
}
if (s->intr_eim == ON_OFF_AUTO_ON && !s->buggy_eim) {
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index d084099ed9..00e9edbc66 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -203,6 +203,9 @@
#define VTD_CAP_MAMV (VTD_MAMV << 48)
#define VTD_CAP_PSI (1ULL << 39)
#define VTD_CAP_SLLPS ((1ULL << 34) | (1ULL << 35))
+#define VTD_CAP_DRAIN_WRITE (1ULL << 54)
+#define VTD_CAP_DRAIN_READ (1ULL << 55)
+#define VTD_CAP_DRAIN (VTD_CAP_DRAIN_READ | VTD_CAP_DRAIN_WRITE)
#define VTD_CAP_CM (1ULL << 7)
/* Supported Adjusted Guest Address Widths */
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 115bc2825c..f248662e97 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -37,7 +37,7 @@
#include "hw/pci/pci_bus.h"
#include "hw/nvram/fw_cfg.h"
#include "hw/timer/hpet.h"
-#include "hw/smbios/smbios.h"
+#include "hw/firmware/smbios.h"
#include "hw/loader.h"
#include "elf.h"
#include "multiboot.h"
@@ -1244,7 +1244,7 @@ void pc_machine_done(Notifier *notifier, void *data)
if (pcms->apic_id_limit > 255 && !xen_enabled()) {
IntelIOMMUState *iommu = INTEL_IOMMU_DEVICE(x86_iommu_get_default());
- if (!iommu || !iommu->x86_iommu.intr_supported ||
+ if (!iommu || !x86_iommu_ir_supported(X86_IOMMU_DEVICE(iommu)) ||
iommu->intr_eim != ON_OFF_AUTO_ON) {
error_report("current -smp configuration requires "
"Extended Interrupt Mode enabled. "
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 6981cfa740..7f1cb527b5 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -30,7 +30,7 @@
#include "hw/i386/pc.h"
#include "hw/i386/apic.h"
#include "hw/display/ramfb.h"
-#include "hw/smbios/smbios.h"
+#include "hw/firmware/smbios.h"
#include "hw/pci/pci.h"
#include "hw/pci/pci_ids.h"
#include "hw/usb.h"
@@ -368,7 +368,7 @@ static void pc_compat_1_2(MachineState *machine)
x86_cpu_change_kvm_default("kvm-pv-eoi", NULL);
}
-/* PC compat function for pc-0.10 to pc-0.13 */
+/* PC compat function for pc-0.12 and pc-0.13 */
static void pc_compat_0_13(MachineState *machine)
{
pc_compat_1_2(machine);
@@ -834,6 +834,7 @@ static void pc_i440fx_0_15_machine_options(MachineClass *m)
{
pc_i440fx_1_0_machine_options(m);
m->hw_version = "0.15";
+ m->deprecation_reason = "use a newer machine type instead";
SET_MACHINE_COMPAT(m, PC_COMPAT_0_15);
}
@@ -951,73 +952,6 @@ static void pc_i440fx_0_12_machine_options(MachineClass *m)
DEFINE_I440FX_MACHINE(v0_12, "pc-0.12", pc_compat_0_13,
pc_i440fx_0_12_machine_options);
-
-#define PC_COMPAT_0_11 \
- PC_CPU_MODEL_IDS("0.11") \
- {\
- .driver = "virtio-blk-pci",\
- .property = "vectors",\
- .value = stringify(0),\
- },{\
- .driver = TYPE_PCI_DEVICE,\
- .property = "rombar",\
- .value = stringify(0),\
- },{\
- .driver = "ide-drive",\
- .property = "ver",\
- .value = "0.11",\
- },{\
- .driver = "scsi-disk",\
- .property = "ver",\
- .value = "0.11",\
- },
-
-static void pc_i440fx_0_11_machine_options(MachineClass *m)
-{
- pc_i440fx_0_12_machine_options(m);
- m->hw_version = "0.11";
- m->deprecation_reason = "use a newer machine type instead";
- SET_MACHINE_COMPAT(m, PC_COMPAT_0_11);
-}
-
-DEFINE_I440FX_MACHINE(v0_11, "pc-0.11", pc_compat_0_13,
- pc_i440fx_0_11_machine_options);
-
-
-#define PC_COMPAT_0_10 \
- PC_CPU_MODEL_IDS("0.10") \
- {\
- .driver = "virtio-blk-pci",\
- .property = "class",\
- .value = stringify(PCI_CLASS_STORAGE_OTHER),\
- },{\
- .driver = "virtio-serial-pci",\
- .property = "class",\
- .value = stringify(PCI_CLASS_DISPLAY_OTHER),\
- },{\
- .driver = "virtio-net-pci",\
- .property = "vectors",\
- .value = stringify(0),\
- },{\
- .driver = "ide-drive",\
- .property = "ver",\
- .value = "0.10",\
- },{\
- .driver = "scsi-disk",\
- .property = "ver",\
- .value = "0.10",\
- },
-
-static void pc_i440fx_0_10_machine_options(MachineClass *m)
-{
- pc_i440fx_0_11_machine_options(m);
- m->hw_version = "0.10";
- SET_MACHINE_COMPAT(m, PC_COMPAT_0_10);
-}
-
-DEFINE_I440FX_MACHINE(v0_10, "pc-0.10", pc_compat_0_13,
- pc_i440fx_0_10_machine_options);
-
typedef struct {
uint16_t gpu_device_id;
uint16_t pch_device_id;
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 58459bdab5..0a3f3f18e4 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -47,7 +47,7 @@
#include "hw/i386/amd_iommu.h"
#include "hw/i386/intel_iommu.h"
#include "hw/display/ramfb.h"
-#include "hw/smbios/smbios.h"
+#include "hw/firmware/smbios.h"
#include "hw/ide/pci.h"
#include "hw/ide/ahci.h"
#include "hw/usb.h"
@@ -304,6 +304,7 @@ static void pc_q35_machine_options(MachineClass *m)
m->units_per_default_bus = 1;
m->default_machine_opts = "firmware=bios-256k.bin";
m->default_display = "std";
+ m->default_kernel_irqchip_split = true;
m->no_floppy = 1;
machine_class_allow_dynamic_sysbus_dev(m, TYPE_AMD_IOMMU_DEVICE);
machine_class_allow_dynamic_sysbus_dev(m, TYPE_INTEL_IOMMU_DEVICE);
@@ -323,6 +324,7 @@ DEFINE_Q35_MACHINE(v4_0, "pc-q35-4.0", NULL,
static void pc_q35_3_1_machine_options(MachineClass *m)
{
pc_q35_4_0_machine_options(m);
+ m->default_kernel_irqchip_split = false;
m->alias = NULL;
SET_MACHINE_COMPAT(m, PC_COMPAT_3_1);
}
diff --git a/hw/i386/trace-events b/hw/i386/trace-events
index 6ac347d18c..77244fc384 100644
--- a/hw/i386/trace-events
+++ b/hw/i386/trace-events
@@ -5,19 +5,15 @@ x86_iommu_iec_notify(bool global, uint32_t index, uint32_t mask) "Notify IEC inv
# hw/i386/intel_iommu.c
vtd_inv_desc(const char *type, uint64_t hi, uint64_t lo) "invalidate desc type %s high 0x%"PRIx64" low 0x%"PRIx64
-vtd_inv_desc_invalid(uint64_t hi, uint64_t lo) "invalid inv desc hi 0x%"PRIx64" lo 0x%"PRIx64
vtd_inv_desc_cc_domain(uint16_t domain) "context invalidate domain 0x%"PRIx16
vtd_inv_desc_cc_global(void) "context invalidate globally"
vtd_inv_desc_cc_device(uint8_t bus, uint8_t dev, uint8_t fn) "context invalidate device %02"PRIx8":%02"PRIx8".%02"PRIx8
vtd_inv_desc_cc_devices(uint16_t sid, uint16_t fmask) "context invalidate devices sid 0x%"PRIx16" fmask 0x%"PRIx16
-vtd_inv_desc_cc_invalid(uint64_t hi, uint64_t lo) "invalid context-cache desc hi 0x%"PRIx64" lo 0x%"PRIx64
vtd_inv_desc_iotlb_global(void) "iotlb invalidate global"
vtd_inv_desc_iotlb_domain(uint16_t domain) "iotlb invalidate whole domain 0x%"PRIx16
vtd_inv_desc_iotlb_pages(uint16_t domain, uint64_t addr, uint8_t mask) "iotlb invalidate domain 0x%"PRIx16" addr 0x%"PRIx64" mask 0x%"PRIx8
-vtd_inv_desc_iotlb_invalid(uint64_t hi, uint64_t lo) "invalid iotlb desc hi 0x%"PRIx64" lo 0x%"PRIx64
vtd_inv_desc_wait_sw(uint64_t addr, uint32_t data) "wait invalidate status write addr 0x%"PRIx64" data 0x%"PRIx32
vtd_inv_desc_wait_irq(const char *msg) "%s"
-vtd_inv_desc_wait_invalid(uint64_t hi, uint64_t lo) "invalid wait desc hi 0x%"PRIx64" lo 0x%"PRIx64
vtd_inv_desc_wait_write_fail(uint64_t hi, uint64_t lo) "write fail for wait desc hi 0x%"PRIx64" lo 0x%"PRIx64
vtd_inv_desc_iec(uint32_t granularity, uint32_t index, uint32_t mask) "granularity 0x%"PRIx32" index 0x%"PRIx32" mask 0x%"PRIx32
vtd_inv_qi_enable(bool enable) "enabled %d"
@@ -27,9 +23,7 @@ vtd_inv_qi_tail(uint16_t head) "write tail %d"
vtd_inv_qi_fetch(void) ""
vtd_context_cache_reset(void) ""
vtd_re_not_present(uint8_t bus) "Root entry bus %"PRIu8" not present"
-vtd_re_invalid(uint64_t hi, uint64_t lo) "invalid root entry hi 0x%"PRIx64" lo 0x%"PRIx64
vtd_ce_not_present(uint8_t bus, uint8_t devfn) "Context entry bus %"PRIu8" devfn %"PRIu8" not present"
-vtd_ce_invalid(uint64_t hi, uint64_t lo) "invalid context entry hi 0x%"PRIx64" lo 0x%"PRIx64
vtd_iotlb_page_hit(uint16_t sid, uint64_t addr, uint64_t slpte, uint16_t domain) "IOTLB page hit sid 0x%"PRIx16" iova 0x%"PRIx64" slpte 0x%"PRIx64" domain 0x%"PRIx16
vtd_iotlb_page_update(uint16_t sid, uint64_t addr, uint64_t slpte, uint16_t domain) "IOTLB page update sid 0x%"PRIx16" iova 0x%"PRIx64" slpte 0x%"PRIx64" domain 0x%"PRIx16
vtd_iotlb_cc_hit(uint8_t bus, uint8_t devfn, uint64_t high, uint64_t low, uint32_t gen) "IOTLB context hit bus 0x%"PRIx8" devfn 0x%"PRIx8" high 0x%"PRIx64" low 0x%"PRIx64" gen %"PRIu32
diff --git a/hw/i386/x86-iommu.c b/hw/i386/x86-iommu.c
index abc3c03158..d1534c1ae0 100644
--- a/hw/i386/x86-iommu.c
+++ b/hw/i386/x86-iommu.c
@@ -112,6 +112,7 @@ static void x86_iommu_realize(DeviceState *dev, Error **errp)
PCMachineState *pcms =
PC_MACHINE(object_dynamic_cast(OBJECT(ms), TYPE_PC_MACHINE));
QLIST_INIT(&x86_iommu->iec_notifiers);
+ bool irq_all_kernel = kvm_irqchip_in_kernel() && !kvm_irqchip_is_split();
if (!pcms || !pcms->bus) {
error_setg(errp, "Machine-type '%s' not supported by IOMMU",
@@ -119,9 +120,14 @@ static void x86_iommu_realize(DeviceState *dev, Error **errp)
return;
}
+ /* If the user didn't specify IR, choose a default value for it */
+ if (x86_iommu->intr_supported == ON_OFF_AUTO_AUTO) {
+ x86_iommu->intr_supported = irq_all_kernel ?
+ ON_OFF_AUTO_OFF : ON_OFF_AUTO_ON;
+ }
+
/* Both Intel and AMD IOMMU IR only support "kernel-irqchip={off|split}" */
- if (x86_iommu->intr_supported && kvm_irqchip_in_kernel() &&
- !kvm_irqchip_is_split()) {
+ if (x86_iommu_ir_supported(x86_iommu) && irq_all_kernel) {
error_setg(errp, "Interrupt Remapping cannot work with "
"kernel-irqchip=on, please use 'split|off'.");
return;
@@ -135,7 +141,8 @@ static void x86_iommu_realize(DeviceState *dev, Error **errp)
}
static Property x86_iommu_properties[] = {
- DEFINE_PROP_BOOL("intremap", X86IOMMUState, intr_supported, false),
+ DEFINE_PROP_ON_OFF_AUTO("intremap", X86IOMMUState,
+ intr_supported, ON_OFF_AUTO_AUTO),
DEFINE_PROP_BOOL("device-iotlb", X86IOMMUState, dt_supported, false),
DEFINE_PROP_BOOL("pt", X86IOMMUState, pt_supported, true),
DEFINE_PROP_END_OF_LIST(),
@@ -148,6 +155,11 @@ static void x86_iommu_class_init(ObjectClass *klass, void *data)
dc->props = x86_iommu_properties;
}
+bool x86_iommu_ir_supported(X86IOMMUState *s)
+{
+ return s->intr_supported == ON_OFF_AUTO_ON;
+}
+
static const TypeInfo x86_iommu_info = {
.name = TYPE_X86_IOMMU_DEVICE,
.parent = TYPE_SYS_BUS_DEVICE,