Commit 7c823bc5 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging



pci, pc, virtio: fixes, features

pci resource capability + misc fixes everywhere.

Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>

# gpg: Signature made Fri 07 Sep 2018 22:50:38 BST
# gpg:                using RSA key 281F0DB8D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>"
# Primary key fingerprint: 0270 606B 6F3C DF3D 0B17  0970 C350 3912 AFBE 8E67
#      Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA  8A0D 281F 0DB8 D28D 5469

* remotes/mst/tags/for_upstream:
  tests: update acpi expected files
  vhost: fix invalid downcast
  pc: make sure that guest isn't able to unplug the first cpu
  hw/pci: add PCI resource reserve capability to legacy PCI bridge
  hw/pci: factor PCI reserve resources to a separate structure
  virtio: update MemoryRegionCaches when guest negotiates features
  pc: acpi: revert back to 1 SRAT entry for hotpluggable area

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 741e1a61 d2a1b1d6
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -117,7 +117,7 @@ static void cpu_hotplug_wr(void *opaque, hwaddr addr, uint64_t data,
            DeviceState *dev = NULL;
            HotplugHandler *hotplug_ctrl = NULL;

            if (!cdev->cpu) {
            if (!cdev->cpu || cdev->cpu == first_cpu) {
                trace_cpuhp_acpi_ejecting_invalid_cpu(cpu_st->selector);
                break;
            }
@@ -541,9 +541,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
                aml_buffer(madt_buf->len, (uint8_t *)madt_buf->data)));
            g_array_free(madt_buf, true);

            if (CPU(arch_ids->cpus[i].cpu) != first_cpu) {
                method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
                aml_append(method, aml_call1(CPU_EJECT_METHOD, uid));
                aml_append(dev, method);
            }

            method = aml_method("_OST", 3, AML_SERIALIZED);
            aml_append(method,
+12 −61
Original line number Diff line number Diff line
@@ -2251,64 +2251,6 @@ build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog)
#define HOLE_640K_START  (640 * KiB)
#define HOLE_640K_END   (1 * MiB)

static void build_srat_hotpluggable_memory(GArray *table_data, uint64_t base,
                                           uint64_t len, int default_node)
{
    MemoryDeviceInfoList *info_list = qmp_memory_device_list();
    MemoryDeviceInfoList *info;
    MemoryDeviceInfo *mi;
    PCDIMMDeviceInfo *di;
    uint64_t end = base + len, cur, size;
    bool is_nvdimm;
    AcpiSratMemoryAffinity *numamem;
    MemoryAffinityFlags flags;

    for (cur = base, info = info_list;
         cur < end;
         cur += size, info = info->next) {
        numamem = acpi_data_push(table_data, sizeof *numamem);

        if (!info) {
            /*
             * Entry is required for Windows to enable memory hotplug in OS
             * and for Linux to enable SWIOTLB when booted with less than
             * 4G of RAM. Windows works better if the entry sets proximity
             * to the highest NUMA node in the machine at the end of the
             * reserved space.
             * Memory devices may override proximity set by this entry,
             * providing _PXM method if necessary.
             */
            build_srat_memory(numamem, end - 1, 1, default_node,
                              MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
            break;
        }

        mi = info->value;
        is_nvdimm = (mi->type == MEMORY_DEVICE_INFO_KIND_NVDIMM);
        di = !is_nvdimm ? mi->u.dimm.data : mi->u.nvdimm.data;

        if (cur < di->addr) {
            build_srat_memory(numamem, cur, di->addr - cur, default_node,
                              MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
            numamem = acpi_data_push(table_data, sizeof *numamem);
        }

        size = di->size;

        flags = MEM_AFFINITY_ENABLED;
        if (di->hotpluggable) {
            flags |= MEM_AFFINITY_HOTPLUGGABLE;
        }
        if (is_nvdimm) {
            flags |= MEM_AFFINITY_NON_VOLATILE;
        }

        build_srat_memory(numamem, di->addr, size, di->node, flags);
    }

    qapi_free_MemoryDeviceInfoList(info_list);
}

static void
build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
{
@@ -2414,10 +2356,19 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
        build_srat_memory(numamem, 0, 0, 0, MEM_AFFINITY_NOFLAGS);
    }

    /*
     * Entry is required for Windows to enable memory hotplug in OS
     * and for Linux to enable SWIOTLB when booted with less than
     * 4G of RAM. Windows works better if the entry sets proximity
     * to the highest NUMA node in the machine.
     * Memory devices may override proximity set by this entry,
     * providing _PXM method if necessary.
     */
    if (hotplugabble_address_space_size) {
        build_srat_hotpluggable_memory(table_data, machine->device_memory->base,
                                       hotplugabble_address_space_size,
                                       pcms->numa_nodes - 1);
        numamem = acpi_data_push(table_data, sizeof *numamem);
        build_srat_memory(numamem, machine->device_memory->base,
                          hotplugabble_address_space_size, pcms->numa_nodes - 1,
                          MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
    }

    build_header(linker, table_data,
+17 −16
Original line number Diff line number Diff line
@@ -29,12 +29,8 @@ typedef struct GenPCIERootPort {

    bool migrate_msix;

    /* additional resources to reserve on firmware init */
    uint32_t bus_reserve;
    uint64_t io_reserve;
    uint64_t mem_reserve;
    uint64_t pref32_reserve;
    uint64_t pref64_reserve;
    /* additional resources to reserve */
    PCIResReserve res_reserve;
} GenPCIERootPort;

static uint8_t gen_rp_aer_vector(const PCIDevice *d)
@@ -82,16 +78,15 @@ static void gen_rp_realize(DeviceState *dev, Error **errp)
        return;
    }

    int rc = pci_bridge_qemu_reserve_cap_init(d, 0, grp->bus_reserve,
            grp->io_reserve, grp->mem_reserve, grp->pref32_reserve,
            grp->pref64_reserve, errp);
    int rc = pci_bridge_qemu_reserve_cap_init(d, 0,
                                              grp->res_reserve, errp);

    if (rc < 0) {
        rpc->parent_class.exit(d);
        return;
    }

    if (!grp->io_reserve) {
    if (!grp->res_reserve.io) {
        pci_word_test_and_clear_mask(d->wmask + PCI_COMMAND,
                                     PCI_COMMAND_IO);
        d->wmask[PCI_IO_BASE] = 0;
@@ -117,12 +112,18 @@ static const VMStateDescription vmstate_rp_dev = {
};

static Property gen_rp_props[] = {
    DEFINE_PROP_BOOL("x-migrate-msix", GenPCIERootPort, migrate_msix, true),
    DEFINE_PROP_UINT32("bus-reserve", GenPCIERootPort, bus_reserve, -1),
    DEFINE_PROP_SIZE("io-reserve", GenPCIERootPort, io_reserve, -1),
    DEFINE_PROP_SIZE("mem-reserve", GenPCIERootPort, mem_reserve, -1),
    DEFINE_PROP_SIZE("pref32-reserve", GenPCIERootPort, pref32_reserve, -1),
    DEFINE_PROP_SIZE("pref64-reserve", GenPCIERootPort, pref64_reserve, -1),
    DEFINE_PROP_BOOL("x-migrate-msix", GenPCIERootPort,
                     migrate_msix, true),
    DEFINE_PROP_UINT32("bus-reserve", GenPCIERootPort,
                       res_reserve.bus, -1),
    DEFINE_PROP_SIZE("io-reserve", GenPCIERootPort,
                     res_reserve.io, -1),
    DEFINE_PROP_SIZE("mem-reserve", GenPCIERootPort,
                     res_reserve.mem_non_pref, -1),
    DEFINE_PROP_SIZE("pref32-reserve", GenPCIERootPort,
                     res_reserve.mem_pref_32, -1),
    DEFINE_PROP_SIZE("pref64-reserve", GenPCIERootPort,
                     res_reserve.mem_pref_64, -1),
    DEFINE_PROP_END_OF_LIST()
};

+24 −0
Original line number Diff line number Diff line
@@ -46,6 +46,9 @@ struct PCIBridgeDev {
    uint32_t flags;

    OnOffAuto msi;

    /* additional resources to reserve */
    PCIResReserve res_reserve;
};
typedef struct PCIBridgeDev PCIBridgeDev;

@@ -95,6 +98,12 @@ static void pci_bridge_dev_realize(PCIDevice *dev, Error **errp)
        error_free(local_err);
    }

    err = pci_bridge_qemu_reserve_cap_init(dev, 0,
                                         bridge_dev->res_reserve, errp);
    if (err) {
        goto cap_error;
    }

    if (shpc_present(dev)) {
        /* TODO: spec recommends using 64 bit prefetcheable BAR.
         * Check whether that works well. */
@@ -103,6 +112,8 @@ static void pci_bridge_dev_realize(PCIDevice *dev, Error **errp)
    }
    return;

cap_error:
    msi_uninit(dev);
msi_error:
    slotid_cap_cleanup(dev);
slotid_error:
@@ -116,6 +127,8 @@ shpc_error:
static void pci_bridge_dev_exitfn(PCIDevice *dev)
{
    PCIBridgeDev *bridge_dev = PCI_BRIDGE_DEV(dev);

    pci_del_capability(dev, PCI_CAP_ID_VNDR, sizeof(PCIBridgeQemuCap));
    if (msi_present(dev)) {
        msi_uninit(dev);
    }
@@ -162,6 +175,17 @@ static Property pci_bridge_dev_properties[] = {
                            ON_OFF_AUTO_AUTO),
    DEFINE_PROP_BIT(PCI_BRIDGE_DEV_PROP_SHPC, PCIBridgeDev, flags,
                    PCI_BRIDGE_DEV_F_SHPC_REQ, true),
    DEFINE_PROP_UINT32("bus-reserve", PCIBridgeDev,
                       res_reserve.bus, -1),
    DEFINE_PROP_SIZE("io-reserve", PCIBridgeDev,
                     res_reserve.io, -1),
    DEFINE_PROP_SIZE("mem-reserve", PCIBridgeDev,
                     res_reserve.mem_non_pref, -1),
    DEFINE_PROP_SIZE("pref32-reserve", PCIBridgeDev,
                     res_reserve.mem_pref_32, -1),
    DEFINE_PROP_SIZE("pref64-reserve", PCIBridgeDev,
                     res_reserve.mem_pref_64, -1),

    DEFINE_PROP_END_OF_LIST(),
};

+17 −21
Original line number Diff line number Diff line
@@ -411,38 +411,34 @@ void pci_bridge_map_irq(PCIBridge *br, const char* bus_name,


int pci_bridge_qemu_reserve_cap_init(PCIDevice *dev, int cap_offset,
                                     uint32_t bus_reserve, uint64_t io_reserve,
                                     uint64_t mem_non_pref_reserve,
                                     uint64_t mem_pref_32_reserve,
                                     uint64_t mem_pref_64_reserve,
                                     Error **errp)
                                     PCIResReserve res_reserve, Error **errp)
{
    if (mem_pref_32_reserve != (uint64_t)-1 &&
        mem_pref_64_reserve != (uint64_t)-1) {
    if (res_reserve.mem_pref_32 != (uint64_t)-1 &&
        res_reserve.mem_pref_64 != (uint64_t)-1) {
        error_setg(errp,
                   "PCI resource reserve cap: PREF32 and PREF64 conflict");
        return -EINVAL;
    }

    if (mem_non_pref_reserve != (uint64_t)-1 &&
        mem_non_pref_reserve >= (1ULL << 32)) {
    if (res_reserve.mem_non_pref != (uint64_t)-1 &&
        res_reserve.mem_non_pref >= (1ULL << 32)) {
        error_setg(errp,
                   "PCI resource reserve cap: mem-reserve must be less than 4G");
        return -EINVAL;
    }

    if (mem_pref_32_reserve != (uint64_t)-1 &&
        mem_pref_32_reserve >= (1ULL << 32)) {
    if (res_reserve.mem_pref_32 != (uint64_t)-1 &&
        res_reserve.mem_pref_32 >= (1ULL << 32)) {
        error_setg(errp,
                   "PCI resource reserve cap: pref32-reserve  must be less than 4G");
        return -EINVAL;
    }

    if (bus_reserve == (uint32_t)-1 &&
        io_reserve == (uint64_t)-1 &&
        mem_non_pref_reserve == (uint64_t)-1 &&
        mem_pref_32_reserve == (uint64_t)-1 &&
        mem_pref_64_reserve == (uint64_t)-1) {
    if (res_reserve.bus == (uint32_t)-1 &&
        res_reserve.io == (uint64_t)-1 &&
        res_reserve.mem_non_pref == (uint64_t)-1 &&
        res_reserve.mem_pref_32 == (uint64_t)-1 &&
        res_reserve.mem_pref_64 == (uint64_t)-1) {
        return 0;
    }

@@ -450,11 +446,11 @@ int pci_bridge_qemu_reserve_cap_init(PCIDevice *dev, int cap_offset,
    PCIBridgeQemuCap cap = {
            .len = cap_len,
            .type = REDHAT_PCI_CAP_RESOURCE_RESERVE,
            .bus_res = bus_reserve,
            .io = io_reserve,
            .mem = mem_non_pref_reserve,
            .mem_pref_32 = mem_pref_32_reserve,
            .mem_pref_64 = mem_pref_64_reserve
            .bus_res = res_reserve.bus,
            .io = res_reserve.io,
            .mem = res_reserve.mem_non_pref,
            .mem_pref_32 = res_reserve.mem_pref_32,
            .mem_pref_64 = res_reserve.mem_pref_64
    };

    int offset = pci_add_capability(dev, PCI_CAP_ID_VNDR,
Loading