aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-08-27 16:59:02 +0100
committerPeter Maydell <peter.maydell@linaro.org>2020-08-27 16:59:02 +0100
commit19591e9e0938ea5066984553c256a043bd5d822f (patch)
tree8992fe45eb89e68a9940685a77b2000808eb03be
parentac8b279f13865d1a4f1958d3bf34240c1c3af90d (diff)
parente1647539b1d04f121b70f1f6f438976477450f10 (diff)
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
virtio,pc,acpi: features, fixes better number of queues for vhost smbios speed options acpi fixes Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Thu 27 Aug 2020 13:33:49 BST # gpg: using RSA key 5D09FD0871C8F85B94CA8A0D281F0DB8D28D5469 # gpg: issuer "mst@redhat.com" # gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" [full] # gpg: aka "Michael S. Tsirkin <mst@redhat.com>" [full] # 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/bios-tables-test: add smbios cpu speed test hw/smbios: add options for type 4 max-speed and current-speed vhost-user-blk-pci: default num_queues to -smp N virtio-blk-pci: default num_queues to -smp N virtio-scsi-pci: default num_queues to -smp N virtio-scsi: introduce a constant for fixed virtqueues virtio-pci: add virtio_pci_optimal_num_queues() helper Introduce a new flag for i440fx to disable PCI hotplug on the root bus acpi: update expected DSDT files with _UID changes disassemble-aml: -o actually works arm/acpi: fix an out of spec _UID for PCI root i386/acpi: fix inconsistent QEMU/OVMF device paths acpi: allow DSDT changes Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/acpi/pcihp.c23
-rw-r--r--hw/acpi/piix4.c5
-rw-r--r--hw/arm/virt-acpi-build.c2
-rw-r--r--hw/block/vhost-user-blk.c6
-rw-r--r--hw/block/virtio-blk.c6
-rw-r--r--hw/core/machine.c8
-rw-r--r--hw/i386/acpi-build.c4
-rw-r--r--hw/scsi/vhost-scsi.c3
-rw-r--r--hw/scsi/vhost-user-scsi.c5
-rw-r--r--hw/scsi/virtio-scsi.c13
-rw-r--r--hw/smbios/smbios.c36
-rw-r--r--hw/virtio/vhost-scsi-pci.c9
-rw-r--r--hw/virtio/vhost-user-blk-pci.c4
-rw-r--r--hw/virtio/vhost-user-scsi-pci.c9
-rw-r--r--hw/virtio/virtio-blk-pci.c7
-rw-r--r--hw/virtio/virtio-pci.c32
-rw-r--r--hw/virtio/virtio-pci.h9
-rw-r--r--hw/virtio/virtio-scsi-pci.c9
-rw-r--r--include/hw/acpi/pcihp.h2
-rw-r--r--include/hw/virtio/vhost-user-blk.h2
-rw-r--r--include/hw/virtio/virtio-blk.h2
-rw-r--r--include/hw/virtio/virtio-scsi.h5
-rw-r--r--qemu-options.hx2
-rwxr-xr-xtests/data/acpi/disassemle-aml.sh11
-rw-r--r--tests/data/acpi/pc/DSDTbin4934 -> 4934 bytes
-rw-r--r--tests/data/acpi/pc/DSDT.acpihmatbin6258 -> 6258 bytes
-rw-r--r--tests/data/acpi/pc/DSDT.bridgebin6793 -> 6793 bytes
-rw-r--r--tests/data/acpi/pc/DSDT.cphpbin5397 -> 5397 bytes
-rw-r--r--tests/data/acpi/pc/DSDT.dimmpxmbin6587 -> 6587 bytes
-rw-r--r--tests/data/acpi/pc/DSDT.ipmikcsbin5006 -> 5006 bytes
-rw-r--r--tests/data/acpi/pc/DSDT.memhpbin6293 -> 6293 bytes
-rw-r--r--tests/data/acpi/pc/DSDT.numamembin4940 -> 4940 bytes
-rw-r--r--tests/data/acpi/q35/DSDTbin7678 -> 7678 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.acpihmatbin9002 -> 9002 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.bridgebin7695 -> 7695 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.cphpbin8141 -> 8141 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.dimmpxmbin9331 -> 9331 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.ipmibtbin7753 -> 7753 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.memhpbin9037 -> 9037 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.mmio64bin8808 -> 8808 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.numamembin7684 -> 7684 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.tisbin8283 -> 8283 bytes
-rw-r--r--tests/data/acpi/virt/DSDTbin5205 -> 5200 bytes
-rw-r--r--tests/data/acpi/virt/DSDT.memhpbin6566 -> 6561 bytes
-rw-r--r--tests/data/acpi/virt/DSDT.numamembin5205 -> 5200 bytes
-rw-r--r--tests/qtest/bios-tables-test.c42
46 files changed, 225 insertions, 31 deletions
diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
index 9e31ab2da4..39b1f74442 100644
--- a/hw/acpi/pcihp.c
+++ b/hw/acpi/pcihp.c
@@ -104,6 +104,24 @@ static void acpi_set_pci_info(void)
}
}
+static void acpi_pcihp_disable_root_bus(void)
+{
+ static bool root_hp_disabled;
+ PCIBus *bus;
+
+ if (root_hp_disabled) {
+ return;
+ }
+
+ bus = find_i440fx();
+ if (bus) {
+ /* setting the hotplug handler to NULL makes the bus non-hotpluggable */
+ qbus_set_hotplug_handler(BUS(bus), NULL);
+ }
+ root_hp_disabled = true;
+ return;
+}
+
static void acpi_pcihp_test_hotplug_bus(PCIBus *bus, void *opaque)
{
AcpiPciHpFind *find = opaque;
@@ -209,8 +227,11 @@ static void acpi_pcihp_update(AcpiPciHpState *s)
}
}
-void acpi_pcihp_reset(AcpiPciHpState *s)
+void acpi_pcihp_reset(AcpiPciHpState *s, bool acpihp_root_off)
{
+ if (acpihp_root_off) {
+ acpi_pcihp_disable_root_bus();
+ }
acpi_set_pci_info();
acpi_pcihp_update(s);
}
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 26bac4f16c..e6163bb6ce 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -78,6 +78,7 @@ typedef struct PIIX4PMState {
AcpiPciHpState acpi_pci_hotplug;
bool use_acpi_hotplug_bridge;
+ bool use_acpi_root_pci_hotplug;
uint8_t disable_s3;
uint8_t disable_s4;
@@ -324,7 +325,7 @@ static void piix4_pm_reset(DeviceState *dev)
pci_conf[0x5B] = 0x02;
}
pm_io_space_update(s);
- acpi_pcihp_reset(&s->acpi_pci_hotplug);
+ acpi_pcihp_reset(&s->acpi_pci_hotplug, !s->use_acpi_root_pci_hotplug);
}
static void piix4_pm_powerdown_req(Notifier *n, void *opaque)
@@ -635,6 +636,8 @@ static Property piix4_pm_properties[] = {
DEFINE_PROP_UINT8(ACPI_PM_PROP_S4_VAL, PIIX4PMState, s4_val, 2),
DEFINE_PROP_BOOL("acpi-pci-hotplug-with-bridge-support", PIIX4PMState,
use_acpi_hotplug_bridge, true),
+ DEFINE_PROP_BOOL("acpi-root-pci-hotplug", PIIX4PMState,
+ use_acpi_root_pci_hotplug, true),
DEFINE_PROP_BOOL("memory-hotplug-support", PIIX4PMState,
acpi_memory_hotplug.is_enabled, true),
DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 91f0df7b13..0a482ff6f7 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -170,7 +170,7 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
aml_append(dev, aml_name_decl("_CID", aml_string("PNP0A03")));
aml_append(dev, aml_name_decl("_SEG", aml_int(0)));
aml_append(dev, aml_name_decl("_BBN", aml_int(0)));
- aml_append(dev, aml_name_decl("_UID", aml_string("PCI0")));
+ aml_append(dev, aml_name_decl("_UID", aml_int(0)));
aml_append(dev, aml_name_decl("_STR", aml_unicode("PCIe 0 Device")));
aml_append(dev, aml_name_decl("_CCA", aml_int(1)));
diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index a00b854736..39aec42dae 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -420,6 +420,9 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp)
return;
}
+ if (s->num_queues == VHOST_USER_BLK_AUTO_NUM_QUEUES) {
+ s->num_queues = 1;
+ }
if (!s->num_queues || s->num_queues > VIRTIO_QUEUE_MAX) {
error_setg(errp, "vhost-user-blk: invalid number of IO queues");
return;
@@ -531,7 +534,8 @@ static const VMStateDescription vmstate_vhost_user_blk = {
static Property vhost_user_blk_properties[] = {
DEFINE_PROP_CHR("chardev", VHostUserBlk, chardev),
- DEFINE_PROP_UINT16("num-queues", VHostUserBlk, num_queues, 1),
+ DEFINE_PROP_UINT16("num-queues", VHostUserBlk, num_queues,
+ VHOST_USER_BLK_AUTO_NUM_QUEUES),
DEFINE_PROP_UINT32("queue-size", VHostUserBlk, queue_size, 128),
DEFINE_PROP_BIT("config-wce", VHostUserBlk, config_wce, 0, true),
DEFINE_PROP_END_OF_LIST(),
diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c
index 413783693c..2204ba149e 100644
--- a/hw/block/virtio-blk.c
+++ b/hw/block/virtio-blk.c
@@ -1147,6 +1147,9 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp)
error_setg(errp, "Device needs media, but drive is empty");
return;
}
+ if (conf->num_queues == VIRTIO_BLK_AUTO_NUM_QUEUES) {
+ conf->num_queues = 1;
+ }
if (!conf->num_queues) {
error_setg(errp, "num-queues property must be larger than 0");
return;
@@ -1281,7 +1284,8 @@ static Property virtio_blk_properties[] = {
#endif
DEFINE_PROP_BIT("request-merging", VirtIOBlock, conf.request_merging, 0,
true),
- DEFINE_PROP_UINT16("num-queues", VirtIOBlock, conf.num_queues, 1),
+ DEFINE_PROP_UINT16("num-queues", VirtIOBlock, conf.num_queues,
+ VIRTIO_BLK_AUTO_NUM_QUEUES),
DEFINE_PROP_UINT16("queue-size", VirtIOBlock, conf.queue_size, 256),
DEFINE_PROP_BOOL("seg-max-adjust", VirtIOBlock, conf.seg_max_adjust, true),
DEFINE_PROP_LINK("iothread", VirtIOBlock, conf.iothread, TYPE_IOTHREAD,
diff --git a/hw/core/machine.c b/hw/core/machine.c
index cf5f2dfaeb..ea26d61237 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -28,7 +28,13 @@
#include "hw/mem/nvdimm.h"
#include "migration/vmstate.h"
-GlobalProperty hw_compat_5_1[] = {};
+GlobalProperty hw_compat_5_1[] = {
+ { "vhost-scsi", "num_queues", "1"},
+ { "vhost-user-blk", "num-queues", "1"},
+ { "vhost-user-scsi", "num_queues", "1"},
+ { "virtio-blk-device", "num-queues", "1"},
+ { "virtio-scsi-device", "num_queues", "1"},
+};
const size_t hw_compat_5_1_len = G_N_ELEMENTS(hw_compat_5_1);
GlobalProperty hw_compat_5_0[] = {
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index b7bcbbbb2a..7a5a8b3521 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1497,7 +1497,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
dev = aml_device("PCI0");
aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03")));
aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
- aml_append(dev, aml_name_decl("_UID", aml_int(1)));
+ aml_append(dev, aml_name_decl("_UID", aml_int(0)));
aml_append(sb_scope, dev);
aml_append(dsdt, sb_scope);
@@ -1512,7 +1512,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08")));
aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03")));
aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
- aml_append(dev, aml_name_decl("_UID", aml_int(1)));
+ aml_append(dev, aml_name_decl("_UID", aml_int(0)));
aml_append(dev, build_q35_osc_method());
aml_append(sb_scope, dev);
aml_append(dsdt, sb_scope);
diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index 13b05af29b..a83ffeefc8 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -270,7 +270,8 @@ static Property vhost_scsi_properties[] = {
DEFINE_PROP_STRING("vhostfd", VirtIOSCSICommon, conf.vhostfd),
DEFINE_PROP_STRING("wwpn", VirtIOSCSICommon, conf.wwpn),
DEFINE_PROP_UINT32("boot_tpgt", VirtIOSCSICommon, conf.boot_tpgt, 0),
- DEFINE_PROP_UINT32("num_queues", VirtIOSCSICommon, conf.num_queues, 1),
+ DEFINE_PROP_UINT32("num_queues", VirtIOSCSICommon, conf.num_queues,
+ VIRTIO_SCSI_AUTO_NUM_QUEUES),
DEFINE_PROP_UINT32("virtqueue_size", VirtIOSCSICommon, conf.virtqueue_size,
128),
DEFINE_PROP_BOOL("seg_max_adjust", VirtIOSCSICommon, conf.seg_max_adjust,
diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c
index f2e524438a..7c0631656c 100644
--- a/hw/scsi/vhost-user-scsi.c
+++ b/hw/scsi/vhost-user-scsi.c
@@ -114,7 +114,7 @@ static void vhost_user_scsi_realize(DeviceState *dev, Error **errp)
goto free_virtio;
}
- vsc->dev.nvqs = 2 + vs->conf.num_queues;
+ vsc->dev.nvqs = VIRTIO_SCSI_VQ_NUM_FIXED + vs->conf.num_queues;
vsc->dev.vqs = g_new0(struct vhost_virtqueue, vsc->dev.nvqs);
vsc->dev.vq_index = 0;
vsc->dev.backend_features = 0;
@@ -162,7 +162,8 @@ static void vhost_user_scsi_unrealize(DeviceState *dev)
static Property vhost_user_scsi_properties[] = {
DEFINE_PROP_CHR("chardev", VirtIOSCSICommon, conf.chardev),
DEFINE_PROP_UINT32("boot_tpgt", VirtIOSCSICommon, conf.boot_tpgt, 0),
- DEFINE_PROP_UINT32("num_queues", VirtIOSCSICommon, conf.num_queues, 1),
+ DEFINE_PROP_UINT32("num_queues", VirtIOSCSICommon, conf.num_queues,
+ VIRTIO_SCSI_AUTO_NUM_QUEUES),
DEFINE_PROP_UINT32("virtqueue_size", VirtIOSCSICommon, conf.virtqueue_size,
128),
DEFINE_PROP_UINT32("max_sectors", VirtIOSCSICommon, conf.max_sectors,
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index b49775269e..3a71ea7097 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -191,7 +191,7 @@ static void virtio_scsi_save_request(QEMUFile *f, SCSIRequest *sreq)
VirtIOSCSIReq *req = sreq->hba_private;
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(req->dev);
VirtIODevice *vdev = VIRTIO_DEVICE(req->dev);
- uint32_t n = virtio_get_queue_index(req->vq) - 2;
+ uint32_t n = virtio_get_queue_index(req->vq) - VIRTIO_SCSI_VQ_NUM_FIXED;
assert(n < vs->conf.num_queues);
qemu_put_be32s(f, &n);
@@ -891,11 +891,15 @@ void virtio_scsi_common_realize(DeviceState *dev,
virtio_init(vdev, "virtio-scsi", VIRTIO_ID_SCSI,
sizeof(VirtIOSCSIConfig));
+ if (s->conf.num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) {
+ s->conf.num_queues = 1;
+ }
if (s->conf.num_queues == 0 ||
- s->conf.num_queues > VIRTIO_QUEUE_MAX - 2) {
+ s->conf.num_queues > VIRTIO_QUEUE_MAX - VIRTIO_SCSI_VQ_NUM_FIXED) {
error_setg(errp, "Invalid number of queues (= %" PRIu32 "), "
"must be a positive integer less than %d.",
- s->conf.num_queues, VIRTIO_QUEUE_MAX - 2);
+ s->conf.num_queues,
+ VIRTIO_QUEUE_MAX - VIRTIO_SCSI_VQ_NUM_FIXED);
virtio_cleanup(vdev);
return;
}
@@ -963,7 +967,8 @@ static void virtio_scsi_device_unrealize(DeviceState *dev)
}
static Property virtio_scsi_properties[] = {
- DEFINE_PROP_UINT32("num_queues", VirtIOSCSI, parent_obj.conf.num_queues, 1),
+ DEFINE_PROP_UINT32("num_queues", VirtIOSCSI, parent_obj.conf.num_queues,
+ VIRTIO_SCSI_AUTO_NUM_QUEUES),
DEFINE_PROP_UINT32("virtqueue_size", VirtIOSCSI,
parent_obj.conf.virtqueue_size, 256),
DEFINE_PROP_BOOL("seg_max_adjust", VirtIOSCSI,
diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
index f560826904..7cc950b41c 100644
--- a/hw/smbios/smbios.c
+++ b/hw/smbios/smbios.c
@@ -92,9 +92,21 @@ static struct {
const char *manufacturer, *version, *serial, *asset, *sku;
} type3;
+/*
+ * SVVP requires max_speed and current_speed to be set and not being
+ * 0 which counts as unknown (SMBIOS 3.1.0/Table 21). Set the
+ * default value to 2000MHz as we did before.
+ */
+#define DEFAULT_CPU_SPEED 2000
+
static struct {
const char *sock_pfx, *manufacturer, *version, *serial, *asset, *part;
-} type4;
+ uint64_t max_speed;
+ uint64_t current_speed;
+} type4 = {
+ .max_speed = DEFAULT_CPU_SPEED,
+ .current_speed = DEFAULT_CPU_SPEED
+};
static struct {
size_t nvalues;
@@ -273,6 +285,14 @@ static const QemuOptDesc qemu_smbios_type4_opts[] = {
.type = QEMU_OPT_STRING,
.help = "version number",
},{
+ .name = "max-speed",
+ .type = QEMU_OPT_NUMBER,
+ .help = "max speed in MHz",
+ },{
+ .name = "current-speed",
+ .type = QEMU_OPT_NUMBER,
+ .help = "speed at system boot in MHz",
+ },{
.name = "serial",
.type = QEMU_OPT_STRING,
.help = "serial number",
@@ -586,9 +606,8 @@ static void smbios_build_type_4_table(MachineState *ms, unsigned instance)
SMBIOS_TABLE_SET_STR(4, processor_version_str, type4.version);
t->voltage = 0;
t->external_clock = cpu_to_le16(0); /* Unknown */
- /* SVVP requires max_speed and current_speed to not be unknown. */
- t->max_speed = cpu_to_le16(2000); /* 2000 MHz */
- t->current_speed = cpu_to_le16(2000); /* 2000 MHz */
+ t->max_speed = cpu_to_le16(type4.max_speed);
+ t->current_speed = cpu_to_le16(type4.current_speed);
t->status = 0x41; /* Socket populated, CPU enabled */
t->processor_upgrade = 0x01; /* Other */
t->l1_cache_handle = cpu_to_le16(0xFFFF); /* N/A */
@@ -1116,6 +1135,15 @@ void smbios_entry_add(QemuOpts *opts, Error **errp)
save_opt(&type4.serial, opts, "serial");
save_opt(&type4.asset, opts, "asset");
save_opt(&type4.part, opts, "part");
+ type4.max_speed = qemu_opt_get_number(opts, "max-speed",
+ DEFAULT_CPU_SPEED);
+ type4.current_speed = qemu_opt_get_number(opts, "current-speed",
+ DEFAULT_CPU_SPEED);
+ if (type4.max_speed > UINT16_MAX ||
+ type4.current_speed > UINT16_MAX) {
+ error_setg(errp, "SMBIOS CPU speed is too large (> %d)",
+ UINT16_MAX);
+ }
return;
case 11:
if (!qemu_opts_validate(opts, qemu_smbios_type11_opts, errp)) {
diff --git a/hw/virtio/vhost-scsi-pci.c b/hw/virtio/vhost-scsi-pci.c
index 095af23f3f..a6bb0dc60d 100644
--- a/hw/virtio/vhost-scsi-pci.c
+++ b/hw/virtio/vhost-scsi-pci.c
@@ -47,10 +47,15 @@ static void vhost_scsi_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
{
VHostSCSIPCI *dev = VHOST_SCSI_PCI(vpci_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
- VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
+ VirtIOSCSIConf *conf = &dev->vdev.parent_obj.parent_obj.conf;
+
+ if (conf->num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) {
+ conf->num_queues =
+ virtio_pci_optimal_num_queues(VIRTIO_SCSI_VQ_NUM_FIXED);
+ }
if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
- vpci_dev->nvectors = vs->conf.num_queues + 3;
+ vpci_dev->nvectors = conf->num_queues + VIRTIO_SCSI_VQ_NUM_FIXED + 1;
}
qdev_realize(vdev, BUS(&vpci_dev->bus), errp);
diff --git a/hw/virtio/vhost-user-blk-pci.c b/hw/virtio/vhost-user-blk-pci.c
index 4f5d5cbf44..a62a71e067 100644
--- a/hw/virtio/vhost-user-blk-pci.c
+++ b/hw/virtio/vhost-user-blk-pci.c
@@ -54,6 +54,10 @@ static void vhost_user_blk_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
VHostUserBlkPCI *dev = VHOST_USER_BLK_PCI(vpci_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
+ if (dev->vdev.num_queues == VHOST_USER_BLK_AUTO_NUM_QUEUES) {
+ dev->vdev.num_queues = virtio_pci_optimal_num_queues(0);
+ }
+
if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
vpci_dev->nvectors = dev->vdev.num_queues + 1;
}
diff --git a/hw/virtio/vhost-user-scsi-pci.c b/hw/virtio/vhost-user-scsi-pci.c
index 4705cd54e8..25e97ca54e 100644
--- a/hw/virtio/vhost-user-scsi-pci.c
+++ b/hw/virtio/vhost-user-scsi-pci.c
@@ -53,10 +53,15 @@ static void vhost_user_scsi_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
{
VHostUserSCSIPCI *dev = VHOST_USER_SCSI_PCI(vpci_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
- VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
+ VirtIOSCSIConf *conf = &dev->vdev.parent_obj.parent_obj.conf;
+
+ if (conf->num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) {
+ conf->num_queues =
+ virtio_pci_optimal_num_queues(VIRTIO_SCSI_VQ_NUM_FIXED);
+ }
if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
- vpci_dev->nvectors = vs->conf.num_queues + 3;
+ vpci_dev->nvectors = conf->num_queues + VIRTIO_SCSI_VQ_NUM_FIXED + 1;
}
qdev_realize(vdev, BUS(&vpci_dev->bus), errp);
diff --git a/hw/virtio/virtio-blk-pci.c b/hw/virtio/virtio-blk-pci.c
index 849cc7dfd8..37c6e0aeb4 100644
--- a/hw/virtio/virtio-blk-pci.c
+++ b/hw/virtio/virtio-blk-pci.c
@@ -50,9 +50,14 @@ static void virtio_blk_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
{
VirtIOBlkPCI *dev = VIRTIO_BLK_PCI(vpci_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
+ VirtIOBlkConf *conf = &dev->vdev.conf;
+
+ if (conf->num_queues == VIRTIO_BLK_AUTO_NUM_QUEUES) {
+ conf->num_queues = virtio_pci_optimal_num_queues(0);
+ }
if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
- vpci_dev->nvectors = dev->vdev.conf.num_queues + 1;
+ vpci_dev->nvectors = conf->num_queues + 1;
}
qdev_realize(vdev, BUS(&vpci_dev->bus), errp);
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index ccdf54e81c..fc69570dcc 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -19,6 +19,7 @@
#include "exec/memop.h"
#include "standard-headers/linux/virtio_pci.h"
+#include "hw/boards.h"
#include "hw/virtio/virtio.h"
#include "migration/qemu-file-types.h"
#include "hw/pci/pci.h"
@@ -2058,6 +2059,37 @@ void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t)
g_free(base_name);
}
+unsigned virtio_pci_optimal_num_queues(unsigned fixed_queues)
+{
+ /*
+ * 1:1 vq to vCPU mapping is ideal because the same vCPU that submitted
+ * virtqueue buffers can handle their completion. When a different vCPU
+ * handles completion it may need to IPI the vCPU that submitted the
+ * request and this adds overhead.
+ *
+ * Virtqueues consume guest RAM and MSI-X vectors. This is wasteful in
+ * guests with very many vCPUs and a device that is only used by a few
+ * vCPUs. Unfortunately optimizing that case requires manual pinning inside
+ * the guest, so those users might as well manually set the number of
+ * queues. There is no upper limit that can be applied automatically and
+ * doing so arbitrarily would result in a sudden performance drop once the
+ * threshold number of vCPUs is exceeded.
+ */
+ unsigned num_queues = current_machine->smp.cpus;
+
+ /*
+ * The maximum number of MSI-X vectors is PCI_MSIX_FLAGS_QSIZE + 1, but the
+ * config change interrupt and the fixed virtqueues must be taken into
+ * account too.
+ */
+ num_queues = MIN(num_queues, PCI_MSIX_FLAGS_QSIZE - fixed_queues);
+
+ /*
+ * There is a limit to how many virtqueues a device can have.
+ */
+ return MIN(num_queues, VIRTIO_QUEUE_MAX - fixed_queues);
+}
+
/* virtio-pci-bus */
static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size,
diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
index e2eaaa9182..91096f0291 100644
--- a/hw/virtio/virtio-pci.h
+++ b/hw/virtio/virtio-pci.h
@@ -243,4 +243,13 @@ typedef struct VirtioPCIDeviceTypeInfo {
/* Register virtio-pci type(s). @t must be static. */
void virtio_pci_types_register(const VirtioPCIDeviceTypeInfo *t);
+/**
+ * virtio_pci_optimal_num_queues:
+ * @fixed_queues: number of queues that are always present
+ *
+ * Returns: The optimal number of queues for a multi-queue device, excluding
+ * @fixed_queues.
+ */
+unsigned virtio_pci_optimal_num_queues(unsigned fixed_queues);
+
#endif
diff --git a/hw/virtio/virtio-scsi-pci.c b/hw/virtio/virtio-scsi-pci.c
index c23a134202..fa4b3bfb50 100644
--- a/hw/virtio/virtio-scsi-pci.c
+++ b/hw/virtio/virtio-scsi-pci.c
@@ -46,12 +46,17 @@ static void virtio_scsi_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
{
VirtIOSCSIPCI *dev = VIRTIO_SCSI_PCI(vpci_dev);
DeviceState *vdev = DEVICE(&dev->vdev);
- VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(vdev);
DeviceState *proxy = DEVICE(vpci_dev);
+ VirtIOSCSIConf *conf = &dev->vdev.parent_obj.conf;
char *bus_name;
+ if (conf->num_queues == VIRTIO_SCSI_AUTO_NUM_QUEUES) {
+ conf->num_queues =
+ virtio_pci_optimal_num_queues(VIRTIO_SCSI_VQ_NUM_FIXED);
+ }
+
if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) {
- vpci_dev->nvectors = vs->conf.num_queues + 3;
+ vpci_dev->nvectors = conf->num_queues + VIRTIO_SCSI_VQ_NUM_FIXED + 1;
}
/*
diff --git a/include/hw/acpi/pcihp.h b/include/hw/acpi/pcihp.h
index 8bc4a4c01d..02f4665767 100644
--- a/include/hw/acpi/pcihp.h
+++ b/include/hw/acpi/pcihp.h
@@ -67,7 +67,7 @@ void acpi_pcihp_device_unplug_request_cb(HotplugHandler *hotplug_dev,
Error **errp);
/* Called on reset */
-void acpi_pcihp_reset(AcpiPciHpState *s);
+void acpi_pcihp_reset(AcpiPciHpState *s, bool acpihp_root_off);
extern const VMStateDescription vmstate_acpi_pcihp_pci_status;
diff --git a/include/hw/virtio/vhost-user-blk.h b/include/hw/virtio/vhost-user-blk.h
index 34ad6f0c0e..292d17147c 100644
--- a/include/hw/virtio/vhost-user-blk.h
+++ b/include/hw/virtio/vhost-user-blk.h
@@ -25,6 +25,8 @@
#define VHOST_USER_BLK(obj) \
OBJECT_CHECK(VHostUserBlk, (obj), TYPE_VHOST_USER_BLK)
+#define VHOST_USER_BLK_AUTO_NUM_QUEUES UINT16_MAX
+
typedef struct VHostUserBlk {
VirtIODevice parent_obj;
CharBackend chardev;
diff --git a/include/hw/virtio/virtio-blk.h b/include/hw/virtio/virtio-blk.h
index b1334c3904..7539c2b848 100644
--- a/include/hw/virtio/virtio-blk.h
+++ b/include/hw/virtio/virtio-blk.h
@@ -30,6 +30,8 @@ struct virtio_blk_inhdr
unsigned char status;
};
+#define VIRTIO_BLK_AUTO_NUM_QUEUES UINT16_MAX
+
struct VirtIOBlkConf
{
BlockConf conf;
diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
index 24e768909d..c0b8e4dd7e 100644
--- a/include/hw/virtio/virtio-scsi.h
+++ b/include/hw/virtio/virtio-scsi.h
@@ -36,6 +36,11 @@
#define VIRTIO_SCSI_MAX_TARGET 255
#define VIRTIO_SCSI_MAX_LUN 16383
+/* Number of virtqueues that are always present */
+#define VIRTIO_SCSI_VQ_NUM_FIXED 2
+
+#define VIRTIO_SCSI_AUTO_NUM_QUEUES UINT32_MAX
+
typedef struct virtio_scsi_cmd_req VirtIOSCSICmdReq;
typedef struct virtio_scsi_cmd_resp VirtIOSCSICmdResp;
typedef struct virtio_scsi_ctrl_tmf_req VirtIOSCSICtrlTMFReq;
diff --git a/qemu-options.hx b/qemu-options.hx
index 708583b4ce..30019c4eca 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2294,7 +2294,7 @@ DEF("smbios", HAS_ARG, QEMU_OPTION_smbios,
" [,sku=str]\n"
" specify SMBIOS type 3 fields\n"
"-smbios type=4[,sock_pfx=str][,manufacturer=str][,version=str][,serial=str]\n"
- " [,asset=str][,part=str]\n"
+ " [,asset=str][,part=str][,max-speed=%d][,current-speed=%d]\n"
" specify SMBIOS type 4 fields\n"
"-smbios type=17[,loc_pfx=str][,bank=str][,manufacturer=str][,serial=str]\n"
" [,asset=str][,part=str][,speed=%d]\n"
diff --git a/tests/data/acpi/disassemle-aml.sh b/tests/data/acpi/disassemle-aml.sh
index 1d8a4d0301..253b7620a0 100755
--- a/tests/data/acpi/disassemle-aml.sh
+++ b/tests/data/acpi/disassemle-aml.sh
@@ -42,11 +42,16 @@ do
else
extra=""
fi
- asl=${aml}.dsl
if [[ "${outdir}" ]];
then
- asl="${outdir}"/${machine}/${asl}
+ # iasl strips an extension from prefix if there.
+ # since we have some files with . in the name, the
+ # last component gets interpreted as an extension:
+ # add another extension to work around that.
+ prefix="-p ${outdir}/${aml}.dsl"
+ else
+ prefix=""
fi
- iasl -d -p ${asl} ${extra} ${aml}
+ iasl ${extra} ${prefix} -d ${aml}
done
done
diff --git a/tests/data/acpi/pc/DSDT b/tests/data/acpi/pc/DSDT
index 6d0aaf729a..b121bb5bc1 100644
--- a/tests/data/acpi/pc/DSDT
+++ b/tests/data/acpi/pc/DSDT
Binary files differ
diff --git a/tests/data/acpi/pc/DSDT.acpihmat b/tests/data/acpi/pc/DSDT.acpihmat
index 2e5e02400b..b0dbb943f4 100644
--- a/tests/data/acpi/pc/DSDT.acpihmat
+++ b/tests/data/acpi/pc/DSDT.acpihmat
Binary files differ
diff --git a/tests/data/acpi/pc/DSDT.bridge b/tests/data/acpi/pc/DSDT.bridge
index 623c4c0358..7b6c7a4787 100644
--- a/tests/data/acpi/pc/DSDT.bridge
+++ b/tests/data/acpi/pc/DSDT.bridge
Binary files differ
diff --git a/tests/data/acpi/pc/DSDT.cphp b/tests/data/acpi/pc/DSDT.cphp
index e0a43ccdad..c0e8aa5b32 100644
--- a/tests/data/acpi/pc/DSDT.cphp
+++ b/tests/data/acpi/pc/DSDT.cphp
Binary files differ
diff --git a/tests/data/acpi/pc/DSDT.dimmpxm b/tests/data/acpi/pc/DSDT.dimmpxm
index 21eb065a0e..1649953b6c 100644
--- a/tests/data/acpi/pc/DSDT.dimmpxm
+++ b/tests/data/acpi/pc/DSDT.dimmpxm
Binary files differ
diff --git a/tests/data/acpi/pc/DSDT.ipmikcs b/tests/data/acpi/pc/DSDT.ipmikcs
index b8f08f266b..92748d49dc 100644
--- a/tests/data/acpi/pc/DSDT.ipmikcs
+++ b/tests/data/acpi/pc/DSDT.ipmikcs
Binary files differ
diff --git a/tests/data/acpi/pc/DSDT.memhp b/tests/data/acpi/pc/DSDT.memhp
index 9a9418f4bd..4026772906 100644
--- a/tests/data/acpi/pc/DSDT.memhp
+++ b/tests/data/acpi/pc/DSDT.memhp
Binary files differ
diff --git a/tests/data/acpi/pc/DSDT.numamem b/tests/data/acpi/pc/DSDT.numamem
index 6eec385c2e..4d9ba337a8 100644
--- a/tests/data/acpi/pc/DSDT.numamem
+++ b/tests/data/acpi/pc/DSDT.numamem
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT b/tests/data/acpi/q35/DSDT
index e63676d7a6..bba8884073 100644
--- a/tests/data/acpi/q35/DSDT
+++ b/tests/data/acpi/q35/DSDT
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.acpihmat b/tests/data/acpi/q35/DSDT.acpihmat
index cd97b81982..9cac92418b 100644
--- a/tests/data/acpi/q35/DSDT.acpihmat
+++ b/tests/data/acpi/q35/DSDT.acpihmat
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.bridge b/tests/data/acpi/q35/DSDT.bridge
index 8b0fb497db..f08b7245f5 100644
--- a/tests/data/acpi/q35/DSDT.bridge
+++ b/tests/data/acpi/q35/DSDT.bridge
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.cphp b/tests/data/acpi/q35/DSDT.cphp
index d9bb414e9b..57d859cef9 100644
--- a/tests/data/acpi/q35/DSDT.cphp
+++ b/tests/data/acpi/q35/DSDT.cphp
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.dimmpxm b/tests/data/acpi/q35/DSDT.dimmpxm
index 29f19b22a3..9d5bd5744e 100644
--- a/tests/data/acpi/q35/DSDT.dimmpxm
+++ b/tests/data/acpi/q35/DSDT.dimmpxm
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.ipmibt b/tests/data/acpi/q35/DSDT.ipmibt
index e8dea1ea42..5cd11de6a8 100644
--- a/tests/data/acpi/q35/DSDT.ipmibt
+++ b/tests/data/acpi/q35/DSDT.ipmibt
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.memhp b/tests/data/acpi/q35/DSDT.memhp
index dca76db15b..05a7a73ec4 100644
--- a/tests/data/acpi/q35/DSDT.memhp
+++ b/tests/data/acpi/q35/DSDT.memhp
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.mmio64 b/tests/data/acpi/q35/DSDT.mmio64
index 6d8facd9e1..efd3f1188f 100644
--- a/tests/data/acpi/q35/DSDT.mmio64
+++ b/tests/data/acpi/q35/DSDT.mmio64
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.numamem b/tests/data/acpi/q35/DSDT.numamem
index 737325dc30..1978b55f12 100644
--- a/tests/data/acpi/q35/DSDT.numamem
+++ b/tests/data/acpi/q35/DSDT.numamem
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.tis b/tests/data/acpi/q35/DSDT.tis
index 27ee927fc5..638de38726 100644
--- a/tests/data/acpi/q35/DSDT.tis
+++ b/tests/data/acpi/q35/DSDT.tis
Binary files differ
diff --git a/tests/data/acpi/virt/DSDT b/tests/data/acpi/virt/DSDT
index e669508d17..9b002836f3 100644
--- a/tests/data/acpi/virt/DSDT
+++ b/tests/data/acpi/virt/DSDT
Binary files differ
diff --git a/tests/data/acpi/virt/DSDT.memhp b/tests/data/acpi/virt/DSDT.memhp
index 4cb81f692d..545a18c365 100644
--- a/tests/data/acpi/virt/DSDT.memhp
+++ b/tests/data/acpi/virt/DSDT.memhp
Binary files differ
diff --git a/tests/data/acpi/virt/DSDT.numamem b/tests/data/acpi/virt/DSDT.numamem
index e669508d17..9b002836f3 100644
--- a/tests/data/acpi/virt/DSDT.numamem
+++ b/tests/data/acpi/virt/DSDT.numamem
Binary files differ
diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index d25ff35492..504b810af5 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -80,6 +80,8 @@ typedef struct {
GArray *tables;
uint32_t smbios_ep_addr;
struct smbios_21_entry_point smbios_ep_table;
+ uint16_t smbios_cpu_max_speed;
+ uint16_t smbios_cpu_curr_speed;
uint8_t *required_struct_types;
int required_struct_types_len;
QTestState *qts;
@@ -563,6 +565,31 @@ static inline bool smbios_single_instance(uint8_t type)
}
}
+static bool smbios_cpu_test(test_data *data, uint32_t addr)
+{
+ uint16_t expect_speed[2];
+ uint16_t real;
+ int offset[2];
+ int i;
+
+ /* Check CPU speed for backward compatibility */
+ offset[0] = offsetof(struct smbios_type_4, max_speed);
+ offset[1] = offsetof(struct smbios_type_4, current_speed);
+ expect_speed[0] = data->smbios_cpu_max_speed ? : 2000;
+ expect_speed[1] = data->smbios_cpu_curr_speed ? : 2000;
+
+ for (i = 0; i < 2; i++) {
+ real = qtest_readw(data->qts, addr + offset[i]);
+ if (real != expect_speed[i]) {
+ fprintf(stderr, "Unexpected SMBIOS CPU speed: real %u expect %u\n",
+ real, expect_speed[i]);
+ return false;
+ }
+ }
+
+ return true;
+}
+
static void test_smbios_structs(test_data *data)
{
DECLARE_BITMAP(struct_bitmap, SMBIOS_MAX_TYPE+1) = { 0 };
@@ -585,6 +612,10 @@ static void test_smbios_structs(test_data *data)
}
set_bit(type, struct_bitmap);
+ if (type == 4) {
+ g_assert(smbios_cpu_test(data, addr));
+ }
+
/* seek to end of unformatted string area of this struct ("\0\0") */
prv = crt = 1;
while (prv || crt) {
@@ -719,6 +750,11 @@ static void test_acpi_q35_tcg(void)
data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types);
test_acpi_one(NULL, &data);
free_test_data(&data);
+
+ data.smbios_cpu_max_speed = 3000;
+ data.smbios_cpu_curr_speed = 2600;
+ test_acpi_one("-smbios type=4,max-speed=3000,current-speed=2600", &data);
+ free_test_data(&data);
}
static void test_acpi_q35_tcg_bridge(void)
@@ -1084,6 +1120,12 @@ static void test_acpi_virt_tcg(void)
test_acpi_one("-cpu cortex-a57", &data);
free_test_data(&data);
+
+ data.smbios_cpu_max_speed = 2900;
+ data.smbios_cpu_curr_speed = 2700;
+ test_acpi_one("-cpu cortex-a57 "
+ "-smbios type=4,max-speed=2900,current-speed=2700", &data);
+ free_test_data(&data);
}
int main(int argc, char *argv[])