mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-06 17:23:56 -06:00
pci, pc, virtio, misc bugfixes
A bunch of bugfixes - some of these will make sense for 2.1.2 I put Cc: qemu-stable included where appropriate. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJUGyniAAoJECgfDbjSjVRpxg0H/j4jSEWHm/4uKSly6W4MXxhN LghE5iAaO3awU88RiRPW/m/g6sagD9RuQAHteHkvyZ6py/li0IFvLtl66OczeSgc rnM2n9MeYfi5Q05T+ygjqYY2ynosYhrI4iPmsnKqbqLi+WWwQHFKuYKNcNmQjmJu Sg4KDz+W4p5j/pMUZdgf4lse3PaLXoMy4IA1HC8U1WmwvyNLZrPRTXhFn1hFbxU6 Rf604wz6gkAFvwizt2SoRMOIF4w0meCKemY1wqcwOeDWqP6Bj76RnRCrVR06AgnX ngVsrP5SrWymqwFUP9ZpeNdBOQSxXE3zT1cE6JU3/KUvTBs6Eur4Dnz7g2mPb8I= =nHHz -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging pci, pc, virtio, misc bugfixes A bunch of bugfixes - some of these will make sense for 2.1.2 I put Cc: qemu-stable included where appropriate. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Thu 18 Sep 2014 19:52:18 BST using RSA key ID D28D5469 # gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" # gpg: aka "Michael S. Tsirkin <mst@redhat.com>" * remotes/mst/tags/for_upstream: pc: leave more space for BIOS allocations virtio-pci: fix migration for pci bus master vhost-user: fix VIRTIO_NET_F_MRG_RXBUF negotiation virtio-pci: enable bus master for old guests Revert "virtio: don't call device on !vm_running" virtio-net: drop assert on vm stop Revert "rng-egd: remove redundant free" qdev: Move global validation to a single function qdev: Rename qdev_prop_check_global() to qdev_prop_check_globals() test-qdev-global-props: Test handling of hotpluggable and non-device types test-qdev-global-props: Initialize not_used=true for all props test-qdev-global-props: Run tests on subprocess tests: disable global props test for old glib test-qdev-global-props: Trivial comment fix hw/machine: Free old values of string properties Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
10e11f4d2b
15 changed files with 236 additions and 75 deletions
|
@ -24,6 +24,7 @@ static void machine_set_accel(Object *obj, const char *value, Error **errp)
|
|||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
g_free(ms->accel);
|
||||
ms->accel = g_strdup(value);
|
||||
}
|
||||
|
||||
|
@ -79,6 +80,7 @@ static void machine_set_kernel(Object *obj, const char *value, Error **errp)
|
|||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
g_free(ms->kernel_filename);
|
||||
ms->kernel_filename = g_strdup(value);
|
||||
}
|
||||
|
||||
|
@ -93,6 +95,7 @@ static void machine_set_initrd(Object *obj, const char *value, Error **errp)
|
|||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
g_free(ms->initrd_filename);
|
||||
ms->initrd_filename = g_strdup(value);
|
||||
}
|
||||
|
||||
|
@ -107,6 +110,7 @@ static void machine_set_append(Object *obj, const char *value, Error **errp)
|
|||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
g_free(ms->kernel_cmdline);
|
||||
ms->kernel_cmdline = g_strdup(value);
|
||||
}
|
||||
|
||||
|
@ -121,6 +125,7 @@ static void machine_set_dtb(Object *obj, const char *value, Error **errp)
|
|||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
g_free(ms->dtb);
|
||||
ms->dtb = g_strdup(value);
|
||||
}
|
||||
|
||||
|
@ -135,6 +140,7 @@ static void machine_set_dumpdtb(Object *obj, const char *value, Error **errp)
|
|||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
g_free(ms->dumpdtb);
|
||||
ms->dumpdtb = g_strdup(value);
|
||||
}
|
||||
|
||||
|
@ -176,6 +182,7 @@ static void machine_set_dt_compatible(Object *obj, const char *value, Error **er
|
|||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
g_free(ms->dt_compatible);
|
||||
ms->dt_compatible = g_strdup(value);
|
||||
}
|
||||
|
||||
|
@ -232,6 +239,7 @@ static void machine_set_firmware(Object *obj, const char *value, Error **errp)
|
|||
{
|
||||
MachineState *ms = MACHINE(obj);
|
||||
|
||||
g_free(ms->firmware);
|
||||
ms->firmware = g_strdup(value);
|
||||
}
|
||||
|
||||
|
|
|
@ -388,28 +388,12 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
|
|||
static int qdev_add_one_global(QemuOpts *opts, void *opaque)
|
||||
{
|
||||
GlobalProperty *g;
|
||||
ObjectClass *oc;
|
||||
|
||||
g = g_malloc0(sizeof(*g));
|
||||
g->driver = qemu_opt_get(opts, "driver");
|
||||
g->property = qemu_opt_get(opts, "property");
|
||||
g->value = qemu_opt_get(opts, "value");
|
||||
oc = object_class_dynamic_cast(object_class_by_name(g->driver),
|
||||
TYPE_DEVICE);
|
||||
if (oc) {
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
if (dc->hotpluggable) {
|
||||
/* If hotpluggable then skip not_used checking. */
|
||||
g->not_used = false;
|
||||
} else {
|
||||
/* Maybe a typo. */
|
||||
g->not_used = true;
|
||||
}
|
||||
} else {
|
||||
/* Maybe a typo. */
|
||||
g->not_used = true;
|
||||
}
|
||||
g->user_provided = true;
|
||||
qdev_prop_register_global(g);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -955,19 +955,35 @@ void qdev_prop_register_global_list(GlobalProperty *props)
|
|||
}
|
||||
}
|
||||
|
||||
int qdev_prop_check_global(void)
|
||||
int qdev_prop_check_globals(void)
|
||||
{
|
||||
GlobalProperty *prop;
|
||||
int ret = 0;
|
||||
|
||||
QTAILQ_FOREACH(prop, &global_props, next) {
|
||||
if (!prop->not_used) {
|
||||
ObjectClass *oc;
|
||||
DeviceClass *dc;
|
||||
if (prop->used) {
|
||||
continue;
|
||||
}
|
||||
if (!prop->user_provided) {
|
||||
continue;
|
||||
}
|
||||
oc = object_class_by_name(prop->driver);
|
||||
oc = object_class_dynamic_cast(oc, TYPE_DEVICE);
|
||||
if (!oc) {
|
||||
error_report("Warning: global %s.%s has invalid class name",
|
||||
prop->driver, prop->property);
|
||||
ret = 1;
|
||||
continue;
|
||||
}
|
||||
dc = DEVICE_CLASS(oc);
|
||||
if (!dc->hotpluggable && !prop->used) {
|
||||
error_report("Warning: global %s.%s=%s not used",
|
||||
prop->driver, prop->property, prop->value);
|
||||
ret = 1;
|
||||
continue;
|
||||
}
|
||||
ret = 1;
|
||||
error_report("Warning: \"-global %s.%s=%s\" not used",
|
||||
prop->driver, prop->property, prop->value);
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -983,7 +999,7 @@ void qdev_prop_set_globals_for_type(DeviceState *dev, const char *typename,
|
|||
if (strcmp(typename, prop->driver) != 0) {
|
||||
continue;
|
||||
}
|
||||
prop->not_used = false;
|
||||
prop->used = true;
|
||||
object_property_parse(OBJECT(dev), prop->value, prop->property, &err);
|
||||
if (err != NULL) {
|
||||
error_propagate(errp, err);
|
||||
|
|
|
@ -72,8 +72,10 @@
|
|||
#define DPRINTF(fmt, ...)
|
||||
#endif
|
||||
|
||||
/* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables. */
|
||||
unsigned acpi_data_size = 0x20000;
|
||||
/* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables
|
||||
* (128K) and other BIOS datastructures (less than 4K reported to be used at
|
||||
* the moment, 32K should be enough for a while). */
|
||||
unsigned acpi_data_size = 0x20000 + 0x8000;
|
||||
void pc_set_legacy_acpi_data_size(void)
|
||||
{
|
||||
acpi_data_size = 0x10000;
|
||||
|
|
|
@ -163,11 +163,11 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
|
|||
if (r < 0) {
|
||||
goto fail;
|
||||
}
|
||||
if (!qemu_has_vnet_hdr_len(options->net_backend,
|
||||
sizeof(struct virtio_net_hdr_mrg_rxbuf))) {
|
||||
net->dev.features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF);
|
||||
}
|
||||
if (backend_kernel) {
|
||||
if (!qemu_has_vnet_hdr_len(options->net_backend,
|
||||
sizeof(struct virtio_net_hdr_mrg_rxbuf))) {
|
||||
net->dev.features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF);
|
||||
}
|
||||
if (~net->dev.features & net->dev.backend_features) {
|
||||
fprintf(stderr, "vhost lacks feature mask %" PRIu64
|
||||
" for backend\n",
|
||||
|
|
|
@ -1125,8 +1125,6 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
|
|||
return num_packets;
|
||||
}
|
||||
|
||||
assert(vdev->vm_running);
|
||||
|
||||
if (q->async_tx.elem.out_num) {
|
||||
virtio_queue_set_notification(q->tx_vq, 0);
|
||||
return num_packets;
|
||||
|
|
|
@ -86,9 +86,6 @@
|
|||
* 12 is historical, and due to x86 page size. */
|
||||
#define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12
|
||||
|
||||
/* Flags track per-device state like workarounds for quirks in older guests. */
|
||||
#define VIRTIO_PCI_FLAG_BUS_MASTER_BUG (1 << 0)
|
||||
|
||||
static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size,
|
||||
VirtIOPCIProxy *dev);
|
||||
|
||||
|
@ -314,12 +311,14 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
|
|||
msix_unuse_all_vectors(&proxy->pci_dev);
|
||||
}
|
||||
|
||||
/* Linux before 2.6.34 sets the device as OK without enabling
|
||||
the PCI device bus master bit. In this case we need to disable
|
||||
some safety checks. */
|
||||
if ((val & VIRTIO_CONFIG_S_DRIVER_OK) &&
|
||||
!(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
|
||||
proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
|
||||
/* Linux before 2.6.34 drives the device without enabling
|
||||
the PCI device bus master bit. Enable it automatically
|
||||
for the guest. This is a PCI spec violation but so is
|
||||
initiating DMA with bus master bit clear. */
|
||||
if (val == (VIRTIO_CONFIG_S_ACKNOWLEDGE | VIRTIO_CONFIG_S_DRIVER)) {
|
||||
pci_default_write_config(&proxy->pci_dev, PCI_COMMAND,
|
||||
proxy->pci_dev.config[PCI_COMMAND] |
|
||||
PCI_COMMAND_MASTER, 1);
|
||||
}
|
||||
break;
|
||||
case VIRTIO_MSI_CONFIG_VECTOR:
|
||||
|
@ -470,13 +469,18 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
|
|||
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
|
||||
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
|
||||
|
||||
uint8_t cmd = proxy->pci_dev.config[PCI_COMMAND];
|
||||
|
||||
pci_default_write_config(pci_dev, address, val, len);
|
||||
|
||||
if (range_covers_byte(address, len, PCI_COMMAND) &&
|
||||
!(pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER) &&
|
||||
!(proxy->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) {
|
||||
(cmd & PCI_COMMAND_MASTER)) {
|
||||
/* Bus driver disables bus mastering - make it act
|
||||
* as a kind of reset to render the device quiescent. */
|
||||
virtio_pci_stop_ioeventfd(proxy);
|
||||
virtio_set_status(vdev, vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
|
||||
virtio_reset(vdev);
|
||||
msix_unuse_all_vectors(&proxy->pci_dev);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -885,11 +889,19 @@ static void virtio_pci_vmstate_change(DeviceState *d, bool running)
|
|||
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
|
||||
|
||||
if (running) {
|
||||
/* Try to find out if the guest has bus master disabled, but is
|
||||
in ready state. Then we have a buggy guest OS. */
|
||||
if ((vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
|
||||
!(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
|
||||
proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
|
||||
/* Linux before 2.6.34 drives the device without enabling
|
||||
the PCI device bus master bit. Enable it automatically
|
||||
for the guest. This is a PCI spec violation but so is
|
||||
initiating DMA with bus master bit clear.
|
||||
Note: this only makes a difference when migrating
|
||||
across QEMU versions from an old QEMU, as for new QEMU
|
||||
bus master and driver bits are always in sync.
|
||||
TODO: consider enabling conditionally for compat machine types. */
|
||||
if (vdev->status & (VIRTIO_CONFIG_S_ACKNOWLEDGE |
|
||||
VIRTIO_CONFIG_S_DRIVER)) {
|
||||
pci_default_write_config(&proxy->pci_dev, PCI_COMMAND,
|
||||
proxy->pci_dev.config[PCI_COMMAND] |
|
||||
PCI_COMMAND_MASTER, 1);
|
||||
}
|
||||
virtio_pci_start_ioeventfd(proxy);
|
||||
} else {
|
||||
|
@ -1030,7 +1042,6 @@ static void virtio_pci_reset(DeviceState *qdev)
|
|||
virtio_pci_stop_ioeventfd(proxy);
|
||||
virtio_bus_reset(bus);
|
||||
msix_unuse_all_vectors(&proxy->pci_dev);
|
||||
proxy->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
|
||||
}
|
||||
|
||||
static Property virtio_pci_properties[] = {
|
||||
|
|
|
@ -1108,10 +1108,7 @@ static void virtio_vmstate_change(void *opaque, int running, RunState state)
|
|||
BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));
|
||||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
||||
bool backend_run = running && (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK);
|
||||
|
||||
if (running) {
|
||||
vdev->vm_running = running;
|
||||
}
|
||||
vdev->vm_running = running;
|
||||
|
||||
if (backend_run) {
|
||||
virtio_set_status(vdev, vdev->status);
|
||||
|
@ -1124,10 +1121,6 @@ static void virtio_vmstate_change(void *opaque, int running, RunState state)
|
|||
if (!backend_run) {
|
||||
virtio_set_status(vdev, vdev->status);
|
||||
}
|
||||
|
||||
if (!running) {
|
||||
vdev->vm_running = running;
|
||||
}
|
||||
}
|
||||
|
||||
void virtio_init(VirtIODevice *vdev, const char *name,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue