aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/acpi/nvdimm.c45
-rw-r--r--hw/block/vhost-user-blk.c27
-rw-r--r--hw/display/bcm2835_fb.c2
-rw-r--r--hw/hppa/hppa_sys.h2
-rw-r--r--hw/hppa/machine.c2
-rw-r--r--hw/i386/pc.c31
-rw-r--r--hw/ide/ahci-allwinner.c2
-rw-r--r--hw/ide/ahci.c2
-rw-r--r--hw/ide/ich.c2
-rw-r--r--hw/intc/ioapic.c3
-rw-r--r--hw/net/e1000e.c2
-rw-r--r--hw/net/rocker/rocker_fp.c1
-rw-r--r--hw/ppc/ppc440_uc.c2
-rw-r--r--hw/ppc/sam460ex.c4
-rw-r--r--hw/scsi/vhost-scsi-common.c1
-rw-r--r--hw/scsi/vhost-user-scsi.c20
-rw-r--r--hw/sd/milkymist-memcard.c2
-rw-r--r--hw/usb/desc-msos.c2
-rw-r--r--hw/usb/desc.c2
-rw-r--r--hw/usb/dev-audio.c2
-rw-r--r--hw/usb/dev-bluetooth.c2
-rw-r--r--hw/usb/dev-hid.c2
-rw-r--r--hw/usb/dev-hub.c2
-rw-r--r--hw/usb/dev-mtp.c2
-rw-r--r--hw/usb/dev-network.c2
-rw-r--r--hw/usb/dev-serial.c2
-rw-r--r--hw/usb/dev-smartcard-reader.c2
-rw-r--r--hw/usb/dev-storage.c2
-rw-r--r--hw/usb/dev-uas.c2
-rw-r--r--hw/usb/dev-wacom.c2
-rw-r--r--hw/virtio/vhost-stub.c10
-rw-r--r--hw/virtio/vhost-user.c182
-rw-r--r--hw/virtio/vhost.c9
33 files changed, 318 insertions, 59 deletions
diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 59d6e4254c..87e4280c71 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -170,6 +170,21 @@ struct NvdimmNfitControlRegion {
typedef struct NvdimmNfitControlRegion NvdimmNfitControlRegion;
/*
+ * NVDIMM Platform Capabilities Structure
+ *
+ * Defined in section 5.2.25.9 of ACPI 6.2 Errata A, September 2017
+ */
+struct NvdimmNfitPlatformCaps {
+ uint16_t type;
+ uint16_t length;
+ uint8_t highest_cap;
+ uint8_t reserved[3];
+ uint32_t capabilities;
+ uint8_t reserved2[4];
+} QEMU_PACKED;
+typedef struct NvdimmNfitPlatformCaps NvdimmNfitPlatformCaps;
+
+/*
* Module serial number is a unique number for each device. We use the
* slot id of NVDIMM device to generate this number so that each device
* associates with a different number.
@@ -351,7 +366,23 @@ static void nvdimm_build_structure_dcr(GArray *structures, DeviceState *dev)
JEDEC Annex L Release 3. */);
}
-static GArray *nvdimm_build_device_structure(void)
+/*
+ * ACPI 6.2 Errata A: 5.2.25.9 NVDIMM Platform Capabilities Structure
+ */
+static void
+nvdimm_build_structure_caps(GArray *structures, uint32_t capabilities)
+{
+ NvdimmNfitPlatformCaps *nfit_caps;
+
+ nfit_caps = acpi_data_push(structures, sizeof(*nfit_caps));
+
+ nfit_caps->type = cpu_to_le16(7 /* NVDIMM Platform Capabilities */);
+ nfit_caps->length = cpu_to_le16(sizeof(*nfit_caps));
+ nfit_caps->highest_cap = 31 - clz32(capabilities);
+ nfit_caps->capabilities = cpu_to_le32(capabilities);
+}
+
+static GArray *nvdimm_build_device_structure(AcpiNVDIMMState *state)
{
GSList *device_list = nvdimm_get_device_list();
GArray *structures = g_array_new(false, true /* clear */, 1);
@@ -373,6 +404,10 @@ static GArray *nvdimm_build_device_structure(void)
}
g_slist_free(device_list);
+ if (state->capabilities) {
+ nvdimm_build_structure_caps(structures, state->capabilities);
+ }
+
return structures;
}
@@ -381,16 +416,18 @@ static void nvdimm_init_fit_buffer(NvdimmFitBuffer *fit_buf)
fit_buf->fit = g_array_new(false, true /* clear */, 1);
}
-static void nvdimm_build_fit_buffer(NvdimmFitBuffer *fit_buf)
+static void nvdimm_build_fit_buffer(AcpiNVDIMMState *state)
{
+ NvdimmFitBuffer *fit_buf = &state->fit_buf;
+
g_array_free(fit_buf->fit, true);
- fit_buf->fit = nvdimm_build_device_structure();
+ fit_buf->fit = nvdimm_build_device_structure(state);
fit_buf->dirty = true;
}
void nvdimm_plug(AcpiNVDIMMState *state)
{
- nvdimm_build_fit_buffer(&state->fit_buf);
+ nvdimm_build_fit_buffer(state);
}
static void nvdimm_build_nfit(AcpiNVDIMMState *state, GArray *table_offsets,
diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index 975eae6211..d755223643 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -203,13 +203,11 @@ static uint64_t vhost_user_blk_get_features(VirtIODevice *vdev,
virtio_add_feature(&features, VIRTIO_BLK_F_TOPOLOGY);
virtio_add_feature(&features, VIRTIO_BLK_F_BLK_SIZE);
virtio_add_feature(&features, VIRTIO_BLK_F_FLUSH);
+ virtio_add_feature(&features, VIRTIO_BLK_F_RO);
if (s->config_wce) {
virtio_add_feature(&features, VIRTIO_BLK_F_CONFIG_WCE);
}
- if (s->config_ro) {
- virtio_add_feature(&features, VIRTIO_BLK_F_RO);
- }
if (s->num_queues > 1) {
virtio_add_feature(&features, VIRTIO_BLK_F_MQ);
}
@@ -226,6 +224,7 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VHostUserBlk *s = VHOST_USER_BLK(vdev);
+ VhostUserState *user;
int i, ret;
if (!s->chardev.chr) {
@@ -243,6 +242,15 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
return;
}
+ user = vhost_user_init();
+ if (!user) {
+ error_setg(errp, "vhost-user-blk: failed to init vhost_user");
+ return;
+ }
+
+ user->chr = &s->chardev;
+ s->vhost_user = user;
+
virtio_init(vdev, "virtio-blk", VIRTIO_ID_BLOCK,
sizeof(struct virtio_blk_config));
@@ -258,7 +266,7 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
vhost_dev_set_config_notifier(&s->dev, &blk_ops);
- ret = vhost_dev_init(&s->dev, &s->chardev, VHOST_BACKEND_TYPE_USER, 0);
+ ret = vhost_dev_init(&s->dev, s->vhost_user, VHOST_BACKEND_TYPE_USER, 0);
if (ret < 0) {
error_setg(errp, "vhost-user-blk: vhost initialization failed: %s",
strerror(-ret));
@@ -283,6 +291,10 @@ vhost_err:
virtio_err:
g_free(s->dev.vqs);
virtio_cleanup(vdev);
+
+ vhost_user_cleanup(user);
+ g_free(user);
+ s->vhost_user = NULL;
}
static void vhost_user_blk_device_unrealize(DeviceState *dev, Error **errp)
@@ -294,6 +306,12 @@ static void vhost_user_blk_device_unrealize(DeviceState *dev, Error **errp)
vhost_dev_cleanup(&s->dev);
g_free(s->dev.vqs);
virtio_cleanup(vdev);
+
+ if (s->vhost_user) {
+ vhost_user_cleanup(s->vhost_user);
+ g_free(s->vhost_user);
+ s->vhost_user = NULL;
+ }
}
static void vhost_user_blk_instance_init(Object *obj)
@@ -319,7 +337,6 @@ static Property vhost_user_blk_properties[] = {
DEFINE_PROP_UINT16("num-queues", VHostUserBlk, num_queues, 1),
DEFINE_PROP_UINT32("queue-size", VHostUserBlk, queue_size, 128),
DEFINE_PROP_BIT("config-wce", VHostUserBlk, config_wce, 0, true),
- DEFINE_PROP_BIT("config-ro", VHostUserBlk, config_ro, 0, false),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
index 7eab927652..3355f4c131 100644
--- a/hw/display/bcm2835_fb.c
+++ b/hw/display/bcm2835_fb.c
@@ -26,7 +26,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "hw/display/bcm2835_fb.h"
-#include "hw/display/framebuffer.h"
+#include "framebuffer.h"
#include "ui/pixel_ops.h"
#include "hw/misc/bcm2835_mbox_defs.h"
#include "qemu/log.h"
diff --git a/hw/hppa/hppa_sys.h b/hw/hppa/hppa_sys.h
index 3f6c145120..f5f983bf4c 100644
--- a/hw/hppa/hppa_sys.h
+++ b/hw/hppa/hppa_sys.h
@@ -9,7 +9,7 @@
#include "hw/i386/pc.h"
#include "hw/irq.h"
-#include "hw/hppa/hppa_hardware.h"
+#include "hppa_hardware.h"
PCIBus *dino_init(MemoryRegion *, qemu_irq *, qemu_irq *);
diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c
index a1d6b0ebfb..aba269bb85 100644
--- a/hw/hppa/machine.c
+++ b/hw/hppa/machine.c
@@ -16,7 +16,7 @@
#include "hw/ide.h"
#include "hw/timer/i8254.h"
#include "hw/char/serial.h"
-#include "hw/hppa/hppa_sys.h"
+#include "hppa_sys.h"
#include "qemu/cutils.h"
#include "qapi/error.h"
#include "qemu/log.h"
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 8b0803cb83..f3befe6721 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -2181,6 +2181,33 @@ static void pc_machine_set_nvdimm(Object *obj, bool value, Error **errp)
pcms->acpi_nvdimm_state.is_enabled = value;
}
+static void pc_machine_get_nvdimm_capabilities(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ PCMachineState *pcms = PC_MACHINE(obj);
+ uint32_t value = pcms->acpi_nvdimm_state.capabilities;
+
+ visit_type_uint32(v, name, &value, errp);
+}
+
+static void pc_machine_set_nvdimm_capabilities(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ PCMachineState *pcms = PC_MACHINE(obj);
+ Error *error = NULL;
+ uint32_t value;
+
+ visit_type_uint32(v, name, &value, &error);
+ if (error) {
+ error_propagate(errp, error);
+ return;
+ }
+
+ pcms->acpi_nvdimm_state.capabilities = value;
+}
+
static bool pc_machine_get_smbus(Object *obj, Error **errp)
{
PCMachineState *pcms = PC_MACHINE(obj);
@@ -2394,6 +2421,10 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
object_class_property_add_bool(oc, PC_MACHINE_NVDIMM,
pc_machine_get_nvdimm, pc_machine_set_nvdimm, &error_abort);
+ object_class_property_add(oc, PC_MACHINE_NVDIMM_CAP, "uint32",
+ pc_machine_get_nvdimm_capabilities,
+ pc_machine_set_nvdimm_capabilities, NULL, NULL, &error_abort);
+
object_class_property_add_bool(oc, PC_MACHINE_SMBUS,
pc_machine_get_smbus, pc_machine_set_smbus, &error_abort);
diff --git a/hw/ide/ahci-allwinner.c b/hw/ide/ahci-allwinner.c
index 2fd95078ba..f98e6cb3d4 100644
--- a/hw/ide/ahci-allwinner.c
+++ b/hw/ide/ahci-allwinner.c
@@ -20,7 +20,7 @@
#include "qemu/error-report.h"
#include "sysemu/dma.h"
#include "hw/ide/internal.h"
-#include "hw/ide/ahci_internal.h"
+#include "ahci_internal.h"
#include "trace.h"
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index e22d7be05f..24dbad5125 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -31,7 +31,7 @@
#include "sysemu/dma.h"
#include "hw/ide/internal.h"
#include "hw/ide/pci.h"
-#include "hw/ide/ahci_internal.h"
+#include "ahci_internal.h"
#include "trace.h"
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index 134478ebb2..51c935a0da 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -67,7 +67,7 @@
#include "hw/isa/isa.h"
#include "sysemu/dma.h"
#include "hw/ide/pci.h"
-#include "hw/ide/ahci_internal.h"
+#include "ahci_internal.h"
#define ICH9_MSI_CAP_OFFSET 0x80
#define ICH9_SATA_CAP_OFFSET 0xA8
diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c
index 36139a4db6..c45f073271 100644
--- a/hw/intc/ioapic.c
+++ b/hw/intc/ioapic.c
@@ -28,9 +28,8 @@
#include "hw/i386/apic.h"
#include "hw/i386/ioapic.h"
#include "hw/i386/ioapic_internal.h"
-#include "include/hw/pci/msi.h"
+#include "hw/pci/msi.h"
#include "sysemu/kvm.h"
-#include "target/i386/cpu.h"
#include "hw/i386/apic-msidef.h"
#include "hw/i386/x86-iommu.h"
#include "trace.h"
diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c
index 16a9417a85..cda8d48333 100644
--- a/hw/net/e1000e.c
+++ b/hw/net/e1000e.c
@@ -41,7 +41,7 @@
#include "hw/pci/msi.h"
#include "hw/pci/msix.h"
-#include "hw/net/e1000_regs.h"
+#include "e1000_regs.h"
#include "e1000x_common.h"
#include "e1000e_core.h"
diff --git a/hw/net/rocker/rocker_fp.c b/hw/net/rocker/rocker_fp.c
index 27b17c890f..4aa7da79b8 100644
--- a/hw/net/rocker/rocker_fp.c
+++ b/hw/net/rocker/rocker_fp.c
@@ -15,7 +15,6 @@
*/
#include "qemu/osdep.h"
-#include "net/clients.h"
#include "qapi/qapi-types-rocker.h"
#include "rocker.h"
#include "rocker_hw.h"
diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c
index e312fdba70..123f4ac09d 100644
--- a/hw/ppc/ppc440_uc.c
+++ b/hw/ppc/ppc440_uc.c
@@ -20,7 +20,7 @@
#include "hw/ppc/ppc.h"
#include "hw/pci/pci.h"
#include "sysemu/block-backend.h"
-#include "hw/ppc/ppc440.h"
+#include "ppc440.h"
/*****************************************************************************/
/* L2 Cache as SRAM */
diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
index 3dd23de71f..bdc53d2603 100644
--- a/hw/ppc/sam460ex.c
+++ b/hw/ppc/sam460ex.c
@@ -26,8 +26,8 @@
#include "elf.h"
#include "exec/address-spaces.h"
#include "exec/memory.h"
-#include "hw/ppc/ppc440.h"
-#include "hw/ppc/ppc405.h"
+#include "ppc440.h"
+#include "ppc405.h"
#include "hw/block/flash.h"
#include "sysemu/sysemu.h"
#include "sysemu/qtest.h"
diff --git a/hw/scsi/vhost-scsi-common.c b/hw/scsi/vhost-scsi-common.c
index 77e9897244..e2a5828af1 100644
--- a/hw/scsi/vhost-scsi-common.c
+++ b/hw/scsi/vhost-scsi-common.c
@@ -17,7 +17,6 @@
#include "qemu/osdep.h"
#include "qemu/error-report.h"
-#include "migration/migration.h"
#include "hw/virtio/vhost.h"
#include "hw/virtio/vhost-scsi-common.h"
#include "hw/virtio/virtio-scsi.h"
diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c
index 9389ed48e0..9355cfdf07 100644
--- a/hw/scsi/vhost-user-scsi.c
+++ b/hw/scsi/vhost-user-scsi.c
@@ -69,6 +69,7 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp)
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev);
VHostUserSCSI *s = VHOST_USER_SCSI(dev);
VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s);
+ VhostUserState *user;
Error *err = NULL;
int ret;
@@ -85,19 +86,30 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp)
return;
}
+ user = vhost_user_init();
+ if (!user) {
+ error_setg(errp, "vhost-user-scsi: failed to init vhost_user");
+ return;
+ }
+ user->chr = &vs->conf.chardev;
+
vsc->dev.nvqs = 2 + vs->conf.num_queues;
vsc->dev.vqs = g_new(struct vhost_virtqueue, vsc->dev.nvqs);
vsc->dev.vq_index = 0;
vsc->dev.backend_features = 0;
- ret = vhost_dev_init(&vsc->dev, (void *)&vs->conf.chardev,
+ ret = vhost_dev_init(&vsc->dev, user,
VHOST_BACKEND_TYPE_USER, 0);
if (ret < 0) {
error_setg(errp, "vhost-user-scsi: vhost initialization failed: %s",
strerror(-ret));
+ vhost_user_cleanup(user);
+ g_free(user);
return;
}
+ s->vhost_user = user;
+
/* Channel and lun both are 0 for bootable vhost-user-scsi disk */
vsc->channel = 0;
vsc->lun = 0;
@@ -117,6 +129,12 @@ static void vhost_user_scsi_unrealize(DeviceState *dev, Error **errp)
g_free(vsc->dev.vqs);
virtio_scsi_common_unrealize(dev, errp);
+
+ if (s->vhost_user) {
+ vhost_user_cleanup(s->vhost_user);
+ g_free(s->vhost_user);
+ s->vhost_user = NULL;
+ }
}
static uint64_t vhost_user_scsi_get_features(VirtIODevice *vdev,
diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c
index 5570c1e9a0..fe1cccca76 100644
--- a/hw/sd/milkymist-memcard.c
+++ b/hw/sd/milkymist-memcard.c
@@ -27,7 +27,7 @@
#include "hw/sysbus.h"
#include "sysemu/sysemu.h"
#include "trace.h"
-#include "include/qapi/error.h"
+#include "qapi/error.h"
#include "sysemu/block-backend.h"
#include "sysemu/blockdev.h"
#include "hw/sd/sd.h"
diff --git a/hw/usb/desc-msos.c b/hw/usb/desc-msos.c
index 3652919815..3a5ad7c8d0 100644
--- a/hw/usb/desc-msos.c
+++ b/hw/usb/desc-msos.c
@@ -1,6 +1,6 @@
#include "qemu/osdep.h"
#include "hw/usb.h"
-#include "hw/usb/desc.h"
+#include "desc.h"
/*
* Microsoft OS Descriptors
diff --git a/hw/usb/desc.c b/hw/usb/desc.c
index 85c15addc5..8b6eaea407 100644
--- a/hw/usb/desc.c
+++ b/hw/usb/desc.c
@@ -1,7 +1,7 @@
#include "qemu/osdep.h"
#include "hw/usb.h"
-#include "hw/usb/desc.h"
+#include "desc.h"
#include "trace.h"
/* ------------------------------------------------------------------ */
diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c
index 343345235c..ee43e4914d 100644
--- a/hw/usb/dev-audio.c
+++ b/hw/usb/dev-audio.c
@@ -32,7 +32,7 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "hw/usb.h"
-#include "hw/usb/desc.h"
+#include "desc.h"
#include "hw/hw.h"
#include "audio/audio.h"
diff --git a/hw/usb/dev-bluetooth.c b/hw/usb/dev-bluetooth.c
index 0bbceaea0b..eac7365b0a 100644
--- a/hw/usb/dev-bluetooth.c
+++ b/hw/usb/dev-bluetooth.c
@@ -22,7 +22,7 @@
#include "qemu-common.h"
#include "qemu/error-report.h"
#include "hw/usb.h"
-#include "hw/usb/desc.h"
+#include "desc.h"
#include "sysemu/bt.h"
#include "hw/bt.h"
diff --git a/hw/usb/dev-hid.c b/hw/usb/dev-hid.c
index c40019df96..62d18290dc 100644
--- a/hw/usb/dev-hid.c
+++ b/hw/usb/dev-hid.c
@@ -26,7 +26,7 @@
#include "hw/hw.h"
#include "ui/console.h"
#include "hw/usb.h"
-#include "hw/usb/desc.h"
+#include "desc.h"
#include "qapi/error.h"
#include "qemu/timer.h"
#include "hw/input/hid.h"
diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c
index 752e30c305..5d9743ef93 100644
--- a/hw/usb/dev-hub.c
+++ b/hw/usb/dev-hub.c
@@ -26,7 +26,7 @@
#include "qemu-common.h"
#include "trace.h"
#include "hw/usb.h"
-#include "hw/usb/desc.h"
+#include "desc.h"
#include "qemu/error-report.h"
#define NUM_PORTS 8
diff --git a/hw/usb/dev-mtp.c b/hw/usb/dev-mtp.c
index 3d59fe4944..560c61c7c1 100644
--- a/hw/usb/dev-mtp.c
+++ b/hw/usb/dev-mtp.c
@@ -24,7 +24,7 @@
#include "qemu/iov.h"
#include "trace.h"
#include "hw/usb.h"
-#include "hw/usb/desc.h"
+#include "desc.h"
/* ----------------------------------------------------------------------- */
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index aea7edcf31..385e090336 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -27,7 +27,7 @@
#include "qapi/error.h"
#include "qemu-common.h"
#include "hw/usb.h"
-#include "hw/usb/desc.h"
+#include "desc.h"
#include "net/net.h"
#include "qemu/error-report.h"
#include "qemu/queue.h"
diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
index 2829dda391..98d1ca3c91 100644
--- a/hw/usb/dev-serial.c
+++ b/hw/usb/dev-serial.c
@@ -14,7 +14,7 @@
#include "qemu/cutils.h"
#include "qemu/error-report.h"
#include "hw/usb.h"
-#include "hw/usb/desc.h"
+#include "desc.h"
#include "chardev/char-serial.h"
#include "chardev/char-fe.h"
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
index f7451923f4..2131e33d27 100644
--- a/hw/usb/dev-smartcard-reader.c
+++ b/hw/usb/dev-smartcard-reader.c
@@ -39,7 +39,7 @@
#include "qemu-common.h"
#include "qemu/error-report.h"
#include "hw/usb.h"
-#include "hw/usb/desc.h"
+#include "desc.h"
#include "ccid.h"
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index d02acda945..481694a473 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -14,7 +14,7 @@
#include "qemu/option.h"
#include "qemu/config-file.h"
#include "hw/usb.h"
-#include "hw/usb/desc.h"
+#include "desc.h"
#include "hw/scsi/scsi.h"
#include "ui/console.h"
#include "monitor/monitor.h"
diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c
index c218b53f09..aaf5a88095 100644
--- a/hw/usb/dev-uas.c
+++ b/hw/usb/dev-uas.c
@@ -17,7 +17,7 @@
#include "qemu/error-report.h"
#include "hw/usb.h"
-#include "hw/usb/desc.h"
+#include "desc.h"
#include "hw/scsi/scsi.h"
#include "scsi/constants.h"
diff --git a/hw/usb/dev-wacom.c b/hw/usb/dev-wacom.c
index bf70013059..ac0bc83b52 100644
--- a/hw/usb/dev-wacom.c
+++ b/hw/usb/dev-wacom.c
@@ -29,7 +29,7 @@
#include "hw/hw.h"
#include "ui/console.h"
#include "hw/usb.h"
-#include "hw/usb/desc.h"
+#include "desc.h"
/* Interface requests */
#define WACOM_GET_REPORT 0x2101
diff --git a/hw/virtio/vhost-stub.c b/hw/virtio/vhost-stub.c
index 2d76cdebdc..049089b5e2 100644
--- a/hw/virtio/vhost-stub.c
+++ b/hw/virtio/vhost-stub.c
@@ -1,7 +1,17 @@
#include "qemu/osdep.h"
#include "hw/virtio/vhost.h"
+#include "hw/virtio/vhost-user.h"
bool vhost_has_free_slot(void)
{
return true;
}
+
+VhostUserState *vhost_user_init(void)
+{
+ return NULL;
+}
+
+void vhost_user_cleanup(VhostUserState *user)
+{
+}
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index ca554d4ff1..b041343632 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -11,7 +11,9 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "hw/virtio/vhost.h"
+#include "hw/virtio/vhost-user.h"
#include "hw/virtio/vhost-backend.h"
+#include "hw/virtio/virtio.h"
#include "hw/virtio/virtio-net.h"
#include "chardev/char-fe.h"
#include "sysemu/kvm.h"
@@ -30,6 +32,7 @@
#define VHOST_MEMORY_MAX_NREGIONS 8
#define VHOST_USER_F_PROTOCOL_FEATURES 30
+#define VHOST_USER_SLAVE_MAX_FDS 8
/*
* Maximum size of virtio device config space
@@ -47,6 +50,8 @@ enum VhostUserProtocolFeature {
VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7,
VHOST_USER_PROTOCOL_F_PAGEFAULT = 8,
VHOST_USER_PROTOCOL_F_CONFIG = 9,
+ VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD = 10,
+ VHOST_USER_PROTOCOL_F_HOST_NOTIFIER = 11,
VHOST_USER_PROTOCOL_F_MAX
};
@@ -91,6 +96,7 @@ typedef enum VhostUserSlaveRequest {
VHOST_USER_SLAVE_NONE = 0,
VHOST_USER_SLAVE_IOTLB_MSG = 1,
VHOST_USER_SLAVE_CONFIG_CHANGE_MSG = 2,
+ VHOST_USER_SLAVE_VRING_HOST_NOTIFIER_MSG = 3,
VHOST_USER_SLAVE_MAX
} VhostUserSlaveRequest;
@@ -135,6 +141,12 @@ static VhostUserConfig c __attribute__ ((unused));
+ sizeof(c.size) \
+ sizeof(c.flags))
+typedef struct VhostUserVringArea {
+ uint64_t u64;
+ uint64_t size;
+ uint64_t offset;
+} VhostUserVringArea;
+
typedef struct {
VhostUserRequest request;
@@ -156,6 +168,7 @@ typedef union {
struct vhost_iotlb_msg iotlb;
VhostUserConfig config;
VhostUserCryptoSession session;
+ VhostUserVringArea area;
} VhostUserPayload;
typedef struct VhostUserMsg {
@@ -173,7 +186,8 @@ static VhostUserMsg m __attribute__ ((unused));
struct vhost_user {
struct vhost_dev *dev;
- CharBackend *chr;
+ /* Shared between vhost devs of the same virtio device */
+ VhostUserState *user;
int slave_fd;
NotifierWithReturn postcopy_notifier;
struct PostCopyFD postcopy_fd;
@@ -199,7 +213,7 @@ static bool ioeventfd_enabled(void)
static int vhost_user_read(struct vhost_dev *dev, VhostUserMsg *msg)
{
struct vhost_user *u = dev->opaque;
- CharBackend *chr = u->chr;
+ CharBackend *chr = u->user->chr;
uint8_t *p = (uint8_t *) msg;
int r, size = VHOST_USER_HDR_SIZE;
@@ -285,7 +299,7 @@ static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg,
int *fds, int fd_num)
{
struct vhost_user *u = dev->opaque;
- CharBackend *chr = u->chr;
+ CharBackend *chr = u->user->chr;
int ret, size = VHOST_USER_HDR_SIZE + msg->hdr.size;
/*
@@ -636,9 +650,37 @@ static int vhost_user_set_vring_num(struct vhost_dev *dev,
return vhost_set_vring(dev, VHOST_USER_SET_VRING_NUM, ring);
}
+static void vhost_user_host_notifier_restore(struct vhost_dev *dev,
+ int queue_idx)
+{
+ struct vhost_user *u = dev->opaque;
+ VhostUserHostNotifier *n = &u->user->notifier[queue_idx];
+ VirtIODevice *vdev = dev->vdev;
+
+ if (n->addr && !n->set) {
+ virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, true);
+ n->set = true;
+ }
+}
+
+static void vhost_user_host_notifier_remove(struct vhost_dev *dev,
+ int queue_idx)
+{
+ struct vhost_user *u = dev->opaque;
+ VhostUserHostNotifier *n = &u->user->notifier[queue_idx];
+ VirtIODevice *vdev = dev->vdev;
+
+ if (n->addr && n->set) {
+ virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, false);
+ n->set = false;
+ }
+}
+
static int vhost_user_set_vring_base(struct vhost_dev *dev,
struct vhost_vring_state *ring)
{
+ vhost_user_host_notifier_restore(dev, ring->index);
+
return vhost_set_vring(dev, VHOST_USER_SET_VRING_BASE, ring);
}
@@ -672,6 +714,8 @@ static int vhost_user_get_vring_base(struct vhost_dev *dev,
.hdr.size = sizeof(msg.payload.state),
};
+ vhost_user_host_notifier_remove(dev, ring->index);
+
if (vhost_user_write(dev, &msg, NULL, 0) < 0) {
return -1;
}
@@ -845,6 +889,66 @@ static int vhost_user_slave_handle_config_change(struct vhost_dev *dev)
return ret;
}
+static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev,
+ VhostUserVringArea *area,
+ int fd)
+{
+ int queue_idx = area->u64 & VHOST_USER_VRING_IDX_MASK;
+ size_t page_size = qemu_real_host_page_size;
+ struct vhost_user *u = dev->opaque;
+ VhostUserState *user = u->user;
+ VirtIODevice *vdev = dev->vdev;
+ VhostUserHostNotifier *n;
+ void *addr;
+ char *name;
+
+ if (!virtio_has_feature(dev->protocol_features,
+ VHOST_USER_PROTOCOL_F_HOST_NOTIFIER) ||
+ vdev == NULL || queue_idx >= virtio_get_num_queues(vdev)) {
+ return -1;
+ }
+
+ n = &user->notifier[queue_idx];
+
+ if (n->addr) {
+ virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, false);
+ object_unparent(OBJECT(&n->mr));
+ munmap(n->addr, page_size);
+ n->addr = NULL;
+ }
+
+ if (area->u64 & VHOST_USER_VRING_NOFD_MASK) {
+ return 0;
+ }
+
+ /* Sanity check. */
+ if (area->size != page_size) {
+ return -1;
+ }
+
+ addr = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED,
+ fd, area->offset);
+ if (addr == MAP_FAILED) {
+ return -1;
+ }
+
+ name = g_strdup_printf("vhost-user/host-notifier@%p mmaps[%d]",
+ user, queue_idx);
+ memory_region_init_ram_device_ptr(&n->mr, OBJECT(vdev), name,
+ page_size, addr);
+ g_free(name);
+
+ if (virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, true)) {
+ munmap(addr, page_size);
+ return -1;
+ }
+
+ n->addr = addr;
+ n->set = true;
+
+ return 0;
+}
+
static void slave_read(void *opaque)
{
struct vhost_dev *dev = opaque;
@@ -854,10 +958,10 @@ static void slave_read(void *opaque)
int size, ret = 0;
struct iovec iov;
struct msghdr msgh;
- int fd = -1;
+ int fd[VHOST_USER_SLAVE_MAX_FDS];
char control[CMSG_SPACE(sizeof(fd))];
struct cmsghdr *cmsg;
- size_t fdsize;
+ int i, fdsize = 0;
memset(&msgh, 0, sizeof(msgh));
msgh.msg_iov = &iov;
@@ -865,6 +969,8 @@ static void slave_read(void *opaque)
msgh.msg_control = control;
msgh.msg_controllen = sizeof(control);
+ memset(fd, -1, sizeof(fd));
+
/* Read header */
iov.iov_base = &hdr;
iov.iov_len = VHOST_USER_HDR_SIZE;
@@ -885,7 +991,7 @@ static void slave_read(void *opaque)
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_RIGHTS) {
fdsize = cmsg->cmsg_len - CMSG_LEN(0);
- memcpy(&fd, CMSG_DATA(cmsg), fdsize);
+ memcpy(fd, CMSG_DATA(cmsg), fdsize);
break;
}
}
@@ -911,16 +1017,21 @@ static void slave_read(void *opaque)
case VHOST_USER_SLAVE_CONFIG_CHANGE_MSG :
ret = vhost_user_slave_handle_config_change(dev);
break;
+ case VHOST_USER_SLAVE_VRING_HOST_NOTIFIER_MSG:
+ ret = vhost_user_slave_handle_vring_host_notifier(dev, &payload.area,
+ fd[0]);
+ break;
default:
error_report("Received unexpected msg type.");
- if (fd != -1) {
- close(fd);
- }
ret = -EINVAL;
}
- /* Message handlers need to make sure that fd will be consumed. */
- fd = -1;
+ /* Close the remaining file descriptors. */
+ for (i = 0; i < fdsize; i++) {
+ if (fd[i] != -1) {
+ close(fd[i]);
+ }
+ }
/*
* REPLY_ACK feature handling. Other reply types has to be managed
@@ -954,8 +1065,10 @@ err:
qemu_set_fd_handler(u->slave_fd, NULL, NULL, NULL);
close(u->slave_fd);
u->slave_fd = -1;
- if (fd != -1) {
- close(fd);
+ for (i = 0; i < fdsize; i++) {
+ if (fd[i] != -1) {
+ close(fd[i]);
+ }
}
return;
}
@@ -1083,7 +1196,7 @@ static int vhost_user_postcopy_waker(struct PostCopyFD *pcfd, RAMBlock *rb,
static int vhost_user_postcopy_advise(struct vhost_dev *dev, Error **errp)
{
struct vhost_user *u = dev->opaque;
- CharBackend *chr = u->chr;
+ CharBackend *chr = u->user->chr;
int ufd;
VhostUserMsg msg = {
.hdr.request = VHOST_USER_POSTCOPY_ADVISE,
@@ -1221,7 +1334,7 @@ static int vhost_user_postcopy_notifier(NotifierWithReturn *notifier,
return 0;
}
-static int vhost_user_init(struct vhost_dev *dev, void *opaque)
+static int vhost_user_backend_init(struct vhost_dev *dev, void *opaque)
{
uint64_t features, protocol_features;
struct vhost_user *u;
@@ -1230,7 +1343,7 @@ static int vhost_user_init(struct vhost_dev *dev, void *opaque)
assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
u = g_new0(struct vhost_user, 1);
- u->chr = opaque;
+ u->user = opaque;
u->slave_fd = -1;
u->dev = dev;
dev->opaque = u;
@@ -1306,7 +1419,7 @@ static int vhost_user_init(struct vhost_dev *dev, void *opaque)
return 0;
}
-static int vhost_user_cleanup(struct vhost_dev *dev)
+static int vhost_user_backend_cleanup(struct vhost_dev *dev)
{
struct vhost_user *u;
@@ -1620,10 +1733,40 @@ vhost_user_crypto_close_session(struct vhost_dev *dev, uint64_t session_id)
return 0;
}
+static bool vhost_user_mem_section_filter(struct vhost_dev *dev,
+ MemoryRegionSection *section)
+{
+ bool result;
+
+ result = memory_region_get_fd(section->mr) >= 0;
+
+ return result;
+}
+
+VhostUserState *vhost_user_init(void)
+{
+ VhostUserState *user = g_new0(struct VhostUserState, 1);
+
+ return user;
+}
+
+void vhost_user_cleanup(VhostUserState *user)
+{
+ int i;
+
+ for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
+ if (user->notifier[i].addr) {
+ object_unparent(OBJECT(&user->notifier[i].mr));
+ munmap(user->notifier[i].addr, qemu_real_host_page_size);
+ user->notifier[i].addr = NULL;
+ }
+ }
+}
+
const VhostOps user_ops = {
.backend_type = VHOST_BACKEND_TYPE_USER,
- .vhost_backend_init = vhost_user_init,
- .vhost_backend_cleanup = vhost_user_cleanup,
+ .vhost_backend_init = vhost_user_backend_init,
+ .vhost_backend_cleanup = vhost_user_backend_cleanup,
.vhost_backend_memslots_limit = vhost_user_memslots_limit,
.vhost_set_log_base = vhost_user_set_log_base,
.vhost_set_mem_table = vhost_user_set_mem_table,
@@ -1650,4 +1793,5 @@ const VhostOps user_ops = {
.vhost_set_config = vhost_user_set_config,
.vhost_crypto_create_session = vhost_user_crypto_create_session,
.vhost_crypto_close_session = vhost_user_crypto_close_session,
+ .vhost_backend_mem_section_filter = vhost_user_mem_section_filter,
};
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 4565b69f83..96175b214d 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -386,7 +386,7 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev,
return r;
}
-static bool vhost_section(MemoryRegionSection *section)
+static bool vhost_section(struct vhost_dev *dev, MemoryRegionSection *section)
{
bool result;
bool log_dirty = memory_region_get_dirty_log_mask(section->mr) &
@@ -399,6 +399,11 @@ static bool vhost_section(MemoryRegionSection *section)
*/
result &= !log_dirty;
+ if (result && dev->vhost_ops->vhost_backend_mem_section_filter) {
+ result &=
+ dev->vhost_ops->vhost_backend_mem_section_filter(dev, section);
+ }
+
trace_vhost_section(section->mr->name, result);
return result;
}
@@ -632,7 +637,7 @@ static void vhost_region_addnop(MemoryListener *listener,
struct vhost_dev *dev = container_of(listener, struct vhost_dev,
memory_listener);
- if (!vhost_section(section)) {
+ if (!vhost_section(dev, section)) {
return;
}
vhost_region_add_section(dev, section);