diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2016-10-18 09:29:43 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2016-10-18 09:29:44 +0100 |
commit | e8ddc2eae5ccc41f0815e5c43e70cb04a7e67e2e (patch) | |
tree | 9c61e0318fe412a4d3f7030b9fdddc2abbb0ad11 /hw | |
parent | 2d02ac10b6644d71c88cc7943e74d7ad6674fff1 (diff) | |
parent | 46c032f3afcc05a0123914609f1003906ba63fda (diff) | |
download | qemu-e8ddc2eae5ccc41f0815e5c43e70cb04a7e67e2e.zip |
Merge remote-tracking branch 'remotes/ehabkost/tags/x86-pull-request' into staging
x86 queue, 2016-10-17
# gpg: Signature made Mon 17 Oct 2016 18:51:07 BST
# gpg: using RSA key 0x2807936F984DC5A6
# gpg: Good signature from "Eduardo Habkost <ehabkost@redhat.com>"
# Primary key fingerprint: 5A32 2FD5 ABC4 D3DB ACCF D1AA 2807 936F 984D C5A6
* remotes/ehabkost/tags/x86-pull-request: (21 commits)
target-i386: Don't use cpu->migratable when filtering features
target-i386: Return runnability information on query-cpu-definitions
target-i386: x86_cpu_load_features() function
target-i386: Unset cannot_destroy_with_object_finalize_yet
target-i386/kvm: cache the return value of kvm_enable_x2apic()
intel_iommu: reject broken EIM
intel_iommu: add OnOffAuto intr_eim as "eim" property
intel_iommu: redo configuraton check in realize
intel_iommu: pass whole remapped addresses to apic
apic: add send_msi() to APICCommonClass
apic: add global apic_get_class()
target-i386: Move warning code outside x86_cpu_filter_features()
qmp: Add runnability information to query-cpu-definitions
target-i386: xsave: Add FP and SSE bits to x86_ext_save_areas
target-i386: Register properties for feature aliases manually
target-i386: Remove underscores from feat_names arrays
target-i386: Make plus_features/minus_features QOM-based
target-i386: Register aliases for feature names with underscores
target-i386: Disable VME by default with TCG
target-i386: List CPU models using subclass list
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/i386/intel_iommu.c | 81 | ||||
-rw-r--r-- | hw/i386/kvm/apic.c | 19 | ||||
-rw-r--r-- | hw/i386/xen/xen_apic.c | 6 | ||||
-rw-r--r-- | hw/intc/apic.c | 8 | ||||
-rw-r--r-- | hw/intc/apic_common.c | 1 |
5 files changed, 86 insertions, 29 deletions
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 2efd69bbd7..1655a65bce 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -21,6 +21,7 @@ #include "qemu/osdep.h" #include "qemu/error-report.h" +#include "qapi/error.h" #include "hw/sysbus.h" #include "exec/address-spaces.h" #include "intel_iommu_internal.h" @@ -32,6 +33,8 @@ #include "hw/i386/x86-iommu.h" #include "hw/pci-host/q35.h" #include "sysemu/kvm.h" +#include "hw/i386/apic_internal.h" +#include "kvm_i386.h" /*#define DEBUG_INTEL_IOMMU*/ #ifdef DEBUG_INTEL_IOMMU @@ -280,18 +283,17 @@ static void vtd_update_iotlb(IntelIOMMUState *s, uint16_t source_id, static void vtd_generate_interrupt(IntelIOMMUState *s, hwaddr mesg_addr_reg, hwaddr mesg_data_reg) { - hwaddr addr; - uint32_t data; + MSIMessage msi; assert(mesg_data_reg < DMAR_REG_SIZE); assert(mesg_addr_reg < DMAR_REG_SIZE); - addr = vtd_get_long_raw(s, mesg_addr_reg); - data = vtd_get_long_raw(s, mesg_data_reg); + msi.address = vtd_get_long_raw(s, mesg_addr_reg); + msi.data = vtd_get_long_raw(s, mesg_data_reg); - VTD_DPRINTF(FLOG, "msi: addr 0x%"PRIx64 " data 0x%"PRIx32, addr, data); - address_space_stl_le(&address_space_memory, addr, data, - MEMTXATTRS_UNSPECIFIED, NULL); + VTD_DPRINTF(FLOG, "msi: addr 0x%"PRIx64 " data 0x%"PRIx32, + msi.address, msi.data); + apic_get_class()->send_msi(&msi); } /* Generate a fault event to software via MSI if conditions are met. @@ -2012,6 +2014,9 @@ static const MemoryRegionOps vtd_mem_ops = { static Property vtd_properties[] = { DEFINE_PROP_UINT32("version", IntelIOMMUState, version, 0), + 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_END_OF_LIST(), }; @@ -2134,6 +2139,7 @@ static void vtd_generate_msi_message(VTDIrq *irq, MSIMessage *msg_out) msg.dest_mode = irq->dest_mode; msg.redir_hint = irq->redir_hint; msg.dest = irq->dest; + msg.__addr_hi = irq->dest & 0xffffff00; msg.__addr_head = cpu_to_le32(0xfee); /* Keep this from original MSI address bits */ msg.__not_used = irq->msi_addr_last_bits; @@ -2293,11 +2299,7 @@ static MemTxResult vtd_mem_ir_write(void *opaque, hwaddr addr, " for device sid 0x%04x", to.address, to.data, sid); - if (dma_memory_write(&address_space_memory, to.address, - &to.data, size)) { - VTD_DPRINTF(GENERAL, "error: fail to write 0x%"PRIx64 - " value 0x%"PRIx32, to.address, to.data); - } + apic_get_class()->send_msi(&to); return MEMTX_OK; } @@ -2382,7 +2384,11 @@ static void vtd_init(IntelIOMMUState *s) s->ecap = VTD_ECAP_QI | VTD_ECAP_IRO; if (x86_iommu->intr_supported) { - s->ecap |= VTD_ECAP_IR | VTD_ECAP_EIM | VTD_ECAP_MHMV; + s->ecap |= VTD_ECAP_IR | VTD_ECAP_MHMV; + if (s->intr_eim == ON_OFF_AUTO_ON) { + s->ecap |= VTD_ECAP_EIM; + } + assert(s->intr_eim != ON_OFF_AUTO_AUTO); } vtd_reset_context_cache(s); @@ -2463,6 +2469,42 @@ static AddressSpace *vtd_host_dma_iommu(PCIBus *bus, void *opaque, int devfn) return &vtd_as->as; } +static bool vtd_decide_config(IntelIOMMUState *s, Error **errp) +{ + X86IOMMUState *x86_iommu = X86_IOMMU_DEVICE(s); + + /* Currently Intel IOMMU IR only support "kernel-irqchip={off|split}" */ + if (x86_iommu->intr_supported && kvm_irqchip_in_kernel() && + !kvm_irqchip_is_split()) { + error_setg(errp, "Intel Interrupt Remapping cannot work with " + "kernel-irqchip=on, please use 'split|off'."); + return false; + } + if (s->intr_eim == ON_OFF_AUTO_ON && !x86_iommu->intr_supported) { + 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 ? + ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF; + } + if (s->intr_eim == ON_OFF_AUTO_ON && !s->buggy_eim) { + if (!kvm_irqchip_in_kernel()) { + error_setg(errp, "eim=on requires accel=kvm,kernel-irqchip=split"); + return false; + } + if (!kvm_enable_x2apic()) { + error_setg(errp, "eim=on requires support on the KVM side" + "(X2APIC_API, first shipped in v4.7)"); + return false; + } + } + + return true; +} + static void vtd_realize(DeviceState *dev, Error **errp) { PCMachineState *pcms = PC_MACHINE(qdev_get_machine()); @@ -2472,6 +2514,11 @@ static void vtd_realize(DeviceState *dev, Error **errp) VTD_DPRINTF(GENERAL, ""); x86_iommu->type = TYPE_INTEL; + + if (!vtd_decide_config(s, errp)) { + return; + } + memset(s->vtd_as_by_bus_num, 0, sizeof(s->vtd_as_by_bus_num)); memory_region_init_io(&s->csrmem, OBJECT(s), &vtd_mem_ops, s, "intel_iommu", DMAR_REG_SIZE); @@ -2486,14 +2533,6 @@ static void vtd_realize(DeviceState *dev, Error **errp) pci_setup_iommu(bus, vtd_host_dma_iommu, dev); /* Pseudo address space under root PCI bus. */ pcms->ioapic_as = vtd_host_dma_iommu(bus, s, Q35_PSEUDO_DEVFN_IOAPIC); - - /* Currently Intel IOMMU IR only support "kernel-irqchip={off|split}" */ - if (x86_iommu->intr_supported && kvm_irqchip_in_kernel() && - !kvm_irqchip_is_split()) { - error_report("Intel Interrupt Remapping cannot work with " - "kernel-irqchip=on, please use 'split|off'."); - exit(1); - } } static void vtd_class_init(ObjectClass *klass, void *data) diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c index c016e63fc2..be55102c00 100644 --- a/hw/i386/kvm/apic.c +++ b/hw/i386/kvm/apic.c @@ -169,6 +169,17 @@ static void kvm_apic_external_nmi(APICCommonState *s) run_on_cpu(CPU(s->cpu), do_inject_external_nmi, s); } +static void kvm_send_msi(MSIMessage *msg) +{ + int ret; + + ret = kvm_irqchip_send_msi(kvm_state, *msg); + if (ret < 0) { + fprintf(stderr, "KVM: injection failed, MSI lost (%s)\n", + strerror(-ret)); + } +} + static uint64_t kvm_apic_mem_read(void *opaque, hwaddr addr, unsigned size) { @@ -179,13 +190,8 @@ static void kvm_apic_mem_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { MSIMessage msg = { .address = addr, .data = data }; - int ret; - ret = kvm_irqchip_send_msi(kvm_state, msg); - if (ret < 0) { - fprintf(stderr, "KVM: injection failed, MSI lost (%s)\n", - strerror(-ret)); - } + kvm_send_msi(&msg); } static const MemoryRegionOps kvm_apic_io_ops = { @@ -232,6 +238,7 @@ static void kvm_apic_class_init(ObjectClass *klass, void *data) k->enable_tpr_reporting = kvm_apic_enable_tpr_reporting; k->vapic_base_update = kvm_apic_vapic_base_update; k->external_nmi = kvm_apic_external_nmi; + k->send_msi = kvm_send_msi; } static const TypeInfo kvm_apic_info = { diff --git a/hw/i386/xen/xen_apic.c b/hw/i386/xen/xen_apic.c index 21d68ee04b..55769eba7e 100644 --- a/hw/i386/xen/xen_apic.c +++ b/hw/i386/xen/xen_apic.c @@ -68,6 +68,11 @@ static void xen_apic_external_nmi(APICCommonState *s) { } +static void xen_send_msi(MSIMessage *msi) +{ + xen_hvm_inject_msi(msi->address, msi->data); +} + static void xen_apic_class_init(ObjectClass *klass, void *data) { APICCommonClass *k = APIC_COMMON_CLASS(klass); @@ -78,6 +83,7 @@ static void xen_apic_class_init(ObjectClass *klass, void *data) k->get_tpr = xen_apic_get_tpr; k->vapic_base_update = xen_apic_vapic_base_update; k->external_nmi = xen_apic_external_nmi; + k->send_msi = xen_send_msi; } static const TypeInfo xen_apic_info = { diff --git a/hw/intc/apic.c b/hw/intc/apic.c index 7bd1d279c4..fe15fb6024 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -740,8 +740,10 @@ static uint32_t apic_mem_readl(void *opaque, hwaddr addr) return val; } -static void apic_send_msi(hwaddr addr, uint32_t data) +static void apic_send_msi(MSIMessage *msi) { + uint64_t addr = msi->address; + uint32_t data = msi->data; uint8_t dest = (addr & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT; uint8_t vector = (data & MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT; uint8_t dest_mode = (addr >> MSI_ADDR_DEST_MODE_SHIFT) & 0x1; @@ -762,7 +764,8 @@ static void apic_mem_writel(void *opaque, hwaddr addr, uint32_t val) * APIC is connected directly to the CPU. * Mapping them on the global bus happens to work because * MSI registers are reserved in APIC MMIO and vice versa. */ - apic_send_msi(addr, val); + MSIMessage msi = { .address = addr, .data = val }; + apic_send_msi(&msi); return; } @@ -913,6 +916,7 @@ static void apic_class_init(ObjectClass *klass, void *data) k->external_nmi = apic_external_nmi; k->pre_save = apic_pre_save; k->post_load = apic_post_load; + k->send_msi = apic_send_msi; } static const TypeInfo apic_info = { diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c index 14ac43c186..8d01c9c875 100644 --- a/hw/intc/apic_common.c +++ b/hw/intc/apic_common.c @@ -18,6 +18,7 @@ * License along with this library; if not, see <http://www.gnu.org/licenses/> */ #include "qemu/osdep.h" +#include "qemu/error-report.h" #include "qapi/error.h" #include "qemu-common.h" #include "cpu.h" |