Commit e8ddc2ea authored by Peter Maydell's avatar Peter Maydell
Browse files

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: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 2d02ac10 46c032f3
Loading
Loading
Loading
Loading
+60 −21
Original line number Diff line number Diff line
@@ -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)
+13 −6
Original line number Diff line number Diff line
@@ -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 = {
+6 −0
Original line number Diff line number Diff line
@@ -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 = {
+6 −2
Original line number Diff line number Diff line
@@ -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 = {
+1 −0
Original line number Diff line number Diff line
@@ -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"
Loading