提交 7c823bc5 编写于 作者: P Peter Maydell

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: NMichael 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: NPeter Maydell <peter.maydell@linaro.org>
......@@ -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);
method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
aml_append(method, aml_call1(CPU_EJECT_METHOD, uid));
aml_append(dev, method);
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,
......
......@@ -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,
......
......@@ -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()
};
......
......@@ -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(),
};
......
......@@ -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,
......
......@@ -1073,10 +1073,8 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
.index = vhost_vq_index,
};
int r;
int a;
a = virtio_queue_get_desc_addr(vdev, idx);
if (a == 0) {
if (virtio_queue_get_desc_addr(vdev, idx) == 0) {
/* Don't stop the virtqueue which might have not been started */
return;
}
......
......@@ -2006,14 +2006,25 @@ static int virtio_set_features_nocheck(VirtIODevice *vdev, uint64_t val)
int virtio_set_features(VirtIODevice *vdev, uint64_t val)
{
/*
int ret;
/*
* The driver must not attempt to set features after feature negotiation
* has finished.
*/
if (vdev->status & VIRTIO_CONFIG_S_FEATURES_OK) {
return -EINVAL;
}
return virtio_set_features_nocheck(vdev, val);
ret = virtio_set_features_nocheck(vdev, val);
if (!ret && virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
/* VIRTIO_RING_F_EVENT_IDX changes the size of the caches. */
int i;
for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
if (vdev->vq[i].vring.num != 0) {
virtio_init_region_cache(vdev, i);
}
}
}
return ret;
}
int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
......
......@@ -133,11 +133,19 @@ typedef struct PCIBridgeQemuCap {
#define REDHAT_PCI_CAP_RESOURCE_RESERVE 1
/*
* PCI BUS/IO/MEM/PREFMEM additional resources recorded as a
* capability in PCI configuration space to reserve on firmware init.
*/
typedef struct PCIResReserve {
uint32_t bus;
uint64_t io;
uint64_t mem_non_pref;
uint64_t mem_pref_32;
uint64_t mem_pref_64;
} PCIResReserve;
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);
#endif /* QEMU_PCI_BRIDGE_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册