aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2024-09-12 16:17:26 +0100
committerPeter Maydell <peter.maydell@linaro.org>2024-09-12 16:17:27 +0100
commit3baa3c9d62bb35904cf6dadbf152922d87f06e8f (patch)
tree7d01a459bc5307d0e4b2b82fc58043f41d7528ce /hw
parent4b7ea33074450bc6148c8e1545d78f179e64adb4 (diff)
parent6e3c2d58e967cde3dadae298e81c5e8eb9fb9080 (diff)
downloadqemu-3baa3c9d62bb35904cf6dadbf152922d87f06e8f.zip
qemu-3baa3c9d62bb35904cf6dadbf152922d87f06e8f.tar.gz
qemu-3baa3c9d62bb35904cf6dadbf152922d87f06e8f.tar.bz2
Merge tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu into staging
virtio,pc,pci: features, fixes, cleanups i286 acpi speedup by precomputing _PRT by Ricardo Ribalda vhost_net speedup by using MR transactions by Zuo Boqun ich9 gained support for periodic and swsmi timer by Dominic Prinz Fixes, cleanups all over the place. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # -----BEGIN PGP SIGNATURE----- # # iQFDBAABCAAtFiEEXQn9CHHI+FuUyooNKB8NuNKNVGkFAmbhoCUPHG1zdEByZWRo # YXQuY29tAAoJECgfDbjSjVRptpUH/iR5AmJFpvAItqlPOvJiYDEch46C73tyrSws # Kk/1EbGSL7mFFD5sfdSSV4Rw8CQBsmM/Dt5VDkJKsWnOLjkBQ2CYH0MYHktnrKcJ # LlSk32HnY5p1DsXnJhgm5M7St8T3mV/oFdJCJAFgCmpx5uT8IRLrKETN8+30OaiY # xo35xAKOAS296+xsWeVubKkMq7H4y2tdZLE/22gb8rlA8d96BJIeVLQ3y3IjeUPR # 24q6c7zpObzGhYNZ/PzAKOn+YcVsV/lLAzKRZJTzTUPyG24BcjJTyyr/zNSYAgfk # lLXzIZID3GThBmrCAiDZ1z6sfo3MRg2wNS/FBXtK6fPIuFxed+8= # =ySRy # -----END PGP SIGNATURE----- # gpg: Signature made Wed 11 Sep 2024 14:50:29 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 * tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu: hw/acpi/ich9: Add periodic and swsmi timer virtio-mem: don't warn about THP sizes on a kernel without THP support hw/audio/virtio-sound: fix heap buffer overflow hw/cxl: fix physical address field in get scan media results output virtio-pci: Add lookup subregion of VirtIOPCIRegion MR vhost_net: configure all host notifiers in a single MR transaction tests/acpi: pc: update golden masters for DSDT hw/i386/acpi-build: Return a pre-computed _PRT table tests/acpi: pc: allow DSDT acpi table changes intel_iommu: Make PASID-cache and PIOTLB type invalid in legacy mode intel_iommu: Fix invalidation descriptor type field virtio: rename virtio_split_packed_update_used_idx hw/pci/pci-hmp-cmds: Avoid displaying bogus size in 'info pci' pci: don't skip function 0 occupancy verification for devfn auto assign hw/isa/vt82c686.c: Embed i8259 irq in device state instead of allocating hw: Move declaration of IRQState to header and add init function virtio: Always reset vhost devices virtio: Allow .get_vhost() without vhost_started Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/acpi/ich9.c23
-rw-r--r--hw/acpi/ich9_timer.c93
-rw-r--r--hw/acpi/meson.build2
-rw-r--r--hw/audio/trace-events1
-rw-r--r--hw/audio/virtio-snd.c24
-rw-r--r--hw/core/irq.c25
-rw-r--r--hw/cxl/cxl-mailbox-utils.c2
-rw-r--r--hw/display/vhost-user-gpu.c2
-rw-r--r--hw/i386/acpi-build.c120
-rw-r--r--hw/i386/intel_iommu.c24
-rw-r--r--hw/i386/intel_iommu_internal.h11
-rw-r--r--hw/i386/pc.c5
-rw-r--r--hw/isa/lpc_ich9.c14
-rw-r--r--hw/isa/vt82c686.c7
-rw-r--r--hw/net/vhost_net.c155
-rw-r--r--hw/net/virtio-net.c19
-rw-r--r--hw/pci/pci-hmp-cmds.c26
-rw-r--r--hw/pci/pci.c17
-rw-r--r--hw/virtio/vhost.c6
-rw-r--r--hw/virtio/virtio-crypto.c18
-rw-r--r--hw/virtio/virtio-mem.c7
-rw-r--r--hw/virtio/virtio-pci.c8
-rw-r--r--hw/virtio/virtio.c12
23 files changed, 418 insertions, 203 deletions
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index 02d8546..c15e5b8 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -35,6 +35,7 @@
#include "sysemu/runstate.h"
#include "hw/acpi/acpi.h"
#include "hw/acpi/ich9_tco.h"
+#include "hw/acpi/ich9_timer.h"
#include "hw/southbridge/ich9.h"
#include "hw/mem/pc-dimm.h"
@@ -108,6 +109,18 @@ static void ich9_smi_writel(void *opaque, hwaddr addr, uint64_t val,
}
pm->smi_en &= ~pm->smi_en_wmask;
pm->smi_en |= (val & pm->smi_en_wmask);
+ if (pm->swsmi_timer_enabled) {
+ ich9_pm_update_swsmi_timer(pm, pm->smi_en &
+ ICH9_PMIO_SMI_EN_SWSMI_EN);
+ }
+ if (pm->periodic_timer_enabled) {
+ ich9_pm_update_periodic_timer(pm, pm->smi_en &
+ ICH9_PMIO_SMI_EN_PERIODIC_EN);
+ }
+ break;
+ case 4:
+ pm->smi_sts &= ~pm->smi_sts_wmask;
+ pm->smi_sts |= (val & pm->smi_sts_wmask);
break;
}
}
@@ -286,6 +299,8 @@ static void pm_powerdown_req(Notifier *n, void *opaque)
void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, qemu_irq sci_irq)
{
+ pm->smi_sts_wmask = 0;
+
memory_region_init(&pm->io, OBJECT(lpc_pci), "ich9-pm", ICH9_PMIO_SIZE);
memory_region_set_enabled(&pm->io, false);
memory_region_add_subregion(pci_address_space_io(lpc_pci),
@@ -305,6 +320,14 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, qemu_irq sci_irq)
"acpi-smi", 8);
memory_region_add_subregion(&pm->io, ICH9_PMIO_SMI_EN, &pm->io_smi);
+ if (pm->swsmi_timer_enabled) {
+ ich9_pm_swsmi_timer_init(pm);
+ }
+
+ if (pm->periodic_timer_enabled) {
+ ich9_pm_periodic_timer_init(pm);
+ }
+
if (pm->enable_tco) {
acpi_pm_tco_init(&pm->tco_regs, &pm->io);
}
diff --git a/hw/acpi/ich9_timer.c b/hw/acpi/ich9_timer.c
new file mode 100644
index 0000000..5b1c910
--- /dev/null
+++ b/hw/acpi/ich9_timer.c
@@ -0,0 +1,93 @@
+/*
+ * QEMU ICH9 Timer emulation
+ *
+ * Copyright (c) 2024 Dominic Prinz <git@dprinz.de>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/core/cpu.h"
+#include "hw/pci/pci.h"
+#include "hw/southbridge/ich9.h"
+#include "qemu/timer.h"
+
+#include "hw/acpi/ich9_timer.h"
+
+void ich9_pm_update_swsmi_timer(ICH9LPCPMRegs *pm, bool enable)
+{
+ uint16_t swsmi_rate_sel;
+ int64_t expire_time;
+ ICH9LPCState *lpc;
+
+ if (enable) {
+ lpc = container_of(pm, ICH9LPCState, pm);
+ swsmi_rate_sel =
+ (pci_get_word(lpc->d.config + ICH9_LPC_GEN_PMCON_3) & 0xc0) >> 6;
+
+ if (swsmi_rate_sel == 0) {
+ expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 1500000LL;
+ } else {
+ expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+ 8 * (1 << swsmi_rate_sel) * 1000000LL;
+ }
+
+ timer_mod(pm->swsmi_timer, expire_time);
+ } else {
+ timer_del(pm->swsmi_timer);
+ }
+}
+
+static void ich9_pm_swsmi_timer_expired(void *opaque)
+{
+ ICH9LPCPMRegs *pm = opaque;
+
+ pm->smi_sts |= ICH9_PMIO_SMI_STS_SWSMI_STS;
+ ich9_generate_smi();
+
+ ich9_pm_update_swsmi_timer(pm, pm->smi_en & ICH9_PMIO_SMI_EN_SWSMI_EN);
+}
+
+void ich9_pm_swsmi_timer_init(ICH9LPCPMRegs *pm)
+{
+ pm->smi_sts_wmask |= ICH9_PMIO_SMI_STS_SWSMI_STS;
+ pm->swsmi_timer =
+ timer_new_ns(QEMU_CLOCK_VIRTUAL, ich9_pm_swsmi_timer_expired, pm);
+}
+
+void ich9_pm_update_periodic_timer(ICH9LPCPMRegs *pm, bool enable)
+{
+ uint16_t per_smi_sel;
+ int64_t expire_time;
+ ICH9LPCState *lpc;
+
+ if (enable) {
+ lpc = container_of(pm, ICH9LPCState, pm);
+ per_smi_sel = pci_get_word(lpc->d.config + ICH9_LPC_GEN_PMCON_1) & 3;
+ expire_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+ 8 * (1 << (3 - per_smi_sel)) * NANOSECONDS_PER_SECOND;
+
+ timer_mod(pm->periodic_timer, expire_time);
+ } else {
+ timer_del(pm->periodic_timer);
+ }
+}
+
+static void ich9_pm_periodic_timer_expired(void *opaque)
+{
+ ICH9LPCPMRegs *pm = opaque;
+
+ pm->smi_sts = ICH9_PMIO_SMI_STS_PERIODIC_STS;
+ ich9_generate_smi();
+
+ ich9_pm_update_periodic_timer(pm,
+ pm->smi_en & ICH9_PMIO_SMI_EN_PERIODIC_EN);
+}
+
+void ich9_pm_periodic_timer_init(ICH9LPCPMRegs *pm)
+{
+ pm->smi_sts_wmask |= ICH9_PMIO_SMI_STS_PERIODIC_STS;
+ pm->periodic_timer =
+ timer_new_ns(QEMU_CLOCK_VIRTUAL, ich9_pm_periodic_timer_expired, pm);
+}
diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build
index fa5c07d..7f8ccc9 100644
--- a/hw/acpi/meson.build
+++ b/hw/acpi/meson.build
@@ -24,7 +24,7 @@ acpi_ss.add(when: 'CONFIG_ACPI_PCI_BRIDGE', if_true: files('pci-bridge.c'))
acpi_ss.add(when: 'CONFIG_ACPI_PCIHP', if_true: files('pcihp.c'))
acpi_ss.add(when: 'CONFIG_ACPI_PCIHP', if_false: files('acpi-pci-hotplug-stub.c'))
acpi_ss.add(when: 'CONFIG_ACPI_VIOT', if_true: files('viot.c'))
-acpi_ss.add(when: 'CONFIG_ACPI_ICH9', if_true: files('ich9.c', 'ich9_tco.c'))
+acpi_ss.add(when: 'CONFIG_ACPI_ICH9', if_true: files('ich9.c', 'ich9_tco.c', 'ich9_timer.c'))
acpi_ss.add(when: 'CONFIG_ACPI_ERST', if_true: files('erst.c'))
acpi_ss.add(when: 'CONFIG_IPMI', if_true: files('ipmi.c'), if_false: files('ipmi-stub.c'))
acpi_ss.add(when: 'CONFIG_PC', if_false: files('acpi-x86-stub.c'))
diff --git a/hw/audio/trace-events b/hw/audio/trace-events
index b1870ff..b8ef572 100644
--- a/hw/audio/trace-events
+++ b/hw/audio/trace-events
@@ -41,7 +41,6 @@ asc_update_irq(int irq, int a, int b) "set IRQ to %d (A: 0x%x B: 0x%x)"
#virtio-snd.c
virtio_snd_get_config(void *vdev, uint32_t jacks, uint32_t streams, uint32_t chmaps) "snd %p: get_config jacks=%"PRIu32" streams=%"PRIu32" chmaps=%"PRIu32""
-virtio_snd_set_config(void *vdev, uint32_t jacks, uint32_t new_jacks, uint32_t streams, uint32_t new_streams, uint32_t chmaps, uint32_t new_chmaps) "snd %p: set_config jacks from %"PRIu32"->%"PRIu32", streams from %"PRIu32"->%"PRIu32", chmaps from %"PRIu32"->%"PRIu32
virtio_snd_get_features(void *vdev, uint64_t features) "snd %p: get_features 0x%"PRIx64
virtio_snd_vm_state_running(void) "vm state running"
virtio_snd_vm_state_stopped(void) "vm state stopped"
diff --git a/hw/audio/virtio-snd.c b/hw/audio/virtio-snd.c
index d1cf5eb..6983818 100644
--- a/hw/audio/virtio-snd.c
+++ b/hw/audio/virtio-snd.c
@@ -108,29 +108,6 @@ virtio_snd_get_config(VirtIODevice *vdev, uint8_t *config)
}
static void
-virtio_snd_set_config(VirtIODevice *vdev, const uint8_t *config)
-{
- VirtIOSound *s = VIRTIO_SND(vdev);
- const virtio_snd_config *sndconfig =
- (const virtio_snd_config *)config;
-
-
- trace_virtio_snd_set_config(vdev,
- s->snd_conf.jacks,
- sndconfig->jacks,
- s->snd_conf.streams,
- sndconfig->streams,
- s->snd_conf.chmaps,
- sndconfig->chmaps);
-
- memcpy(&s->snd_conf, sndconfig, sizeof(virtio_snd_config));
- le32_to_cpus(&s->snd_conf.jacks);
- le32_to_cpus(&s->snd_conf.streams);
- le32_to_cpus(&s->snd_conf.chmaps);
-
-}
-
-static void
virtio_snd_pcm_buffer_free(VirtIOSoundPCMBuffer *buffer)
{
g_free(buffer->elem);
@@ -1400,7 +1377,6 @@ static void virtio_snd_class_init(ObjectClass *klass, void *data)
vdc->realize = virtio_snd_realize;
vdc->unrealize = virtio_snd_unrealize;
vdc->get_config = virtio_snd_get_config;
- vdc->set_config = virtio_snd_set_config;
vdc->get_features = get_features;
vdc->reset = virtio_snd_reset;
vdc->legacy_features = 0;
diff --git a/hw/core/irq.c b/hw/core/irq.c
index 3f14e2d..db95ffc 100644
--- a/hw/core/irq.c
+++ b/hw/core/irq.c
@@ -26,16 +26,6 @@
#include "hw/irq.h"
#include "qom/object.h"
-OBJECT_DECLARE_SIMPLE_TYPE(IRQState, IRQ)
-
-struct IRQState {
- Object parent_obj;
-
- qemu_irq_handler handler;
- void *opaque;
- int n;
-};
-
void qemu_set_irq(qemu_irq irq, int level)
{
if (!irq)
@@ -44,6 +34,15 @@ void qemu_set_irq(qemu_irq irq, int level)
irq->handler(irq->opaque, irq->n, level);
}
+void qemu_init_irq(IRQState *irq, qemu_irq_handler handler, void *opaque,
+ int n)
+{
+ object_initialize(irq, sizeof(*irq), TYPE_IRQ);
+ irq->handler = handler;
+ irq->opaque = opaque;
+ irq->n = n;
+}
+
qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler handler,
void *opaque, int n)
{
@@ -69,10 +68,8 @@ qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n)
{
IRQState *irq;
- irq = IRQ(object_new(TYPE_IRQ));
- irq->handler = handler;
- irq->opaque = opaque;
- irq->n = n;
+ irq = g_new(IRQState, 1);
+ qemu_init_irq(irq, handler, opaque, n);
return irq;
}
diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
index 3ebbd32..9258e48 100644
--- a/hw/cxl/cxl-mailbox-utils.c
+++ b/hw/cxl/cxl-mailbox-utils.c
@@ -2076,7 +2076,7 @@ static CXLRetCode cmd_media_get_scan_media_results(const struct cxl_cmd *cmd,
start = ROUND_DOWN(ent->start, 64ull);
stop = ROUND_DOWN(ent->start, 64ull) + ent->length;
- stq_le_p(&out->records[i].addr, start | (ent->type & 0x7));
+ stq_le_p(&out->records[i].addr, start);
stl_le_p(&out->records[i].length, (stop - start) / CXL_CACHE_LINE_SIZE);
i++;
diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
index c0c6691..14548f1 100644
--- a/hw/display/vhost-user-gpu.c
+++ b/hw/display/vhost-user-gpu.c
@@ -642,7 +642,7 @@ vhost_user_gpu_device_realize(DeviceState *qdev, Error **errp)
static struct vhost_dev *vhost_user_gpu_get_vhost(VirtIODevice *vdev)
{
VhostUserGPU *g = VHOST_USER_GPU(vdev);
- return &g->vhost->dev;
+ return g->vhost ? &g->vhost->dev : NULL;
}
static Property vhost_user_gpu_properties[] = {
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 5d4bd2b..4967aa7 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -724,120 +724,44 @@ static Aml *aml_pci_pdsm(void)
return method;
}
-/**
- * build_prt_entry:
- * @link_name: link name for PCI route entry
- *
- * build AML package containing a PCI route entry for @link_name
- */
-static Aml *build_prt_entry(const char *link_name)
-{
- Aml *a_zero = aml_int(0);
- Aml *pkg = aml_package(4);
- aml_append(pkg, a_zero);
- aml_append(pkg, a_zero);
- aml_append(pkg, aml_name("%s", link_name));
- aml_append(pkg, a_zero);
- return pkg;
-}
-
/*
- * initialize_route - Initialize the interrupt routing rule
- * through a specific LINK:
- * if (lnk_idx == idx)
- * route using link 'link_name'
- */
-static Aml *initialize_route(Aml *route, const char *link_name,
- Aml *lnk_idx, int idx)
-{
- Aml *if_ctx = aml_if(aml_equal(lnk_idx, aml_int(idx)));
- Aml *pkg = build_prt_entry(link_name);
-
- aml_append(if_ctx, aml_store(pkg, route));
-
- return if_ctx;
-}
-
-/*
- * build_prt - Define interrupt rounting rules
+ * build_prt - Define interrupt routing rules
*
* Returns an array of 128 routes, one for each device,
* based on device location.
* The main goal is to equally distribute the interrupts
* over the 4 existing ACPI links (works only for i440fx).
- * The hash function is (slot + pin) & 3 -> "LNK[D|A|B|C]".
+ * The hash function is: (slot + pin) & 3 -> "LNK[D|A|B|C]".
*
*/
static Aml *build_prt(bool is_pci0_prt)
{
- Aml *method, *while_ctx, *pin, *res;
+ const int nroutes = 128;
+ Aml *rt_pkg, *method;
+ int pin;
method = aml_method("_PRT", 0, AML_NOTSERIALIZED);
- res = aml_local(0);
- pin = aml_local(1);
- aml_append(method, aml_store(aml_package(128), res));
- aml_append(method, aml_store(aml_int(0), pin));
+ rt_pkg = aml_varpackage(nroutes);
- /* while (pin < 128) */
- while_ctx = aml_while(aml_lless(pin, aml_int(128)));
- {
- Aml *slot = aml_local(2);
- Aml *lnk_idx = aml_local(3);
- Aml *route = aml_local(4);
-
- /* slot = pin >> 2 */
- aml_append(while_ctx,
- aml_store(aml_shiftright(pin, aml_int(2), NULL), slot));
- /* lnk_idx = (slot + pin) & 3 */
- aml_append(while_ctx,
- aml_store(aml_and(aml_add(pin, slot, NULL), aml_int(3), NULL),
- lnk_idx));
-
- /* route[2] = "LNK[D|A|B|C]", selection based on pin % 3 */
- aml_append(while_ctx, initialize_route(route, "LNKD", lnk_idx, 0));
- if (is_pci0_prt) {
- Aml *if_device_1, *if_pin_4, *else_pin_4;
-
- /* device 1 is the power-management device, needs SCI */
- if_device_1 = aml_if(aml_equal(lnk_idx, aml_int(1)));
- {
- if_pin_4 = aml_if(aml_equal(pin, aml_int(4)));
- {
- aml_append(if_pin_4,
- aml_store(build_prt_entry("LNKS"), route));
- }
- aml_append(if_device_1, if_pin_4);
- else_pin_4 = aml_else();
- {
- aml_append(else_pin_4,
- aml_store(build_prt_entry("LNKA"), route));
- }
- aml_append(if_device_1, else_pin_4);
- }
- aml_append(while_ctx, if_device_1);
+ for (pin = 0; pin < nroutes; pin++) {
+ Aml *pkg = aml_package(4);
+ int slot = pin >> 2;
+
+ aml_append(pkg, aml_int((slot << 16) | 0xFFFF));
+ aml_append(pkg, aml_int(pin & 3));
+ /* device 1 is the power-management device, needs SCI */
+ if (is_pci0_prt && pin == 4) {
+ aml_append(pkg, aml_name("%s", "LNKS"));
} else {
- aml_append(while_ctx, initialize_route(route, "LNKA", lnk_idx, 1));
+ static const char link_name[][5] = {"LNKD", "LNKA", "LNKB", "LNKC"};
+ int hash = (slot + pin) & 3;
+ aml_append(pkg, aml_name("%s", link_name[hash]));
}
- aml_append(while_ctx, initialize_route(route, "LNKB", lnk_idx, 2));
- aml_append(while_ctx, initialize_route(route, "LNKC", lnk_idx, 3));
-
- /* route[0] = 0x[slot]FFFF */
- aml_append(while_ctx,
- aml_store(aml_or(aml_shiftleft(slot, aml_int(16)), aml_int(0xFFFF),
- NULL),
- aml_index(route, aml_int(0))));
- /* route[1] = pin & 3 */
- aml_append(while_ctx,
- aml_store(aml_and(pin, aml_int(3), NULL),
- aml_index(route, aml_int(1))));
- /* res[pin] = route */
- aml_append(while_ctx, aml_store(route, aml_index(res, pin)));
- /* pin++ */
- aml_append(while_ctx, aml_increment(pin));
+ aml_append(pkg, aml_int(0));
+ aml_append(rt_pkg, pkg);
}
- aml_append(method, while_ctx);
- /* return res*/
- aml_append(method, aml_return(res));
+
+ aml_append(method, aml_return(rt_pkg));
return method;
}
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 16d2885..90cd4e5 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -2744,7 +2744,7 @@ static bool vtd_process_inv_desc(IntelIOMMUState *s)
return false;
}
- desc_type = inv_desc.lo & VTD_INV_DESC_TYPE;
+ desc_type = VTD_INV_DESC_TYPE(inv_desc.lo);
/* FIXME: should update at first or at last? */
s->iq_last_desc_type = desc_type;
@@ -2763,17 +2763,6 @@ static bool vtd_process_inv_desc(IntelIOMMUState *s)
}
break;
- /*
- * TODO: the entity of below two cases will be implemented in future series.
- * To make guest (which integrates scalable mode support patch set in
- * iommu driver) work, just return true is enough so far.
- */
- case VTD_INV_DESC_PC:
- break;
-
- case VTD_INV_DESC_PIOTLB:
- break;
-
case VTD_INV_DESC_WAIT:
trace_vtd_inv_desc("wait", inv_desc.hi, inv_desc.lo);
if (!vtd_process_wait_desc(s, &inv_desc)) {
@@ -2795,6 +2784,17 @@ static bool vtd_process_inv_desc(IntelIOMMUState *s)
}
break;
+ /*
+ * TODO: the entity of below two cases will be implemented in future series.
+ * To make guest (which integrates scalable mode support patch set in
+ * iommu driver) work, just return true is enough so far.
+ */
+ case VTD_INV_DESC_PC:
+ case VTD_INV_DESC_PIOTLB:
+ if (s->scalable_mode) {
+ break;
+ }
+ /* fallthrough */
default:
error_report_once("%s: invalid inv desc: hi=%"PRIx64", lo=%"PRIx64
" (unknown type)", __func__, inv_desc.hi,
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index 5f32c36..13d5d12 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -356,7 +356,8 @@ union VTDInvDesc {
typedef union VTDInvDesc VTDInvDesc;
/* Masks for struct VTDInvDesc */
-#define VTD_INV_DESC_TYPE 0xf
+#define VTD_INV_DESC_TYPE(val) ((((val) >> 5) & 0x70ULL) | \
+ ((val) & 0xfULL))
#define VTD_INV_DESC_CC 0x1 /* Context-cache Invalidate Desc */
#define VTD_INV_DESC_IOTLB 0x2
#define VTD_INV_DESC_DEVICE 0x3
@@ -372,7 +373,7 @@ typedef union VTDInvDesc VTDInvDesc;
#define VTD_INV_DESC_WAIT_IF (1ULL << 4)
#define VTD_INV_DESC_WAIT_FN (1ULL << 6)
#define VTD_INV_DESC_WAIT_DATA_SHIFT 32
-#define VTD_INV_DESC_WAIT_RSVD_LO 0Xffffff80ULL
+#define VTD_INV_DESC_WAIT_RSVD_LO 0Xfffff180ULL
#define VTD_INV_DESC_WAIT_RSVD_HI 3ULL
/* Masks for Context-cache Invalidation Descriptor */
@@ -383,7 +384,7 @@ typedef union VTDInvDesc VTDInvDesc;
#define VTD_INV_DESC_CC_DID(val) (((val) >> 16) & VTD_DOMAIN_ID_MASK)
#define VTD_INV_DESC_CC_SID(val) (((val) >> 32) & 0xffffUL)
#define VTD_INV_DESC_CC_FM(val) (((val) >> 48) & 3UL)
-#define VTD_INV_DESC_CC_RSVD 0xfffc00000000ffc0ULL
+#define VTD_INV_DESC_CC_RSVD 0xfffc00000000f1c0ULL
/* Masks for IOTLB Invalidate Descriptor */
#define VTD_INV_DESC_IOTLB_G (3ULL << 4)
@@ -393,7 +394,7 @@ typedef union VTDInvDesc VTDInvDesc;
#define VTD_INV_DESC_IOTLB_DID(val) (((val) >> 16) & VTD_DOMAIN_ID_MASK)
#define VTD_INV_DESC_IOTLB_ADDR(val) ((val) & ~0xfffULL)
#define VTD_INV_DESC_IOTLB_AM(val) ((val) & 0x3fULL)
-#define VTD_INV_DESC_IOTLB_RSVD_LO 0xffffffff0000ff00ULL
+#define VTD_INV_DESC_IOTLB_RSVD_LO 0xffffffff0000f100ULL
#define VTD_INV_DESC_IOTLB_RSVD_HI 0xf80ULL
#define VTD_INV_DESC_IOTLB_PASID_PASID (2ULL << 4)
#define VTD_INV_DESC_IOTLB_PASID_PAGE (3ULL << 4)
@@ -406,7 +407,7 @@ typedef union VTDInvDesc VTDInvDesc;
#define VTD_INV_DESC_DEVICE_IOTLB_SIZE(val) ((val) & 0x1)
#define VTD_INV_DESC_DEVICE_IOTLB_SID(val) (((val) >> 32) & 0xFFFFULL)
#define VTD_INV_DESC_DEVICE_IOTLB_RSVD_HI 0xffeULL
-#define VTD_INV_DESC_DEVICE_IOTLB_RSVD_LO 0xffff0000ffe0fff8
+#define VTD_INV_DESC_DEVICE_IOTLB_RSVD_LO 0xffff0000ffe0f1f0
/* Rsvd field masks for spte */
#define VTD_SPTE_SNP 0x800ULL
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index ba0ff51..8d84c22 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -79,7 +79,10 @@
{ "qemu64-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },\
{ "athlon-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },
-GlobalProperty pc_compat_9_1[] = {};
+GlobalProperty pc_compat_9_1[] = {
+ { "ICH9-LPC", "x-smi-swsmi-timer", "off" },
+ { "ICH9-LPC", "x-smi-periodic-timer", "off" },
+};
const size_t pc_compat_9_1_len = G_N_ELEMENTS(pc_compat_9_1);
GlobalProperty pc_compat_9_0[] = {
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index bd727b2..ab17b76 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -43,6 +43,7 @@
#include "hw/southbridge/ich9.h"
#include "hw/acpi/acpi.h"
#include "hw/acpi/ich9.h"
+#include "hw/acpi/ich9_timer.h"
#include "hw/pci/pci_bus.h"
#include "hw/qdev-properties.h"
#include "sysemu/runstate.h"
@@ -531,6 +532,15 @@ ich9_lpc_pmcon_update(ICH9LPCState *lpc)
uint16_t gen_pmcon_1 = pci_get_word(lpc->d.config + ICH9_LPC_GEN_PMCON_1);
uint16_t wmask;
+ if (lpc->pm.swsmi_timer_enabled) {
+ ich9_pm_update_swsmi_timer(
+ &lpc->pm, lpc->pm.smi_en & ICH9_PMIO_SMI_EN_SWSMI_EN);
+ }
+ if (lpc->pm.periodic_timer_enabled) {
+ ich9_pm_update_periodic_timer(
+ &lpc->pm, lpc->pm.smi_en & ICH9_PMIO_SMI_EN_PERIODIC_EN);
+ }
+
if (gen_pmcon_1 & ICH9_LPC_GEN_PMCON_1_SMI_LOCK) {
wmask = pci_get_word(lpc->d.wmask + ICH9_LPC_GEN_PMCON_1);
wmask &= ~ICH9_LPC_GEN_PMCON_1_SMI_LOCK;
@@ -826,6 +836,10 @@ static Property ich9_lpc_properties[] = {
ICH9_LPC_SMI_F_CPU_HOTPLUG_BIT, true),
DEFINE_PROP_BIT64("x-smi-cpu-hotunplug", ICH9LPCState, smi_host_features,
ICH9_LPC_SMI_F_CPU_HOT_UNPLUG_BIT, true),
+ DEFINE_PROP_BOOL("x-smi-swsmi-timer", ICH9LPCState,
+ pm.swsmi_timer_enabled, true),
+ DEFINE_PROP_BOOL("x-smi-periodic-timer", ICH9LPCState,
+ pm.periodic_timer_enabled, true),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c
index 505b44c..82591e3 100644
--- a/hw/isa/vt82c686.c
+++ b/hw/isa/vt82c686.c
@@ -592,6 +592,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(ViaISAState, VIA_ISA)
struct ViaISAState {
PCIDevice dev;
+
+ IRQState i8259_irq;
qemu_irq cpu_intr;
qemu_irq *isa_irqs_in;
uint16_t irq_state[ISA_NUM_IRQS];
@@ -715,13 +717,12 @@ static void via_isa_realize(PCIDevice *d, Error **errp)
ViaISAState *s = VIA_ISA(d);
DeviceState *dev = DEVICE(d);
PCIBus *pci_bus = pci_get_bus(d);
- qemu_irq *isa_irq;
ISABus *isa_bus;
int i;
qdev_init_gpio_out_named(dev, &s->cpu_intr, "intr", 1);
qdev_init_gpio_in_named(dev, via_isa_pirq, "pirq", PCI_NUM_PINS);
- isa_irq = qemu_allocate_irqs(via_isa_request_i8259_irq, s, 1);
+ qemu_init_irq(&s->i8259_irq, via_isa_request_i8259_irq, s, 0);
isa_bus = isa_bus_new(dev, pci_address_space(d), pci_address_space_io(d),
errp);
@@ -729,7 +730,7 @@ static void via_isa_realize(PCIDevice *d, Error **errp)
return;
}
- s->isa_irqs_in = i8259_init(isa_bus, *isa_irq);
+ s->isa_irqs_in = i8259_init(isa_bus, &s->i8259_irq);
isa_bus_register_input_irqs(isa_bus, s->isa_irqs_in);
i8254_pit_init(isa_bus, 0x40, 0, NULL);
i8257_dma_init(OBJECT(d), isa_bus, 0);
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index dedf9ad..997aab0 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -162,6 +162,135 @@ void vhost_net_save_acked_features(NetClientState *nc)
#endif
}
+static void vhost_net_disable_notifiers_nvhosts(VirtIODevice *dev,
+ NetClientState *ncs, int data_queue_pairs, int nvhosts)
+{
+ VirtIONet *n = VIRTIO_NET(dev);
+ BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev)));
+ struct vhost_net *net;
+ struct vhost_dev *hdev;
+ int r, i, j;
+ NetClientState *peer;
+
+ /*
+ * Batch all the host notifiers in a single transaction to avoid
+ * quadratic time complexity in address_space_update_ioeventfds().
+ */
+ memory_region_transaction_begin();
+
+ for (i = 0; i < nvhosts; i++) {
+ if (i < data_queue_pairs) {
+ peer = qemu_get_peer(ncs, i);
+ } else {
+ peer = qemu_get_peer(ncs, n->max_queue_pairs);
+ }
+
+ net = get_vhost_net(peer);
+ hdev = &net->dev;
+ for (j = 0; j < hdev->nvqs; j++) {
+ r = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus),
+ hdev->vq_index + j,
+ false);
+ if (r < 0) {
+ error_report("vhost %d VQ %d notifier cleanup failed: %d",
+ i, j, -r);
+ }
+ assert(r >= 0);
+ }
+ }
+ /*
+ * The transaction expects the ioeventfds to be open when it
+ * commits. Do it now, before the cleanup loop.
+ */
+ memory_region_transaction_commit();
+
+ for (i = 0; i < nvhosts; i++) {
+ if (i < data_queue_pairs) {
+ peer = qemu_get_peer(ncs, i);
+ } else {
+ peer = qemu_get_peer(ncs, n->max_queue_pairs);
+ }
+
+ net = get_vhost_net(peer);
+ hdev = &net->dev;
+ for (j = 0; j < hdev->nvqs; j++) {
+ virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus),
+ hdev->vq_index + j);
+ }
+ virtio_device_release_ioeventfd(dev);
+ }
+}
+
+static int vhost_net_enable_notifiers(VirtIODevice *dev,
+ NetClientState *ncs, int data_queue_pairs, int cvq)
+{
+ VirtIONet *n = VIRTIO_NET(dev);
+ BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev)));
+ int nvhosts = data_queue_pairs + cvq;
+ struct vhost_net *net;
+ struct vhost_dev *hdev;
+ int r, i, j;
+ NetClientState *peer;
+
+ /*
+ * Batch all the host notifiers in a single transaction to avoid
+ * quadratic time complexity in address_space_update_ioeventfds().
+ */
+ memory_region_transaction_begin();
+
+ for (i = 0; i < nvhosts; i++) {
+ if (i < data_queue_pairs) {
+ peer = qemu_get_peer(ncs, i);
+ } else {
+ peer = qemu_get_peer(ncs, n->max_queue_pairs);
+ }
+
+ net = get_vhost_net(peer);
+ hdev = &net->dev;
+ /*
+ * We will pass the notifiers to the kernel, make sure that QEMU
+ * doesn't interfere.
+ */
+ r = virtio_device_grab_ioeventfd(dev);
+ if (r < 0) {
+ error_report("binding does not support host notifiers");
+ memory_region_transaction_commit();
+ goto fail_nvhosts;
+ }
+
+ for (j = 0; j < hdev->nvqs; j++) {
+ r = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus),
+ hdev->vq_index + j,
+ true);
+ if (r < 0) {
+ error_report("vhost %d VQ %d notifier binding failed: %d",
+ i, j, -r);
+ memory_region_transaction_commit();
+ vhost_dev_disable_notifiers_nvqs(hdev, dev, j);
+ goto fail_nvhosts;
+ }
+ }
+ }
+
+ memory_region_transaction_commit();
+
+ return 0;
+fail_nvhosts:
+ vhost_net_disable_notifiers_nvhosts(dev, ncs, data_queue_pairs, i);
+ return r;
+}
+
+/*
+ * Stop processing guest IO notifications in qemu.
+ * Start processing them in vhost in kernel.
+ */
+static void vhost_net_disable_notifiers(VirtIODevice *dev,
+ NetClientState *ncs, int data_queue_pairs, int cvq)
+{
+ vhost_net_disable_notifiers_nvhosts(dev, ncs, data_queue_pairs,
+ data_queue_pairs + cvq);
+}
+
static int vhost_net_get_fd(NetClientState *backend)
{
switch (backend->info->type) {
@@ -272,11 +401,6 @@ static int vhost_net_start_one(struct vhost_net *net,
}
}
- r = vhost_dev_enable_notifiers(&net->dev, dev);
- if (r < 0) {
- goto fail_notifiers;
- }
-
r = vhost_dev_start(&net->dev, dev, false);
if (r < 0) {
goto fail_start;
@@ -328,8 +452,6 @@ fail:
}
vhost_dev_stop(&net->dev, dev, false);
fail_start:
- vhost_dev_disable_notifiers(&net->dev, dev);
-fail_notifiers:
return r;
}
@@ -351,7 +473,6 @@ static void vhost_net_stop_one(struct vhost_net *net,
if (net->nc->info->stop) {
net->nc->info->stop(net->nc);
}
- vhost_dev_disable_notifiers(&net->dev, dev);
}
int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
@@ -396,10 +517,16 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
}
}
+ r = vhost_net_enable_notifiers(dev, ncs, data_queue_pairs, cvq);
+ if (r < 0) {
+ error_report("Error enabling host notifiers: %d", -r);
+ goto err;
+ }
+
r = k->set_guest_notifiers(qbus->parent, total_notifiers, true);
if (r < 0) {
error_report("Error binding guest notifier: %d", -r);
- goto err;
+ goto err_host_notifiers;
}
for (i = 0; i < nvhosts; i++) {
@@ -414,19 +541,19 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
r = vhost_set_vring_enable(peer, peer->vring_enable);
if (r < 0) {
- goto err_start;
+ goto err_guest_notifiers;
}
}
r = vhost_net_start_one(get_vhost_net(peer), dev);
if (r < 0) {
- goto err_start;
+ goto err_guest_notifiers;
}
}
return 0;
-err_start:
+err_guest_notifiers:
while (--i >= 0) {
peer = qemu_get_peer(ncs, i < data_queue_pairs ?
i : n->max_queue_pairs);
@@ -437,6 +564,8 @@ err_start:
fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", e);
fflush(stderr);
}
+err_host_notifiers:
+ vhost_net_disable_notifiers(dev, ncs, data_queue_pairs, cvq);
err:
return r;
}
@@ -468,6 +597,8 @@ void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs,
fflush(stderr);
}
assert(r >= 0);
+
+ vhost_net_disable_notifiers(dev, ncs, data_queue_pairs, cvq);
}
void vhost_net_cleanup(struct vhost_net *net)
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index ed33a32..fb84d14 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -3896,8 +3896,23 @@ static bool dev_unplug_pending(void *opaque)
static struct vhost_dev *virtio_net_get_vhost(VirtIODevice *vdev)
{
VirtIONet *n = VIRTIO_NET(vdev);
- NetClientState *nc = qemu_get_queue(n->nic);
- struct vhost_net *net = get_vhost_net(nc->peer);
+ NetClientState *nc;
+ struct vhost_net *net;
+
+ if (!n->nic) {
+ return NULL;
+ }
+
+ nc = qemu_get_queue(n->nic);
+ if (!nc) {
+ return NULL;
+ }
+
+ net = get_vhost_net(nc->peer);
+ if (!net) {
+ return NULL;
+ }
+
return &net->dev;
}
diff --git a/hw/pci/pci-hmp-cmds.c b/hw/pci/pci-hmp-cmds.c
index b09fce9..fdfe444 100644
--- a/hw/pci/pci-hmp-cmds.c
+++ b/hw/pci/pci-hmp-cmds.c
@@ -83,15 +83,25 @@ static void hmp_info_pci_device(Monitor *mon, const PciDeviceInfo *dev)
monitor_printf(mon, " BAR%" PRId64 ": ", region->value->bar);
if (!strcmp(region->value->type, "io")) {
- monitor_printf(mon, "I/O at 0x%04" PRIx64
- " [0x%04" PRIx64 "].\n",
- addr, addr + size - 1);
+ if (addr != PCI_BAR_UNMAPPED) {
+ monitor_printf(mon, "I/O at 0x%04" PRIx64
+ " [0x%04" PRIx64 "]\n",
+ addr, addr + size - 1);
+ } else {
+ monitor_printf(mon, "I/O (not mapped)\n");
+ }
} else {
- monitor_printf(mon, "%d bit%s memory at 0x%08" PRIx64
- " [0x%08" PRIx64 "].\n",
- region->value->mem_type_64 ? 64 : 32,
- region->value->prefetch ? " prefetchable" : "",
- addr, addr + size - 1);
+ if (addr != PCI_BAR_UNMAPPED) {
+ monitor_printf(mon, "%d bit%s memory at 0x%08" PRIx64
+ " [0x%08" PRIx64 "]\n",
+ region->value->mem_type_64 ? 64 : 32,
+ region->value->prefetch ? " prefetchable" : "",
+ addr, addr + size - 1);
+ } else {
+ monitor_printf(mon, "%d bit%s memory (not mapped)\n",
+ region->value->mem_type_64 ? 64 : 32,
+ region->value->prefetch ? " prefetchable" : "");
+ }
}
}
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index d2caf3e..87da35c 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1181,14 +1181,15 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev,
PCI_SLOT(devfn), PCI_FUNC(devfn), name,
bus->devices[devfn]->name, bus->devices[devfn]->qdev.id);
return NULL;
- } /*
- * Populating function 0 triggers a scan from the guest that
- * exposes other non-zero functions. Hence we need to ensure that
- * function 0 wasn't added yet.
- */
- else if (dev->hotplugged &&
- !pci_is_vf(pci_dev) &&
- pci_get_function_0(pci_dev)) {
+ }
+
+ /*
+ * Populating function 0 triggers a scan from the guest that
+ * exposes other non-zero functions. Hence we need to ensure that
+ * function 0 wasn't added yet.
+ */
+ if (dev->hotplugged && !pci_is_vf(pci_dev) &&
+ pci_get_function_0(pci_dev)) {
error_setg(errp, "PCI: slot %d function 0 already occupied by %s,"
" new func %s cannot be exposed to guest.",
PCI_SLOT(pci_get_function_0(pci_dev)->devfn),
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 06fc717..7c5ef81 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1682,9 +1682,9 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)
memset(hdev, 0, sizeof(struct vhost_dev));
}
-static void vhost_dev_disable_notifiers_nvqs(struct vhost_dev *hdev,
- VirtIODevice *vdev,
- unsigned int nvqs)
+void vhost_dev_disable_notifiers_nvqs(struct vhost_dev *hdev,
+ VirtIODevice *vdev,
+ unsigned int nvqs)
{
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
int i, r;
diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
index 6e9d829..c3ffd83 100644
--- a/hw/virtio/virtio-crypto.c
+++ b/hw/virtio/virtio-crypto.c
@@ -1247,9 +1247,21 @@ static bool virtio_crypto_guest_notifier_pending(VirtIODevice *vdev, int idx)
static struct vhost_dev *virtio_crypto_get_vhost(VirtIODevice *vdev)
{
VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev);
- CryptoDevBackend *b = vcrypto->cryptodev;
- CryptoDevBackendClient *cc = b->conf.peers.ccs[0];
- CryptoDevBackendVhost *vhost_crypto = cryptodev_get_vhost(cc, b, 0);
+ CryptoDevBackend *b;
+ CryptoDevBackendClient *cc;
+ CryptoDevBackendVhost *vhost_crypto;
+
+ b = vcrypto->cryptodev;
+ if (!b) {
+ return NULL;
+ }
+
+ cc = b->conf.peers.ccs[0];
+ vhost_crypto = cryptodev_get_vhost(cc, b, 0);
+ if (!vhost_crypto) {
+ return NULL;
+ }
+
return &vhost_crypto->dev;
}
diff --git a/hw/virtio/virtio-mem.c b/hw/virtio/virtio-mem.c
index ef64bf1..4075f3d 100644
--- a/hw/virtio/virtio-mem.c
+++ b/hw/virtio/virtio-mem.c
@@ -88,6 +88,7 @@ static uint32_t virtio_mem_default_thp_size(void)
static uint32_t thp_size;
#define HPAGE_PMD_SIZE_PATH "/sys/kernel/mm/transparent_hugepage/hpage_pmd_size"
+#define HPAGE_PATH "/sys/kernel/mm/transparent_hugepage/"
static uint32_t virtio_mem_thp_size(void)
{
gchar *content = NULL;
@@ -98,6 +99,12 @@ static uint32_t virtio_mem_thp_size(void)
return thp_size;
}
+ /* No THP -> no restrictions. */
+ if (!g_file_test(HPAGE_PATH, G_FILE_TEST_EXISTS)) {
+ thp_size = VIRTIO_MEM_MIN_BLOCK_SIZE;
+ return thp_size;
+ }
+
/*
* Try to probe the actual THP size, fallback to (sane but eventually
* incorrect) default sizes.
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 524b63e..4d832fe 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -615,8 +615,12 @@ static MemoryRegion *virtio_address_space_lookup(VirtIOPCIProxy *proxy,
reg = &proxy->regs[i];
if (*off >= reg->offset &&
*off + len <= reg->offset + reg->size) {
- *off -= reg->offset;
- return &reg->mr;
+ MemoryRegionSection mrs = memory_region_find(&reg->mr,
+ *off - reg->offset, len);
+ assert(mrs.mr);
+ *off = mrs.offset_within_region;
+ memory_region_unref(mrs.mr);
+ return mrs.mr;
}
}
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 9e10cbc..a26f189 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -2331,8 +2331,12 @@ void virtio_reset(void *opaque)
vdev->device_endian = virtio_default_endian();
}
- if (vdev->vhost_started && k->get_vhost) {
- vhost_reset_device(k->get_vhost(vdev));
+ if (k->get_vhost) {
+ struct vhost_dev *hdev = k->get_vhost(vdev);
+ /* Only reset when vhost back-end is connected */
+ if (hdev && hdev->vhost_ops) {
+ vhost_reset_device(hdev);
+ }
}
if (k->reset) {
@@ -3665,7 +3669,7 @@ static void virtio_queue_packed_update_used_idx(VirtIODevice *vdev, int n)
return;
}
-static void virtio_split_packed_update_used_idx(VirtIODevice *vdev, int n)
+static void virtio_queue_split_update_used_idx(VirtIODevice *vdev, int n)
{
RCU_READ_LOCK_GUARD();
if (vdev->vq[n].vring.desc) {
@@ -3678,7 +3682,7 @@ void virtio_queue_update_used_idx(VirtIODevice *vdev, int n)
if (virtio_vdev_has_feature(vdev, VIRTIO_F_RING_PACKED)) {
return virtio_queue_packed_update_used_idx(vdev, n);
} else {
- return virtio_split_packed_update_used_idx(vdev, n);
+ return virtio_queue_split_update_used_idx(vdev, n);
}
}