aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/9pfs/trace-events2
-rw-r--r--hw/acpi/tpm.c2
-rw-r--r--hw/acpi/trace-events2
-rw-r--r--hw/adc/trace-events2
-rw-r--r--hw/alpha/trace-events2
-rw-r--r--hw/arm/Kconfig1
-rw-r--r--hw/arm/armv7m.c7
-rw-r--r--hw/arm/aspeed.c6
-rw-r--r--hw/arm/mcimx6ul-evk.c2
-rw-r--r--hw/arm/mcimx7d-sabre.c2
-rw-r--r--hw/arm/npcm7xx_boards.c4
-rw-r--r--hw/arm/sabrelite.c2
-rw-r--r--hw/arm/trace-events2
-rw-r--r--hw/audio/trace-events2
-rw-r--r--hw/block/dataplane/trace-events2
-rw-r--r--hw/block/trace-events2
-rw-r--r--hw/char/trace-events2
-rw-r--r--hw/core/cpu-common.c (renamed from hw/core/cpu.c)125
-rw-r--r--hw/core/cpu-sysemu.c145
-rw-r--r--hw/core/machine.c1
-rw-r--r--hw/core/meson.build3
-rw-r--r--hw/display/meson.build1
-rw-r--r--hw/display/qxl.c2
-rw-r--r--hw/display/trace-events4
-rw-r--r--hw/display/virtio-gpu-base.c3
-rw-r--r--hw/display/virtio-gpu-udmabuf.c223
-rw-r--r--hw/display/virtio-gpu-virgl.c3
-rw-r--r--hw/display/virtio-gpu.c431
-rw-r--r--hw/dma/trace-events2
-rw-r--r--hw/gpio/trace-events2
-rw-r--r--hw/hppa/trace-events2
-rw-r--r--hw/i2c/trace-events2
-rw-r--r--hw/i386/Kconfig1
-rw-r--r--hw/i386/pc.c6
-rw-r--r--hw/i386/trace-events2
-rw-r--r--hw/i386/xen/trace-events2
-rw-r--r--hw/ide/trace-events2
-rw-r--r--hw/input/hid.c4
-rw-r--r--hw/input/pckbd.c353
-rw-r--r--hw/input/ps2.c22
-rw-r--r--hw/input/trace-events4
-rw-r--r--hw/intc/trace-events2
-rw-r--r--hw/isa/trace-events2
-rw-r--r--hw/mem/Kconfig2
-rw-r--r--hw/mem/trace-events2
-rw-r--r--hw/mips/jazz.c35
-rw-r--r--hw/misc/macio/trace-events2
-rw-r--r--hw/misc/npcm7xx_clk.c2
-rw-r--r--hw/misc/trace-events2
-rw-r--r--hw/net/imx_fec.c8
-rw-r--r--hw/net/trace-events4
-rw-r--r--hw/net/virtio-net.c1
-rw-r--r--hw/nvram/trace-events2
-rw-r--r--hw/pci-host/trace-events2
-rw-r--r--hw/pci/trace-events2
-rw-r--r--hw/ppc/Kconfig1
-rw-r--r--hw/ppc/pef.c6
-rw-r--r--hw/ppc/spapr.c8
-rw-r--r--hw/ppc/spapr_nvdimm.c16
-rw-r--r--hw/ppc/spapr_pci_vfio.c40
-rw-r--r--hw/ppc/spapr_rtas.c15
-rw-r--r--hw/ppc/trace-events2
-rw-r--r--hw/rdma/trace-events2
-rw-r--r--hw/rdma/vmw/trace-events2
-rw-r--r--hw/rtc/trace-events2
-rw-r--r--hw/s390x/trace-events2
-rw-r--r--hw/scsi/scsi-disk.c12
-rw-r--r--hw/scsi/trace-events2
-rw-r--r--hw/sd/trace-events2
-rw-r--r--hw/sparc/trace-events2
-rw-r--r--hw/sparc64/trace-events2
-rw-r--r--hw/timer/trace-events2
-rw-r--r--hw/tpm/tpm_ppi.c2
-rw-r--r--hw/tpm/trace-events2
-rw-r--r--hw/usb/hcd-xhci-pci.c13
-rw-r--r--hw/usb/hcd-xhci-sysbus.c4
-rw-r--r--hw/usb/hcd-xhci.c8
-rw-r--r--hw/usb/hcd-xhci.h2
-rw-r--r--hw/usb/trace-events2
-rw-r--r--hw/vfio/trace-events2
-rw-r--r--hw/virtio/trace-events2
-rw-r--r--hw/virtio/virtio.c4
-rw-r--r--hw/watchdog/trace-events2
-rw-r--r--hw/xen/trace-events2
84 files changed, 1178 insertions, 442 deletions
diff --git a/hw/9pfs/trace-events b/hw/9pfs/trace-events
index 10188daf7f..6c77966c0b 100644
--- a/hw/9pfs/trace-events
+++ b/hw/9pfs/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# 9p.c
v9fs_rcancel(uint16_t tag, uint8_t id) "tag %d id %d"
diff --git a/hw/acpi/tpm.c b/hw/acpi/tpm.c
index b96459e45b..cdc0227536 100644
--- a/hw/acpi/tpm.c
+++ b/hw/acpi/tpm.c
@@ -57,7 +57,7 @@ void tpm_build_ppi_acpi(TPMIf *tpm, Aml *dev)
aml_operation_region(
"TPP3", AML_SYSTEM_MEMORY,
aml_int(TPM_PPI_ADDR_BASE +
- 0x15a /* movv, docs/specs/tpm.txt */),
+ 0x15a /* movv, docs/specs/tpm.rst */),
0x1));
field = aml_field("TPP3", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE);
aml_append(field, aml_named_field("MOVV", 8));
diff --git a/hw/acpi/trace-events b/hw/acpi/trace-events
index dcc1438f3a..974d770e8b 100644
--- a/hw/acpi/trace-events
+++ b/hw/acpi/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# memory_hotplug.c
mhp_acpi_invalid_slot_selected(uint32_t slot) "0x%"PRIx32
diff --git a/hw/adc/trace-events b/hw/adc/trace-events
index 4c3279ece2..456f21c8f4 100644
--- a/hw/adc/trace-events
+++ b/hw/adc/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# npcm7xx_adc.c
npcm7xx_adc_read(const char *id, uint64_t offset, uint32_t value) " %s offset: 0x%04" PRIx64 " value 0x%04" PRIx32
diff --git a/hw/alpha/trace-events b/hw/alpha/trace-events
index 5b8315f27f..952a816407 100644
--- a/hw/alpha/trace-events
+++ b/hw/alpha/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# pci.c
alpha_pci_iack_write(void) ""
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index b887f6a5b1..67723d9ea6 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -6,6 +6,7 @@ config ARM_VIRT
imply VFIO_PLATFORM
imply VFIO_XGMAC
imply TPM_TIS_SYSBUS
+ imply NVDIMM
select ARM_GIC
select ACPI
select ARM_SMMUV3
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index af0d935bf7..9ce5c30cd5 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -176,6 +176,12 @@ static void armv7m_realize(DeviceState *dev, Error **errp)
return;
}
}
+ if (object_property_find(OBJECT(s->cpu), "init-nsvtor")) {
+ if (!object_property_set_uint(OBJECT(s->cpu), "init-nsvtor",
+ s->init_nsvtor, errp)) {
+ return;
+ }
+ }
if (object_property_find(OBJECT(s->cpu), "start-powered-off")) {
if (!object_property_set_bool(OBJECT(s->cpu), "start-powered-off",
s->start_powered_off, errp)) {
@@ -254,6 +260,7 @@ static Property armv7m_properties[] = {
MemoryRegion *),
DEFINE_PROP_LINK("idau", ARMv7MState, idau, TYPE_IDAU_INTERFACE, Object *),
DEFINE_PROP_UINT32("init-svtor", ARMv7MState, init_svtor, 0),
+ DEFINE_PROP_UINT32("init-nsvtor", ARMv7MState, init_nsvtor, 0),
DEFINE_PROP_BOOL("enable-bitband", ARMv7MState, enable_bitband, false),
DEFINE_PROP_BOOL("start-powered-off", ARMv7MState, start_powered_off,
false),
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 3fe6c55744..0eafc79154 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -947,7 +947,7 @@ static void aspeed_machine_ast2600_evb_class_init(ObjectClass *oc, void *data)
MachineClass *mc = MACHINE_CLASS(oc);
AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
- mc->desc = "Aspeed AST2600 EVB (Cortex A7)";
+ mc->desc = "Aspeed AST2600 EVB (Cortex-A7)";
amc->soc_name = "ast2600-a1";
amc->hw_strap1 = AST2600_EVB_HW_STRAP1;
amc->hw_strap2 = AST2600_EVB_HW_STRAP2;
@@ -966,7 +966,7 @@ static void aspeed_machine_tacoma_class_init(ObjectClass *oc, void *data)
MachineClass *mc = MACHINE_CLASS(oc);
AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
- mc->desc = "OpenPOWER Tacoma BMC (Cortex A7)";
+ mc->desc = "OpenPOWER Tacoma BMC (Cortex-A7)";
amc->soc_name = "ast2600-a1";
amc->hw_strap1 = TACOMA_BMC_HW_STRAP1;
amc->hw_strap2 = TACOMA_BMC_HW_STRAP2;
@@ -1003,7 +1003,7 @@ static void aspeed_machine_rainier_class_init(ObjectClass *oc, void *data)
MachineClass *mc = MACHINE_CLASS(oc);
AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
- mc->desc = "IBM Rainier BMC (Cortex A7)";
+ mc->desc = "IBM Rainier BMC (Cortex-A7)";
amc->soc_name = "ast2600-a1";
amc->hw_strap1 = RAINIER_BMC_HW_STRAP1;
amc->hw_strap2 = RAINIER_BMC_HW_STRAP2;
diff --git a/hw/arm/mcimx6ul-evk.c b/hw/arm/mcimx6ul-evk.c
index ce16b6b317..77fae874b1 100644
--- a/hw/arm/mcimx6ul-evk.c
+++ b/hw/arm/mcimx6ul-evk.c
@@ -67,7 +67,7 @@ static void mcimx6ul_evk_init(MachineState *machine)
static void mcimx6ul_evk_machine_init(MachineClass *mc)
{
- mc->desc = "Freescale i.MX6UL Evaluation Kit (Cortex A7)";
+ mc->desc = "Freescale i.MX6UL Evaluation Kit (Cortex-A7)";
mc->init = mcimx6ul_evk_init;
mc->max_cpus = FSL_IMX6UL_NUM_CPUS;
mc->default_ram_id = "mcimx6ul-evk.ram";
diff --git a/hw/arm/mcimx7d-sabre.c b/hw/arm/mcimx7d-sabre.c
index e896222c34..935d4b0f1c 100644
--- a/hw/arm/mcimx7d-sabre.c
+++ b/hw/arm/mcimx7d-sabre.c
@@ -67,7 +67,7 @@ static void mcimx7d_sabre_init(MachineState *machine)
static void mcimx7d_sabre_machine_init(MachineClass *mc)
{
- mc->desc = "Freescale i.MX7 DUAL SABRE (Cortex A7)";
+ mc->desc = "Freescale i.MX7 DUAL SABRE (Cortex-A7)";
mc->init = mcimx7d_sabre_init;
mc->max_cpus = FSL_IMX7_NUM_CPUS;
mc->default_ram_id = "mcimx7d-sabre.ram";
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
index d4553e3786..698be46d30 100644
--- a/hw/arm/npcm7xx_boards.c
+++ b/hw/arm/npcm7xx_boards.c
@@ -299,7 +299,7 @@ static void npcm750_evb_machine_class_init(ObjectClass *oc, void *data)
npcm7xx_set_soc_type(nmc, TYPE_NPCM750);
- mc->desc = "Nuvoton NPCM750 Evaluation Board (Cortex A9)";
+ mc->desc = "Nuvoton NPCM750 Evaluation Board (Cortex-A9)";
mc->init = npcm750_evb_init;
mc->default_ram_size = 512 * MiB;
};
@@ -311,7 +311,7 @@ static void gsj_machine_class_init(ObjectClass *oc, void *data)
npcm7xx_set_soc_type(nmc, TYPE_NPCM730);
- mc->desc = "Quanta GSJ (Cortex A9)";
+ mc->desc = "Quanta GSJ (Cortex-A9)";
mc->init = quanta_gsj_init;
mc->default_ram_size = 512 * MiB;
};
diff --git a/hw/arm/sabrelite.c b/hw/arm/sabrelite.c
index 42348e5cb1..29fc777b61 100644
--- a/hw/arm/sabrelite.c
+++ b/hw/arm/sabrelite.c
@@ -105,7 +105,7 @@ static void sabrelite_init(MachineState *machine)
static void sabrelite_machine_init(MachineClass *mc)
{
- mc->desc = "Freescale i.MX6 Quad SABRE Lite Board (Cortex A9)";
+ mc->desc = "Freescale i.MX6 Quad SABRE Lite Board (Cortex-A9)";
mc->init = sabrelite_init;
mc->max_cpus = FSL_IMX6_NUM_CPUS;
mc->ignore_memory_transaction_failures = true;
diff --git a/hw/arm/trace-events b/hw/arm/trace-events
index b79a91af5f..2dee296c8f 100644
--- a/hw/arm/trace-events
+++ b/hw/arm/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# virt-acpi-build.c
virt_acpi_setup(void) "No fw cfg or ACPI disabled. Bailing out."
diff --git a/hw/audio/trace-events b/hw/audio/trace-events
index 432e10712f..e0e71cd9b1 100644
--- a/hw/audio/trace-events
+++ b/hw/audio/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# cs4231.c
cs4231_mem_readl_dreg(uint32_t reg, uint32_t ret) "read dreg %d: 0x%02x"
diff --git a/hw/block/dataplane/trace-events b/hw/block/dataplane/trace-events
index 843cc4e7b1..38fc3e7507 100644
--- a/hw/block/dataplane/trace-events
+++ b/hw/block/dataplane/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# virtio-blk.c
virtio_blk_data_plane_start(void *s) "dataplane %p"
diff --git a/hw/block/trace-events b/hw/block/trace-events
index 646917d045..70bed9ddb7 100644
--- a/hw/block/trace-events
+++ b/hw/block/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# fdc.c
fdc_ioport_read(uint8_t reg, uint8_t value) "read reg 0x%02x val 0x%02x"
diff --git a/hw/char/trace-events b/hw/char/trace-events
index 2e6e6b119a..1436fb462d 100644
--- a/hw/char/trace-events
+++ b/hw/char/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# parallel.c
parallel_ioport_read(const char *desc, uint16_t addr, uint8_t value) "read [%s] addr 0x%02x val 0x%02x"
diff --git a/hw/core/cpu.c b/hw/core/cpu-common.c
index 00330ba07d..e2f5a64604 100644
--- a/hw/core/cpu.c
+++ b/hw/core/cpu-common.c
@@ -34,7 +34,6 @@
#include "hw/qdev-properties.h"
#include "trace/trace-root.h"
#include "qemu/plugin.h"
-#include "sysemu/hw_accel.h"
CPUState *cpu_by_arch_id(int64_t id)
{
@@ -67,33 +66,6 @@ CPUState *cpu_create(const char *typename)
return cpu;
}
-bool cpu_paging_enabled(const CPUState *cpu)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
-
- return cc->get_paging_enabled(cpu);
-}
-
-static bool cpu_common_get_paging_enabled(const CPUState *cpu)
-{
- return false;
-}
-
-void cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list,
- Error **errp)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
-
- cc->get_memory_mapping(cpu, list, errp);
-}
-
-static void cpu_common_get_memory_mapping(CPUState *cpu,
- MemoryMappingList *list,
- Error **errp)
-{
- error_setg(errp, "Obtaining memory mappings is unsupported on this CPU.");
-}
-
/* Resetting the IRQ comes from across the code base so we take the
* BQL here if we need to. cpu_interrupt assumes it is held.*/
void cpu_reset_interrupt(CPUState *cpu, int mask)
@@ -117,65 +89,6 @@ void cpu_exit(CPUState *cpu)
qatomic_set(&cpu->icount_decr_ptr->u16.high, -1);
}
-int cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
- void *opaque)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
-
- return (*cc->write_elf32_qemunote)(f, cpu, opaque);
-}
-
-static int cpu_common_write_elf32_qemunote(WriteCoreDumpFunction f,
- CPUState *cpu, void *opaque)
-{
- return 0;
-}
-
-int cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cpu,
- int cpuid, void *opaque)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
-
- return (*cc->write_elf32_note)(f, cpu, cpuid, opaque);
-}
-
-static int cpu_common_write_elf32_note(WriteCoreDumpFunction f,
- CPUState *cpu, int cpuid,
- void *opaque)
-{
- return -1;
-}
-
-int cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
- void *opaque)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
-
- return (*cc->write_elf64_qemunote)(f, cpu, opaque);
-}
-
-static int cpu_common_write_elf64_qemunote(WriteCoreDumpFunction f,
- CPUState *cpu, void *opaque)
-{
- return 0;
-}
-
-int cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu,
- int cpuid, void *opaque)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
-
- return (*cc->write_elf64_note)(f, cpu, cpuid, opaque);
-}
-
-static int cpu_common_write_elf64_note(WriteCoreDumpFunction f,
- CPUState *cpu, int cpuid,
- void *opaque)
-{
- return -1;
-}
-
-
static int cpu_common_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg)
{
return 0;
@@ -186,28 +99,6 @@ static int cpu_common_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg)
return 0;
}
-static bool cpu_common_virtio_is_big_endian(CPUState *cpu)
-{
- return target_words_bigendian();
-}
-
-/*
- * XXX the following #if is always true because this is a common_ss
- * module, so target CONFIG_* is never defined.
- */
-#if !defined(CONFIG_USER_ONLY)
-GuestPanicInformation *cpu_get_crash_info(CPUState *cpu)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
- GuestPanicInformation *res = NULL;
-
- if (cc->get_crash_info) {
- res = cc->get_crash_info(cpu);
- }
- return res;
-}
-#endif
-
void cpu_dump_state(CPUState *cpu, FILE *f, int flags)
{
CPUClass *cc = CPU_GET_CLASS(cpu);
@@ -218,15 +109,6 @@ void cpu_dump_state(CPUState *cpu, FILE *f, int flags)
}
}
-void cpu_dump_statistics(CPUState *cpu, int flags)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
-
- if (cc->dump_statistics) {
- cc->dump_statistics(cpu, flags);
- }
-}
-
void cpu_reset(CPUState *cpu)
{
device_cold_reset(DEVICE(cpu));
@@ -398,15 +280,8 @@ static void cpu_class_init(ObjectClass *klass, void *data)
k->parse_features = cpu_common_parse_features;
k->get_arch_id = cpu_common_get_arch_id;
k->has_work = cpu_common_has_work;
- k->get_paging_enabled = cpu_common_get_paging_enabled;
- k->get_memory_mapping = cpu_common_get_memory_mapping;
- k->write_elf32_qemunote = cpu_common_write_elf32_qemunote;
- k->write_elf32_note = cpu_common_write_elf32_note;
- k->write_elf64_qemunote = cpu_common_write_elf64_qemunote;
- k->write_elf64_note = cpu_common_write_elf64_note;
k->gdb_read_register = cpu_common_gdb_read_register;
k->gdb_write_register = cpu_common_gdb_write_register;
- k->virtio_is_big_endian = cpu_common_virtio_is_big_endian;
set_bit(DEVICE_CATEGORY_CPU, dc->categories);
dc->realize = cpu_common_realizefn;
dc->unrealize = cpu_common_unrealizefn;
diff --git a/hw/core/cpu-sysemu.c b/hw/core/cpu-sysemu.c
new file mode 100644
index 0000000000..00253f8929
--- /dev/null
+++ b/hw/core/cpu-sysemu.c
@@ -0,0 +1,145 @@
+/*
+ * QEMU CPU model (system emulation specific)
+ *
+ * Copyright (c) 2012-2014 SUSE LINUX Products GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see
+ * <http://www.gnu.org/licenses/gpl-2.0.html>
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/core/cpu.h"
+#include "hw/core/sysemu-cpu-ops.h"
+
+bool cpu_paging_enabled(const CPUState *cpu)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ if (cc->sysemu_ops->get_paging_enabled) {
+ return cc->sysemu_ops->get_paging_enabled(cpu);
+ }
+
+ return false;
+}
+
+void cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list,
+ Error **errp)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ if (cc->sysemu_ops->get_memory_mapping) {
+ cc->sysemu_ops->get_memory_mapping(cpu, list, errp);
+ return;
+ }
+
+ error_setg(errp, "Obtaining memory mappings is unsupported on this CPU.");
+}
+
+hwaddr cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
+ MemTxAttrs *attrs)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ if (cc->sysemu_ops->get_phys_page_attrs_debug) {
+ return cc->sysemu_ops->get_phys_page_attrs_debug(cpu, addr, attrs);
+ }
+ /* Fallback for CPUs which don't implement the _attrs_ hook */
+ *attrs = MEMTXATTRS_UNSPECIFIED;
+ return cc->sysemu_ops->get_phys_page_debug(cpu, addr);
+}
+
+hwaddr cpu_get_phys_page_debug(CPUState *cpu, vaddr addr)
+{
+ MemTxAttrs attrs = {};
+
+ return cpu_get_phys_page_attrs_debug(cpu, addr, &attrs);
+}
+
+int cpu_asidx_from_attrs(CPUState *cpu, MemTxAttrs attrs)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+ int ret = 0;
+
+ if (cc->sysemu_ops->asidx_from_attrs) {
+ ret = cc->sysemu_ops->asidx_from_attrs(cpu, attrs);
+ assert(ret < cpu->num_ases && ret >= 0);
+ }
+ return ret;
+}
+
+int cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
+ void *opaque)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ if (!cc->sysemu_ops->write_elf32_qemunote) {
+ return 0;
+ }
+ return (*cc->sysemu_ops->write_elf32_qemunote)(f, cpu, opaque);
+}
+
+int cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cpu,
+ int cpuid, void *opaque)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ if (!cc->sysemu_ops->write_elf32_note) {
+ return -1;
+ }
+ return (*cc->sysemu_ops->write_elf32_note)(f, cpu, cpuid, opaque);
+}
+
+int cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
+ void *opaque)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ if (!cc->sysemu_ops->write_elf64_qemunote) {
+ return 0;
+ }
+ return (*cc->sysemu_ops->write_elf64_qemunote)(f, cpu, opaque);
+}
+
+int cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu,
+ int cpuid, void *opaque)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ if (!cc->sysemu_ops->write_elf64_note) {
+ return -1;
+ }
+ return (*cc->sysemu_ops->write_elf64_note)(f, cpu, cpuid, opaque);
+}
+
+bool cpu_virtio_is_big_endian(CPUState *cpu)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+
+ if (cc->sysemu_ops->virtio_is_big_endian) {
+ return cc->sysemu_ops->virtio_is_big_endian(cpu);
+ }
+ return target_words_bigendian();
+}
+
+GuestPanicInformation *cpu_get_crash_info(CPUState *cpu)
+{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+ GuestPanicInformation *res = NULL;
+
+ if (cc->sysemu_ops->get_crash_info) {
+ res = cc->sysemu_ops->get_crash_info(cpu);
+ }
+ return res;
+}
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 1bf0e687b9..55b9bc7817 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -38,6 +38,7 @@
GlobalProperty hw_compat_6_0[] = {
{ "gpex-pcihost", "allow-unmapped-accesses", "false" },
+ { "i8042", "extended-state", "false"},
};
const size_t hw_compat_6_0_len = G_N_ELEMENTS(hw_compat_6_0);
diff --git a/hw/core/meson.build b/hw/core/meson.build
index 59f1605bb0..18f44fb7c2 100644
--- a/hw/core/meson.build
+++ b/hw/core/meson.build
@@ -13,7 +13,7 @@ hwcore_files = files(
'qdev-clock.c',
)
-common_ss.add(files('cpu.c'))
+common_ss.add(files('cpu-common.c'))
common_ss.add(when: 'CONFIG_FITLOADER', if_true: files('loader-fit.c'))
common_ss.add(when: 'CONFIG_GENERIC_LOADER', if_true: files('generic-loader.c'))
common_ss.add(when: ['CONFIG_GUEST_LOADER', fdt], if_true: files('guest-loader.c'))
@@ -25,6 +25,7 @@ common_ss.add(when: 'CONFIG_SPLIT_IRQ', if_true: files('split-irq.c'))
common_ss.add(when: 'CONFIG_XILINX_AXI', if_true: files('stream.c'))
softmmu_ss.add(files(
+ 'cpu-sysemu.c',
'fw-path-provider.c',
'loader.c',
'machine-hmp-cmds.c',
diff --git a/hw/display/meson.build b/hw/display/meson.build
index aaf797c5e9..e1f473c1df 100644
--- a/hw/display/meson.build
+++ b/hw/display/meson.build
@@ -56,6 +56,7 @@ if config_all_devices.has_key('CONFIG_VIRTIO_GPU')
virtio_gpu_ss = ss.source_set()
virtio_gpu_ss.add(when: 'CONFIG_VIRTIO_GPU',
if_true: [files('virtio-gpu-base.c', 'virtio-gpu.c'), pixman])
+ virtio_gpu_ss.add(when: 'CONFIG_LINUX', if_true: files('virtio-gpu-udmabuf.c'))
virtio_gpu_ss.add(when: 'CONFIG_VHOST_USER_GPU', if_true: files('vhost-user-gpu.c'))
hw_display_modules += {'virtio-gpu': virtio_gpu_ss}
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index 2ba75637ec..6e1f8ff1b2 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -321,7 +321,7 @@ static ram_addr_t qxl_rom_size(void)
#define QXL_ROM_SZ 8192
QEMU_BUILD_BUG_ON(QXL_REQUIRED_SZ > QXL_ROM_SZ);
- return QXL_ROM_SZ;
+ return QEMU_ALIGN_UP(QXL_REQUIRED_SZ, qemu_real_host_page_size);
}
static void init_qxl_rom(PCIQXLDevice *d)
diff --git a/hw/display/trace-events b/hw/display/trace-events
index 9fccca18a1..f03f6655bc 100644
--- a/hw/display/trace-events
+++ b/hw/display/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# jazz_led.c
jazz_led_read(uint64_t addr, uint8_t val) "read addr=0x%"PRIx64": 0x%x"
@@ -30,8 +30,10 @@ virtio_gpu_features(bool virgl) "virgl %d"
virtio_gpu_cmd_get_display_info(void) ""
virtio_gpu_cmd_get_edid(uint32_t scanout) "scanout %d"
virtio_gpu_cmd_set_scanout(uint32_t id, uint32_t res, uint32_t w, uint32_t h, uint32_t x, uint32_t y) "id %d, res 0x%x, w %d, h %d, x %d, y %d"
+virtio_gpu_cmd_set_scanout_blob(uint32_t id, uint32_t res, uint32_t w, uint32_t h, uint32_t x, uint32_t y) "id %d, res 0x%x, w %d, h %d, x %d, y %d"
virtio_gpu_cmd_res_create_2d(uint32_t res, uint32_t fmt, uint32_t w, uint32_t h) "res 0x%x, fmt 0x%x, w %d, h %d"
virtio_gpu_cmd_res_create_3d(uint32_t res, uint32_t fmt, uint32_t w, uint32_t h, uint32_t d) "res 0x%x, fmt 0x%x, w %d, h %d, d %d"
+virtio_gpu_cmd_res_create_blob(uint32_t res, uint64_t size) "res 0x%x, size %" PRId64
virtio_gpu_cmd_res_unref(uint32_t res) "res 0x%x"
virtio_gpu_cmd_res_back_attach(uint32_t res) "res 0x%x"
virtio_gpu_cmd_res_back_detach(uint32_t res) "res 0x%x"
diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c
index afb3ee7d9a..dd294276cb 100644
--- a/hw/display/virtio-gpu-base.c
+++ b/hw/display/virtio-gpu-base.c
@@ -208,6 +208,9 @@ virtio_gpu_base_get_features(VirtIODevice *vdev, uint64_t features,
if (virtio_gpu_edid_enabled(g->conf)) {
features |= (1 << VIRTIO_GPU_F_EDID);
}
+ if (virtio_gpu_blob_enabled(g->conf)) {
+ features |= (1 << VIRTIO_GPU_F_RESOURCE_BLOB);
+ }
return features;
}
diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c
new file mode 100644
index 0000000000..3c01a415e7
--- /dev/null
+++ b/hw/display/virtio-gpu-udmabuf.c
@@ -0,0 +1,223 @@
+/*
+ * Virtio GPU Device
+ *
+ * Copyright Red Hat, Inc. 2013-2014
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ * Gerd Hoffmann <kraxel@redhat.com>
+ *
+ * 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 "qemu/units.h"
+#include "qemu-common.h"
+#include "qemu/iov.h"
+#include "ui/console.h"
+#include "hw/virtio/virtio-gpu.h"
+#include "hw/virtio/virtio-gpu-pixman.h"
+#include "trace.h"
+#include "exec/ramblock.h"
+#include "sysemu/hostmem.h"
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <linux/memfd.h>
+#include "qemu/memfd.h"
+#include "standard-headers/linux/udmabuf.h"
+
+static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res)
+{
+ struct udmabuf_create_list *list;
+ RAMBlock *rb;
+ ram_addr_t offset;
+ int udmabuf, i;
+
+ udmabuf = udmabuf_fd();
+ if (udmabuf < 0) {
+ return;
+ }
+
+ list = g_malloc0(sizeof(struct udmabuf_create_list) +
+ sizeof(struct udmabuf_create_item) * res->iov_cnt);
+
+ for (i = 0; i < res->iov_cnt; i++) {
+ rcu_read_lock();
+ rb = qemu_ram_block_from_host(res->iov[i].iov_base, false, &offset);
+ rcu_read_unlock();
+
+ if (!rb || rb->fd < 0) {
+ g_free(list);
+ return;
+ }
+
+ list->list[i].memfd = rb->fd;
+ list->list[i].offset = offset;
+ list->list[i].size = res->iov[i].iov_len;
+ }
+
+ list->count = res->iov_cnt;
+ list->flags = UDMABUF_FLAGS_CLOEXEC;
+
+ res->dmabuf_fd = ioctl(udmabuf, UDMABUF_CREATE_LIST, list);
+ if (res->dmabuf_fd < 0) {
+ warn_report("%s: UDMABUF_CREATE_LIST: %s", __func__,
+ strerror(errno));
+ }
+ g_free(list);
+}
+
+static void virtio_gpu_remap_udmabuf(struct virtio_gpu_simple_resource *res)
+{
+ res->remapped = mmap(NULL, res->blob_size, PROT_READ,
+ MAP_SHARED, res->dmabuf_fd, 0);
+ if (res->remapped == MAP_FAILED) {
+ warn_report("%s: dmabuf mmap failed: %s", __func__,
+ strerror(errno));
+ res->remapped = NULL;
+ }
+}
+
+static void virtio_gpu_destroy_udmabuf(struct virtio_gpu_simple_resource *res)
+{
+ if (res->remapped) {
+ munmap(res->remapped, res->blob_size);
+ res->remapped = NULL;
+ }
+ if (res->dmabuf_fd >= 0) {
+ close(res->dmabuf_fd);
+ res->dmabuf_fd = -1;
+ }
+}
+
+static int find_memory_backend_type(Object *obj, void *opaque)
+{
+ bool *memfd_backend = opaque;
+ int ret;
+
+ if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) {
+ HostMemoryBackend *backend = MEMORY_BACKEND(obj);
+ RAMBlock *rb = backend->mr.ram_block;
+
+ if (rb && rb->fd > 0) {
+ ret = fcntl(rb->fd, F_GET_SEALS);
+ if (ret > 0) {
+ *memfd_backend = true;
+ }
+ }
+ }
+
+ return 0;
+}
+
+bool virtio_gpu_have_udmabuf(void)
+{
+ Object *memdev_root;
+ int udmabuf;
+ bool memfd_backend = false;
+
+ udmabuf = udmabuf_fd();
+ if (udmabuf < 0) {
+ return false;
+ }
+
+ memdev_root = object_resolve_path("/objects", NULL);
+ object_child_foreach(memdev_root, find_memory_backend_type, &memfd_backend);
+
+ return memfd_backend;
+}
+
+void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
+{
+ void *pdata = NULL;
+
+ res->dmabuf_fd = -1;
+ if (res->iov_cnt == 1) {
+ pdata = res->iov[0].iov_base;
+ } else {
+ virtio_gpu_create_udmabuf(res);
+ if (res->dmabuf_fd < 0) {
+ return;
+ }
+ virtio_gpu_remap_udmabuf(res);
+ if (!res->remapped) {
+ return;
+ }
+ pdata = res->remapped;
+ }
+
+ res->blob = pdata;
+}
+
+void virtio_gpu_fini_udmabuf(struct virtio_gpu_simple_resource *res)
+{
+ if (res->remapped) {
+ virtio_gpu_destroy_udmabuf(res);
+ }
+}
+
+static void virtio_gpu_free_dmabuf(VirtIOGPU *g, VGPUDMABuf *dmabuf)
+{
+ struct virtio_gpu_scanout *scanout;
+
+ scanout = &g->parent_obj.scanout[dmabuf->scanout_id];
+ dpy_gl_release_dmabuf(scanout->con, &dmabuf->buf);
+ QTAILQ_REMOVE(&g->dmabuf.bufs, dmabuf, next);
+ g_free(dmabuf);
+}
+
+static VGPUDMABuf
+*virtio_gpu_create_dmabuf(VirtIOGPU *g,
+ uint32_t scanout_id,
+ struct virtio_gpu_simple_resource *res,
+ struct virtio_gpu_framebuffer *fb)
+{
+ VGPUDMABuf *dmabuf;
+
+ if (res->dmabuf_fd < 0) {
+ return NULL;
+ }
+
+ dmabuf = g_new0(VGPUDMABuf, 1);
+ dmabuf->buf.width = fb->width;
+ dmabuf->buf.height = fb->height;
+ dmabuf->buf.stride = fb->stride;
+ dmabuf->buf.fourcc = qemu_pixman_to_drm_format(fb->format);
+ dmabuf->buf.fd = res->dmabuf_fd;
+
+ dmabuf->scanout_id = scanout_id;
+ QTAILQ_INSERT_HEAD(&g->dmabuf.bufs, dmabuf, next);
+
+ return dmabuf;
+}
+
+int virtio_gpu_update_dmabuf(VirtIOGPU *g,
+ uint32_t scanout_id,
+ struct virtio_gpu_simple_resource *res,
+ struct virtio_gpu_framebuffer *fb)
+{
+ struct virtio_gpu_scanout *scanout = &g->parent_obj.scanout[scanout_id];
+ VGPUDMABuf *new_primary, *old_primary = NULL;
+
+ new_primary = virtio_gpu_create_dmabuf(g, scanout_id, res, fb);
+ if (!new_primary) {
+ return -EINVAL;
+ }
+
+ if (g->dmabuf.primary) {
+ old_primary = g->dmabuf.primary;
+ }
+
+ g->dmabuf.primary = new_primary;
+ qemu_console_resize(scanout->con,
+ new_primary->buf.width,
+ new_primary->buf.height);
+ dpy_gl_scanout_dmabuf(scanout->con, &new_primary->buf);
+
+ if (old_primary) {
+ virtio_gpu_free_dmabuf(g, old_primary);
+ }
+
+ return 0;
+}
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 72c14d9132..092c6dc380 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -289,7 +289,8 @@ static void virgl_resource_attach_backing(VirtIOGPU *g,
VIRTIO_GPU_FILL_CMD(att_rb);
trace_virtio_gpu_cmd_res_back_attach(att_rb.resource_id);
- ret = virtio_gpu_create_mapping_iov(g, &att_rb, cmd, NULL, &res_iovs, &res_niov);
+ ret = virtio_gpu_create_mapping_iov(g, att_rb.nr_entries, sizeof(att_rb),
+ cmd, NULL, &res_iovs, &res_niov);
if (ret != 0) {
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
return;
diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
index db56f0454a..4d549377cb 100644
--- a/hw/display/virtio-gpu.c
+++ b/hw/display/virtio-gpu.c
@@ -35,6 +35,10 @@
static struct virtio_gpu_simple_resource*
virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id);
+static struct virtio_gpu_simple_resource *
+virtio_gpu_find_check_resource(VirtIOGPU *g, uint32_t resource_id,
+ bool require_backing,
+ const char *caller, uint32_t *error);
static void virtio_gpu_cleanup_mapping(VirtIOGPU *g,
struct virtio_gpu_simple_resource *res);
@@ -45,20 +49,30 @@ void virtio_gpu_update_cursor_data(VirtIOGPU *g,
{
struct virtio_gpu_simple_resource *res;
uint32_t pixels;
+ void *data;
- res = virtio_gpu_find_resource(g, resource_id);
+ res = virtio_gpu_find_check_resource(g, resource_id, false,
+ __func__, NULL);
if (!res) {
return;
}
- if (pixman_image_get_width(res->image) != s->current_cursor->width ||
- pixman_image_get_height(res->image) != s->current_cursor->height) {
- return;
+ if (res->blob_size) {
+ if (res->blob_size < (s->current_cursor->width *
+ s->current_cursor->height * 4)) {
+ return;
+ }
+ data = res->blob;
+ } else {
+ if (pixman_image_get_width(res->image) != s->current_cursor->width ||
+ pixman_image_get_height(res->image) != s->current_cursor->height) {
+ return;
+ }
+ data = pixman_image_get_data(res->image);
}
pixels = s->current_cursor->width * s->current_cursor->height;
- memcpy(s->current_cursor->data,
- pixman_image_get_data(res->image),
+ memcpy(s->current_cursor->data, data,
pixels * sizeof(uint32_t));
}
@@ -114,6 +128,37 @@ virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id)
return NULL;
}
+static struct virtio_gpu_simple_resource *
+virtio_gpu_find_check_resource(VirtIOGPU *g, uint32_t resource_id,
+ bool require_backing,
+ const char *caller, uint32_t *error)
+{
+ struct virtio_gpu_simple_resource *res;
+
+ res = virtio_gpu_find_resource(g, resource_id);
+ if (!res) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid resource specified %d\n",
+ caller, resource_id);
+ if (error) {
+ *error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+ }
+ return NULL;
+ }
+
+ if (require_backing) {
+ if (!res->iov || (!res->image && !res->blob)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: no backing storage %d\n",
+ caller, resource_id);
+ if (error) {
+ *error = VIRTIO_GPU_RESP_ERR_UNSPEC;
+ }
+ return NULL;
+ }
+ }
+
+ return res;
+}
+
void virtio_gpu_ctrl_response(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd,
struct virtio_gpu_ctrl_hdr *resp,
@@ -277,6 +322,62 @@ static void virtio_gpu_resource_create_2d(VirtIOGPU *g,
g->hostmem += res->hostmem;
}
+static void virtio_gpu_resource_create_blob(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ struct virtio_gpu_simple_resource *res;
+ struct virtio_gpu_resource_create_blob cblob;
+ int ret;
+
+ VIRTIO_GPU_FILL_CMD(cblob);
+ virtio_gpu_create_blob_bswap(&cblob);
+ trace_virtio_gpu_cmd_res_create_blob(cblob.resource_id, cblob.size);
+
+ if (cblob.resource_id == 0) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: resource id 0 is not allowed\n",
+ __func__);
+ cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+ return;
+ }
+
+ res = virtio_gpu_find_resource(g, cblob.resource_id);
+ if (res) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: resource already exists %d\n",
+ __func__, cblob.resource_id);
+ cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+ return;
+ }
+
+ res = g_new0(struct virtio_gpu_simple_resource, 1);
+ res->resource_id = cblob.resource_id;
+ res->blob_size = cblob.size;
+
+ if (cblob.blob_mem != VIRTIO_GPU_BLOB_MEM_GUEST &&
+ cblob.blob_flags != VIRTIO_GPU_BLOB_FLAG_USE_SHAREABLE) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid memory type\n",
+ __func__);
+ cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+ g_free(res);
+ return;
+ }
+
+ if (res->iov) {
+ cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
+ return;
+ }
+
+ ret = virtio_gpu_create_mapping_iov(g, cblob.nr_entries, sizeof(cblob),
+ cmd, &res->addrs, &res->iov,
+ &res->iov_cnt);
+ if (ret != 0) {
+ cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
+ return;
+ }
+
+ virtio_gpu_init_udmabuf(res);
+ QTAILQ_INSERT_HEAD(&g->reslist, res, next);
+}
+
static void virtio_gpu_disable_scanout(VirtIOGPU *g, int scanout_id)
{
struct virtio_gpu_scanout *scanout = &g->parent_obj.scanout[scanout_id];
@@ -311,7 +412,7 @@ static void virtio_gpu_resource_destroy(VirtIOGPU *g,
}
}
- pixman_image_unref(res->image);
+ qemu_pixman_image_unref(res->image);
virtio_gpu_cleanup_mapping(g, res);
QTAILQ_REMOVE(&g->reslist, res, next);
g->hostmem -= res->hostmem;
@@ -352,11 +453,9 @@ static void virtio_gpu_transfer_to_host_2d(VirtIOGPU *g,
virtio_gpu_t2d_bswap(&t2d);
trace_virtio_gpu_cmd_res_xfer_toh_2d(t2d.resource_id);
- res = virtio_gpu_find_resource(g, t2d.resource_id);
- if (!res || !res->iov) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n",
- __func__, t2d.resource_id);
- cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+ res = virtio_gpu_find_check_resource(g, t2d.resource_id, true,
+ __func__, &cmd->error);
+ if (!res || res->blob) {
return;
}
@@ -402,6 +501,7 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g,
{
struct virtio_gpu_simple_resource *res;
struct virtio_gpu_resource_flush rf;
+ struct virtio_gpu_scanout *scanout;
pixman_region16_t flush_region;
int i;
@@ -410,20 +510,31 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g,
trace_virtio_gpu_cmd_res_flush(rf.resource_id,
rf.r.width, rf.r.height, rf.r.x, rf.r.y);
- res = virtio_gpu_find_resource(g, rf.resource_id);
+ res = virtio_gpu_find_check_resource(g, rf.resource_id, false,
+ __func__, &cmd->error);
if (!res) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n",
- __func__, rf.resource_id);
- cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
return;
}
- if (rf.r.x > res->width ||
+ if (res->blob) {
+ for (i = 0; i < g->parent_obj.conf.max_outputs; i++) {
+ scanout = &g->parent_obj.scanout[i];
+ if (scanout->resource_id == res->resource_id &&
+ console_has_gl(scanout->con)) {
+ dpy_gl_update(scanout->con, 0, 0, scanout->width,
+ scanout->height);
+ return;
+ }
+ }
+ }
+
+ if (!res->blob &&
+ (rf.r.x > res->width ||
rf.r.y > res->height ||
rf.r.width > res->width ||
rf.r.height > res->height ||
rf.r.x + rf.r.width > res->width ||
- rf.r.y + rf.r.height > res->height) {
+ rf.r.y + rf.r.height > res->height)) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: flush bounds outside resource"
" bounds for resource %d: %d %d %d %d vs %d %d\n",
__func__, rf.resource_id, rf.r.x, rf.r.y,
@@ -435,7 +546,6 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g,
pixman_region_init_rect(&flush_region,
rf.r.x, rf.r.y, rf.r.width, rf.r.height);
for (i = 0; i < g->parent_obj.conf.max_outputs; i++) {
- struct virtio_gpu_scanout *scanout;
pixman_region16_t region, finalregion;
pixman_box16_t *extents;
@@ -468,14 +578,115 @@ static void virtio_unref_resource(pixman_image_t *image, void *data)
pixman_image_unref(data);
}
+static void virtio_gpu_update_scanout(VirtIOGPU *g,
+ uint32_t scanout_id,
+ struct virtio_gpu_simple_resource *res,
+ struct virtio_gpu_rect *r)
+{
+ struct virtio_gpu_simple_resource *ores;
+ struct virtio_gpu_scanout *scanout;
+
+ scanout = &g->parent_obj.scanout[scanout_id];
+ ores = virtio_gpu_find_resource(g, scanout->resource_id);
+ if (ores) {
+ ores->scanout_bitmask &= ~(1 << scanout_id);
+ }
+
+ res->scanout_bitmask |= (1 << scanout_id);
+ scanout->resource_id = res->resource_id;
+ scanout->x = r->x;
+ scanout->y = r->y;
+ scanout->width = r->width;
+ scanout->height = r->height;
+}
+
+static void virtio_gpu_do_set_scanout(VirtIOGPU *g,
+ uint32_t scanout_id,
+ struct virtio_gpu_framebuffer *fb,
+ struct virtio_gpu_simple_resource *res,
+ struct virtio_gpu_rect *r,
+ uint32_t *error)
+{
+ struct virtio_gpu_scanout *scanout;
+ uint8_t *data;
+
+ if (scanout_id >= g->parent_obj.conf.max_outputs) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout id specified %d",
+ __func__, scanout_id);
+ *error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
+ return;
+ }
+ scanout = &g->parent_obj.scanout[scanout_id];
+
+ if (r->x > fb->width ||
+ r->y > fb->height ||
+ r->width < 16 ||
+ r->height < 16 ||
+ r->width > fb->width ||
+ r->height > fb->height ||
+ r->x + r->width > fb->width ||
+ r->y + r->height > fb->height) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout %d bounds for"
+ " resource %d, rect (%d,%d)+%d,%d, fb %d %d\n",
+ __func__, scanout_id, res->resource_id,
+ r->x, r->y, r->width, r->height,
+ fb->width, fb->height);
+ *error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+ return;
+ }
+
+ g->parent_obj.enable = 1;
+
+ if (res->blob) {
+ if (console_has_gl(scanout->con)) {
+ if (!virtio_gpu_update_dmabuf(g, scanout_id, res, fb)) {
+ virtio_gpu_update_scanout(g, scanout_id, res, r);
+ return;
+ }
+ }
+
+ data = res->blob;
+ } else {
+ data = (uint8_t *)pixman_image_get_data(res->image);
+ }
+
+ /* create a surface for this scanout */
+ if ((res->blob && !console_has_gl(scanout->con)) ||
+ !scanout->ds ||
+ surface_data(scanout->ds) != data + fb->offset ||
+ scanout->width != r->width ||
+ scanout->height != r->height) {
+ pixman_image_t *rect;
+ void *ptr = data + fb->offset;
+ rect = pixman_image_create_bits(fb->format, r->width, r->height,
+ ptr, fb->stride);
+
+ if (res->image) {
+ pixman_image_ref(res->image);
+ pixman_image_set_destroy_function(rect, virtio_unref_resource,
+ res->image);
+ }
+
+ /* realloc the surface ptr */
+ scanout->ds = qemu_create_displaysurface_pixman(rect);
+ if (!scanout->ds) {
+ *error = VIRTIO_GPU_RESP_ERR_UNSPEC;
+ return;
+ }
+
+ pixman_image_unref(rect);
+ dpy_gfx_replace_surface(g->parent_obj.scanout[scanout_id].con,
+ scanout->ds);
+ }
+
+ virtio_gpu_update_scanout(g, scanout_id, res, r);
+}
+
static void virtio_gpu_set_scanout(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd)
{
- struct virtio_gpu_simple_resource *res, *ores;
- struct virtio_gpu_scanout *scanout;
- pixman_format_code_t format;
- uint32_t offset;
- int bpp;
+ struct virtio_gpu_simple_resource *res;
+ struct virtio_gpu_framebuffer fb = { 0 };
struct virtio_gpu_set_scanout ss;
VIRTIO_GPU_FILL_CMD(ss);
@@ -483,86 +694,85 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g,
trace_virtio_gpu_cmd_set_scanout(ss.scanout_id, ss.resource_id,
ss.r.width, ss.r.height, ss.r.x, ss.r.y);
- if (ss.scanout_id >= g->parent_obj.conf.max_outputs) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout id specified %d",
- __func__, ss.scanout_id);
- cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID;
+ if (ss.resource_id == 0) {
+ virtio_gpu_disable_scanout(g, ss.scanout_id);
return;
}
- g->parent_obj.enable = 1;
+ res = virtio_gpu_find_check_resource(g, ss.resource_id, true,
+ __func__, &cmd->error);
+ if (!res) {
+ return;
+ }
+
+ fb.format = pixman_image_get_format(res->image);
+ fb.bytes_pp = DIV_ROUND_UP(PIXMAN_FORMAT_BPP(fb.format), 8);
+ fb.width = pixman_image_get_width(res->image);
+ fb.height = pixman_image_get_height(res->image);
+ fb.stride = pixman_image_get_stride(res->image);
+ fb.offset = ss.r.x * fb.bytes_pp + ss.r.y * fb.stride;
+
+ virtio_gpu_do_set_scanout(g, ss.scanout_id,
+ &fb, res, &ss.r, &cmd->error);
+}
+
+static void virtio_gpu_set_scanout_blob(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ struct virtio_gpu_simple_resource *res;
+ struct virtio_gpu_framebuffer fb = { 0 };
+ struct virtio_gpu_set_scanout_blob ss;
+ uint64_t fbend;
+
+ VIRTIO_GPU_FILL_CMD(ss);
+ virtio_gpu_scanout_blob_bswap(&ss);
+ trace_virtio_gpu_cmd_set_scanout_blob(ss.scanout_id, ss.resource_id,
+ ss.r.width, ss.r.height, ss.r.x,
+ ss.r.y);
+
if (ss.resource_id == 0) {
virtio_gpu_disable_scanout(g, ss.scanout_id);
return;
}
- /* create a surface for this scanout */
- res = virtio_gpu_find_resource(g, ss.resource_id);
+ res = virtio_gpu_find_check_resource(g, ss.resource_id, true,
+ __func__, &cmd->error);
if (!res) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n",
- __func__, ss.resource_id);
- cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
return;
}
- if (ss.r.x > res->width ||
- ss.r.y > res->height ||
- ss.r.width < 16 ||
- ss.r.height < 16 ||
- ss.r.width > res->width ||
- ss.r.height > res->height ||
- ss.r.x + ss.r.width > res->width ||
- ss.r.y + ss.r.height > res->height) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal scanout %d bounds for"
- " resource %d, (%d,%d)+%d,%d vs %d %d\n",
- __func__, ss.scanout_id, ss.resource_id, ss.r.x, ss.r.y,
- ss.r.width, ss.r.height, res->width, res->height);
+ fb.format = virtio_gpu_get_pixman_format(ss.format);
+ if (!fb.format) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: host couldn't handle guest format %d\n",
+ __func__, ss.format);
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
return;
}
- scanout = &g->parent_obj.scanout[ss.scanout_id];
-
- format = pixman_image_get_format(res->image);
- bpp = DIV_ROUND_UP(PIXMAN_FORMAT_BPP(format), 8);
- offset = (ss.r.x * bpp) + ss.r.y * pixman_image_get_stride(res->image);
- if (!scanout->ds || surface_data(scanout->ds)
- != ((uint8_t *)pixman_image_get_data(res->image) + offset) ||
- scanout->width != ss.r.width ||
- scanout->height != ss.r.height) {
- pixman_image_t *rect;
- void *ptr = (uint8_t *)pixman_image_get_data(res->image) + offset;
- rect = pixman_image_create_bits(format, ss.r.width, ss.r.height, ptr,
- pixman_image_get_stride(res->image));
- pixman_image_ref(res->image);
- pixman_image_set_destroy_function(rect, virtio_unref_resource,
- res->image);
- /* realloc the surface ptr */
- scanout->ds = qemu_create_displaysurface_pixman(rect);
- if (!scanout->ds) {
- cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
- return;
- }
- pixman_image_unref(rect);
- dpy_gfx_replace_surface(g->parent_obj.scanout[ss.scanout_id].con,
- scanout->ds);
- }
+ fb.bytes_pp = DIV_ROUND_UP(PIXMAN_FORMAT_BPP(fb.format), 8);
+ fb.width = ss.width;
+ fb.height = ss.height;
+ fb.stride = ss.strides[0];
+ fb.offset = ss.offsets[0] + ss.r.x * fb.bytes_pp + ss.r.y * fb.stride;
- ores = virtio_gpu_find_resource(g, scanout->resource_id);
- if (ores) {
- ores->scanout_bitmask &= ~(1 << ss.scanout_id);
+ fbend = fb.offset;
+ fbend += fb.stride * (ss.r.height - 1);
+ fbend += fb.bytes_pp * ss.r.width;
+ if (fbend > res->blob_size) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: fb end out of range\n",
+ __func__);
+ cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+ return;
}
- res->scanout_bitmask |= (1 << ss.scanout_id);
- scanout->resource_id = ss.resource_id;
- scanout->x = ss.r.x;
- scanout->y = ss.r.y;
- scanout->width = ss.r.width;
- scanout->height = ss.r.height;
+ virtio_gpu_do_set_scanout(g, ss.scanout_id,
+ &fb, res, &ss.r, &cmd->error);
}
int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
- struct virtio_gpu_resource_attach_backing *ab,
+ uint32_t nr_entries, uint32_t offset,
struct virtio_gpu_ctrl_command *cmd,
uint64_t **addr, struct iovec **iov,
uint32_t *niov)
@@ -571,17 +781,17 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
size_t esize, s;
int e, v;
- if (ab->nr_entries > 16384) {
+ if (nr_entries > 16384) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: nr_entries is too big (%d > 16384)\n",
- __func__, ab->nr_entries);
+ __func__, nr_entries);
return -1;
}
- esize = sizeof(*ents) * ab->nr_entries;
+ esize = sizeof(*ents) * nr_entries;
ents = g_malloc(esize);
s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num,
- sizeof(*ab), ents, esize);
+ offset, ents, esize);
if (s != esize) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: command data size incorrect %zu vs %zu\n",
@@ -594,7 +804,7 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
if (addr) {
*addr = NULL;
}
- for (e = 0, v = 0; e < ab->nr_entries; e++) {
+ for (e = 0, v = 0; e < nr_entries; e++) {
uint64_t a = le64_to_cpu(ents[e].addr);
uint32_t l = le32_to_cpu(ents[e].length);
hwaddr len;
@@ -606,8 +816,7 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g,
a, &len, DMA_DIRECTION_TO_DEVICE);
if (!map) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for"
- " resource %d element %d\n",
- __func__, ab->resource_id, e);
+ " element %d\n", __func__, e);
virtio_gpu_cleanup_mapping_iov(g, *iov, v);
g_free(ents);
*iov = NULL;
@@ -663,6 +872,10 @@ static void virtio_gpu_cleanup_mapping(VirtIOGPU *g,
res->iov_cnt = 0;
g_free(res->addrs);
res->addrs = NULL;
+
+ if (res->blob) {
+ virtio_gpu_fini_udmabuf(res);
+ }
}
static void
@@ -690,8 +903,8 @@ virtio_gpu_resource_attach_backing(VirtIOGPU *g,
return;
}
- ret = virtio_gpu_create_mapping_iov(g, &ab, cmd, &res->addrs,
- &res->iov, &res->iov_cnt);
+ ret = virtio_gpu_create_mapping_iov(g, ab.nr_entries, sizeof(ab), cmd,
+ &res->addrs, &res->iov, &res->iov_cnt);
if (ret != 0) {
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
return;
@@ -709,11 +922,9 @@ virtio_gpu_resource_detach_backing(VirtIOGPU *g,
virtio_gpu_bswap_32(&detach, sizeof(detach));
trace_virtio_gpu_cmd_res_back_detach(detach.resource_id);
- res = virtio_gpu_find_resource(g, detach.resource_id);
- if (!res || !res->iov) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: illegal resource specified %d\n",
- __func__, detach.resource_id);
- cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID;
+ res = virtio_gpu_find_check_resource(g, detach.resource_id, true,
+ __func__, &cmd->error);
+ if (!res) {
return;
}
virtio_gpu_cleanup_mapping(g, res);
@@ -735,6 +946,13 @@ void virtio_gpu_simple_process_cmd(VirtIOGPU *g,
case VIRTIO_GPU_CMD_RESOURCE_CREATE_2D:
virtio_gpu_resource_create_2d(g, cmd);
break;
+ case VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB:
+ if (!virtio_gpu_blob_enabled(g->parent_obj.conf)) {
+ cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+ break;
+ }
+ virtio_gpu_resource_create_blob(g, cmd);
+ break;
case VIRTIO_GPU_CMD_RESOURCE_UNREF:
virtio_gpu_resource_unref(g, cmd);
break;
@@ -747,6 +965,13 @@ void virtio_gpu_simple_process_cmd(VirtIOGPU *g,
case VIRTIO_GPU_CMD_SET_SCANOUT:
virtio_gpu_set_scanout(g, cmd);
break;
+ case VIRTIO_GPU_CMD_SET_SCANOUT_BLOB:
+ if (!virtio_gpu_blob_enabled(g->parent_obj.conf)) {
+ cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+ break;
+ }
+ virtio_gpu_set_scanout_blob(g, cmd);
+ break;
case VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING:
virtio_gpu_resource_attach_backing(g, cmd);
break;
@@ -1058,6 +1283,18 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
VirtIOGPU *g = VIRTIO_GPU(qdev);
+ if (virtio_gpu_blob_enabled(g->parent_obj.conf)) {
+ if (!virtio_gpu_have_udmabuf()) {
+ error_setg(errp, "cannot enable blob resources without udmabuf");
+ return;
+ }
+
+ if (virtio_gpu_virgl_enabled(g->parent_obj.conf)) {
+ error_setg(errp, "blobs and virgl are not compatible (yet)");
+ return;
+ }
+ }
+
if (!virtio_gpu_base_device_realize(qdev,
virtio_gpu_handle_ctrl_cb,
virtio_gpu_handle_cursor_cb,
@@ -1151,6 +1388,8 @@ static Property virtio_gpu_properties[] = {
VIRTIO_GPU_BASE_PROPERTIES(VirtIOGPU, parent_obj.conf),
DEFINE_PROP_SIZE("max_hostmem", VirtIOGPU, conf_max_hostmem,
256 * MiB),
+ DEFINE_PROP_BIT("blob", VirtIOGPU, parent_obj.conf.flags,
+ VIRTIO_GPU_FLAG_BLOB_ENABLED, false),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/dma/trace-events b/hw/dma/trace-events
index 44893995f6..3c47df54e4 100644
--- a/hw/dma/trace-events
+++ b/hw/dma/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# rc4030.c
jazzio_read(uint64_t addr, uint32_t ret) "read reg[0x%"PRIx64"] = 0x%x"
diff --git a/hw/gpio/trace-events b/hw/gpio/trace-events
index 46ab9323bd..f0b664158e 100644
--- a/hw/gpio/trace-events
+++ b/hw/gpio/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# npcm7xx_gpio.c
npcm7xx_gpio_read(const char *id, uint64_t offset, uint64_t value) " %s offset: 0x%04" PRIx64 " value 0x%08" PRIx64
diff --git a/hw/hppa/trace-events b/hw/hppa/trace-events
index 3ff620319a..3f42be9056 100644
--- a/hw/hppa/trace-events
+++ b/hw/hppa/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# pci.c
hppa_pci_iack_write(void) ""
diff --git a/hw/i2c/trace-events b/hw/i2c/trace-events
index 82f19e6a2d..7d8907c1ee 100644
--- a/hw/i2c/trace-events
+++ b/hw/i2c/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# core.c
diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
index 7f91f30877..66838fa397 100644
--- a/hw/i386/Kconfig
+++ b/hw/i386/Kconfig
@@ -23,6 +23,7 @@ config PC
imply TPM_TIS_ISA
imply VGA_PCI
imply VIRTIO_VGA
+ imply NVDIMM
select FDC
select I8259
select I8254
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 8cfaf216e7..c6d8d0d84d 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -94,7 +94,11 @@
#include "trace.h"
#include CONFIG_DEVICES
-GlobalProperty pc_compat_6_0[] = {};
+GlobalProperty pc_compat_6_0[] = {
+ { "qemu64" "-" TYPE_X86_CPU, "family", "6" },
+ { "qemu64" "-" TYPE_X86_CPU, "model", "6" },
+ { "qemu64" "-" TYPE_X86_CPU, "stepping", "3" },
+};
const size_t pc_compat_6_0_len = G_N_ELEMENTS(pc_compat_6_0);
GlobalProperty pc_compat_5_2[] = {
diff --git a/hw/i386/trace-events b/hw/i386/trace-events
index e48bef2b0d..5bf7e52bf5 100644
--- a/hw/i386/trace-events
+++ b/hw/i386/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# x86-iommu.c
x86_iommu_iec_notify(bool global, uint32_t index, uint32_t mask) "Notify IEC invalidation: global=%d index=%" PRIu32 " mask=%" PRIu32
diff --git a/hw/i386/xen/trace-events b/hw/i386/xen/trace-events
index ca3a4948ba..5d6be61090 100644
--- a/hw/i386/xen/trace-events
+++ b/hw/i386/xen/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# xen_platform.c
xen_platform_log(char *s) "xen platform: %s"
diff --git a/hw/ide/trace-events b/hw/ide/trace-events
index 6e357685f9..15d7921f15 100644
--- a/hw/ide/trace-events
+++ b/hw/ide/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# core.c
# portio
diff --git a/hw/input/hid.c b/hw/input/hid.c
index e1d2e46083..8aab0521f4 100644
--- a/hw/input/hid.c
+++ b/hw/input/hid.c
@@ -51,8 +51,8 @@ static const uint8_t hid_usage_keys[0x100] = {
0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65,
+ 0x88, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x8a, 0x00, 0x8b, 0x00, 0x89, 0xe7, 0x65,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
diff --git a/hw/input/pckbd.c b/hw/input/pckbd.c
index dde85ba6c6..baba62f357 100644
--- a/hw/input/pckbd.c
+++ b/hw/input/pckbd.c
@@ -23,13 +23,16 @@
*/
#include "qemu/osdep.h"
+#include "qemu/error-report.h"
#include "qemu/log.h"
+#include "qemu/timer.h"
#include "hw/isa/isa.h"
#include "migration/vmstate.h"
#include "hw/acpi/aml-build.h"
#include "hw/input/ps2.h"
#include "hw/irq.h"
#include "hw/input/i8042.h"
+#include "hw/qdev-properties.h"
#include "sysemu/reset.h"
#include "sysemu/runstate.h"
@@ -59,21 +62,6 @@
#define KBD_CCMD_RESET 0xFE /* Pulse bit 0 of the output port P2 = CPU reset. */
#define KBD_CCMD_NO_OP 0xFF /* Pulse no bits of the output port P2. */
-/* Keyboard Commands */
-#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
-#define KBD_CMD_ECHO 0xEE
-#define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */
-#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */
-#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */
-#define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */
-#define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */
-#define KBD_CMD_RESET 0xFF /* Reset */
-
-/* Keyboard Replies */
-#define KBD_REPLY_POR 0xAA /* Power on reset */
-#define KBD_REPLY_ACK 0xFA /* Command ACK */
-#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
-
/* Status Register Bits */
#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */
#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */
@@ -106,41 +94,37 @@
*/
#define KBD_OUT_ONES 0xcc
-/* Mouse Commands */
-#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
-#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
-#define AUX_SET_RES 0xE8 /* Set resolution */
-#define AUX_GET_SCALE 0xE9 /* Get scaling factor */
-#define AUX_SET_STREAM 0xEA /* Set stream mode */
-#define AUX_POLL 0xEB /* Poll */
-#define AUX_RESET_WRAP 0xEC /* Reset wrap mode */
-#define AUX_SET_WRAP 0xEE /* Set wrap mode */
-#define AUX_SET_REMOTE 0xF0 /* Set remote mode */
-#define AUX_GET_TYPE 0xF2 /* Get type */
-#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */
-#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
-#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
-#define AUX_SET_DEFAULT 0xF6
-#define AUX_RESET 0xFF /* Reset aux device */
-#define AUX_ACK 0xFA /* Command byte ACK. */
-
-#define MOUSE_STATUS_REMOTE 0x40
-#define MOUSE_STATUS_ENABLED 0x20
-#define MOUSE_STATUS_SCALE21 0x10
-
-#define KBD_PENDING_KBD 1
-#define KBD_PENDING_AUX 2
+#define KBD_PENDING_KBD_COMPAT 0x01
+#define KBD_PENDING_AUX_COMPAT 0x02
+#define KBD_PENDING_CTRL_KBD 0x04
+#define KBD_PENDING_CTRL_AUX 0x08
+#define KBD_PENDING_KBD KBD_MODE_DISABLE_KBD /* 0x10 */
+#define KBD_PENDING_AUX KBD_MODE_DISABLE_MOUSE /* 0x20 */
+
+#define KBD_MIGR_TIMER_PENDING 0x1
+
+#define KBD_OBSRC_KBD 0x01
+#define KBD_OBSRC_MOUSE 0x02
+#define KBD_OBSRC_CTRL 0x04
typedef struct KBDState {
uint8_t write_cmd; /* if non zero, write data to port 60 is expected */
uint8_t status;
uint8_t mode;
uint8_t outport;
+ uint32_t migration_flags;
+ uint32_t obsrc;
bool outport_present;
+ bool extended_state;
+ bool extended_state_loaded;
/* Bitmask of devices with data available. */
uint8_t pending;
+ uint8_t obdata;
+ uint8_t cbdata;
+ uint8_t pending_tmp;
void *kbd;
void *mouse;
+ QEMUTimer *throttle_timer;
qemu_irq irq_kbd;
qemu_irq irq_mouse;
@@ -148,56 +132,123 @@ typedef struct KBDState {
hwaddr mask;
} KBDState;
-/* update irq and KBD_STAT_[MOUSE_]OBF */
/* XXX: not generating the irqs if KBD_MODE_DISABLE_KBD is set may be
incorrect, but it avoids having to simulate exact delays */
-static void kbd_update_irq(KBDState *s)
+static void kbd_update_irq_lines(KBDState *s)
{
int irq_kbd_level, irq_mouse_level;
irq_kbd_level = 0;
irq_mouse_level = 0;
+
+ if (s->status & KBD_STAT_OBF) {
+ if (s->status & KBD_STAT_MOUSE_OBF) {
+ if (s->mode & KBD_MODE_MOUSE_INT) {
+ irq_mouse_level = 1;
+ }
+ } else {
+ if ((s->mode & KBD_MODE_KBD_INT) &&
+ !(s->mode & KBD_MODE_DISABLE_KBD)) {
+ irq_kbd_level = 1;
+ }
+ }
+ }
+ qemu_set_irq(s->irq_kbd, irq_kbd_level);
+ qemu_set_irq(s->irq_mouse, irq_mouse_level);
+}
+
+static void kbd_deassert_irq(KBDState *s)
+{
+ s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF);
+ s->outport &= ~(KBD_OUT_OBF | KBD_OUT_MOUSE_OBF);
+ kbd_update_irq_lines(s);
+}
+
+static uint8_t kbd_pending(KBDState *s)
+{
+ if (s->extended_state) {
+ return s->pending & (~s->mode | ~(KBD_PENDING_KBD | KBD_PENDING_AUX));
+ } else {
+ return s->pending;
+ }
+}
+
+/* update irq and KBD_STAT_[MOUSE_]OBF */
+static void kbd_update_irq(KBDState *s)
+{
+ uint8_t pending = kbd_pending(s);
+
s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF);
s->outport &= ~(KBD_OUT_OBF | KBD_OUT_MOUSE_OBF);
- if (s->pending) {
+ if (pending) {
s->status |= KBD_STAT_OBF;
s->outport |= KBD_OUT_OBF;
- /* kbd data takes priority over aux data. */
- if (s->pending == KBD_PENDING_AUX) {
+ if (pending & KBD_PENDING_CTRL_KBD) {
+ s->obsrc = KBD_OBSRC_CTRL;
+ } else if (pending & KBD_PENDING_CTRL_AUX) {
s->status |= KBD_STAT_MOUSE_OBF;
s->outport |= KBD_OUT_MOUSE_OBF;
- if (s->mode & KBD_MODE_MOUSE_INT)
- irq_mouse_level = 1;
+ s->obsrc = KBD_OBSRC_CTRL;
+ } else if (pending & KBD_PENDING_KBD) {
+ s->obsrc = KBD_OBSRC_KBD;
} else {
- if ((s->mode & KBD_MODE_KBD_INT) &&
- !(s->mode & KBD_MODE_DISABLE_KBD))
- irq_kbd_level = 1;
+ s->status |= KBD_STAT_MOUSE_OBF;
+ s->outport |= KBD_OUT_MOUSE_OBF;
+ s->obsrc = KBD_OBSRC_MOUSE;
}
}
- qemu_set_irq(s->irq_kbd, irq_kbd_level);
- qemu_set_irq(s->irq_mouse, irq_mouse_level);
+ kbd_update_irq_lines(s);
+}
+
+static void kbd_safe_update_irq(KBDState *s)
+{
+ /*
+ * with KBD_STAT_OBF set, a call to kbd_read_data() will eventually call
+ * kbd_update_irq()
+ */
+ if (s->status & KBD_STAT_OBF) {
+ return;
+ }
+ /* the throttle timer is pending and will call kbd_update_irq() */
+ if (s->throttle_timer && timer_pending(s->throttle_timer)) {
+ return;
+ }
+ if (kbd_pending(s)) {
+ kbd_update_irq(s);
+ }
}
static void kbd_update_kbd_irq(void *opaque, int level)
{
- KBDState *s = (KBDState *)opaque;
+ KBDState *s = opaque;
- if (level)
+ if (level) {
s->pending |= KBD_PENDING_KBD;
- else
+ } else {
s->pending &= ~KBD_PENDING_KBD;
- kbd_update_irq(s);
+ }
+ kbd_safe_update_irq(s);
}
static void kbd_update_aux_irq(void *opaque, int level)
{
- KBDState *s = (KBDState *)opaque;
+ KBDState *s = opaque;
- if (level)
+ if (level) {
s->pending |= KBD_PENDING_AUX;
- else
+ } else {
s->pending &= ~KBD_PENDING_AUX;
- kbd_update_irq(s);
+ }
+ kbd_safe_update_irq(s);
+}
+
+static void kbd_throttle_timeout(void *opaque)
+{
+ KBDState *s = opaque;
+
+ if (kbd_pending(s)) {
+ kbd_update_irq(s);
+ }
}
static uint64_t kbd_read_status(void *opaque, hwaddr addr,
@@ -212,10 +263,25 @@ static uint64_t kbd_read_status(void *opaque, hwaddr addr,
static void kbd_queue(KBDState *s, int b, int aux)
{
- if (aux)
- ps2_queue(s->mouse, b);
- else
- ps2_queue(s->kbd, b);
+ if (s->extended_state) {
+ s->cbdata = b;
+ s->pending &= ~KBD_PENDING_CTRL_KBD & ~KBD_PENDING_CTRL_AUX;
+ s->pending |= aux ? KBD_PENDING_CTRL_AUX : KBD_PENDING_CTRL_KBD;
+ kbd_safe_update_irq(s);
+ } else {
+ ps2_queue(aux ? s->mouse : s->kbd, b);
+ }
+}
+
+static uint8_t kbd_dequeue(KBDState *s)
+{
+ uint8_t b = s->cbdata;
+
+ s->pending &= ~KBD_PENDING_CTRL_KBD & ~KBD_PENDING_CTRL_AUX;
+ if (kbd_pending(s)) {
+ kbd_update_irq(s);
+ }
+ return b;
}
static void outport_write(KBDState *s, uint32_t val)
@@ -265,6 +331,7 @@ static void kbd_write_command(void *opaque, hwaddr addr,
break;
case KBD_CCMD_MOUSE_ENABLE:
s->mode &= ~KBD_MODE_DISABLE_MOUSE;
+ kbd_safe_update_irq(s);
break;
case KBD_CCMD_TEST_MOUSE:
kbd_queue(s, 0x00, 0);
@@ -278,11 +345,10 @@ static void kbd_write_command(void *opaque, hwaddr addr,
break;
case KBD_CCMD_KBD_DISABLE:
s->mode |= KBD_MODE_DISABLE_KBD;
- kbd_update_irq(s);
break;
case KBD_CCMD_KBD_ENABLE:
s->mode &= ~KBD_MODE_DISABLE_KBD;
- kbd_update_irq(s);
+ kbd_safe_update_irq(s);
break;
case KBD_CCMD_READ_INPORT:
kbd_queue(s, 0x80, 0);
@@ -315,15 +381,24 @@ static uint64_t kbd_read_data(void *opaque, hwaddr addr,
unsigned size)
{
KBDState *s = opaque;
- uint32_t val;
- if (s->pending == KBD_PENDING_AUX)
- val = ps2_read_data(s->mouse);
- else
- val = ps2_read_data(s->kbd);
+ if (s->status & KBD_STAT_OBF) {
+ kbd_deassert_irq(s);
+ if (s->obsrc & KBD_OBSRC_KBD) {
+ if (s->throttle_timer) {
+ timer_mod(s->throttle_timer,
+ qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + 1000);
+ }
+ s->obdata = ps2_read_data(s->kbd);
+ } else if (s->obsrc & KBD_OBSRC_MOUSE) {
+ s->obdata = ps2_read_data(s->mouse);
+ } else if (s->obsrc & KBD_OBSRC_CTRL) {
+ s->obdata = kbd_dequeue(s);
+ }
+ }
- trace_pckbd_kbd_read_data(val);
- return val;
+ trace_pckbd_kbd_read_data(s->obdata);
+ return s->obdata;
}
static void kbd_write_data(void *opaque, hwaddr addr,
@@ -336,12 +411,23 @@ static void kbd_write_data(void *opaque, hwaddr addr,
switch(s->write_cmd) {
case 0:
ps2_write_keyboard(s->kbd, val);
+ /* sending data to the keyboard reenables PS/2 communication */
+ s->mode &= ~KBD_MODE_DISABLE_KBD;
+ kbd_safe_update_irq(s);
break;
case KBD_CCMD_WRITE_MODE:
s->mode = val;
ps2_keyboard_set_translation(s->kbd, (s->mode & KBD_MODE_KCC) != 0);
- /* ??? */
- kbd_update_irq(s);
+ /*
+ * a write to the mode byte interrupt enable flags directly updates
+ * the irq lines
+ */
+ kbd_update_irq_lines(s);
+ /*
+ * a write to the mode byte disable interface flags may raise
+ * an irq if there is pending data in the PS/2 queues.
+ */
+ kbd_safe_update_irq(s);
break;
case KBD_CCMD_WRITE_OBUF:
kbd_queue(s, val, 0);
@@ -354,6 +440,9 @@ static void kbd_write_data(void *opaque, hwaddr addr,
break;
case KBD_CCMD_WRITE_MOUSE:
ps2_write_mouse(s->mouse, val);
+ /* sending data to the mouse reenables PS/2 communication */
+ s->mode &= ~KBD_MODE_DISABLE_MOUSE;
+ kbd_safe_update_irq(s);
break;
default:
break;
@@ -368,7 +457,11 @@ static void kbd_reset(void *opaque)
s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT;
s->status = KBD_STAT_CMD | KBD_STAT_UNLOCKED;
s->outport = KBD_OUT_RESET | KBD_OUT_A20 | KBD_OUT_ONES;
- s->outport_present = false;
+ s->pending = 0;
+ kbd_deassert_irq(s);
+ if (s->throttle_timer) {
+ timer_del(s->throttle_timer);
+ }
}
static uint8_t kbd_outport_default(KBDState *s)
@@ -403,13 +496,99 @@ static const VMStateDescription vmstate_kbd_outport = {
}
};
+static int kbd_extended_state_pre_save(void *opaque)
+{
+ KBDState *s = opaque;
+
+ s->migration_flags = 0;
+ if (s->throttle_timer && timer_pending(s->throttle_timer)) {
+ s->migration_flags |= KBD_MIGR_TIMER_PENDING;
+ }
+
+ return 0;
+}
+
+static int kbd_extended_state_post_load(void *opaque, int version_id)
+{
+ KBDState *s = opaque;
+
+ if (s->migration_flags & KBD_MIGR_TIMER_PENDING) {
+ kbd_throttle_timeout(s);
+ }
+ s->extended_state_loaded = true;
+
+ return 0;
+}
+
+static bool kbd_extended_state_needed(void *opaque)
+{
+ KBDState *s = opaque;
+
+ return s->extended_state;
+}
+
+static const VMStateDescription vmstate_kbd_extended_state = {
+ .name = "pckbd/extended_state",
+ .post_load = kbd_extended_state_post_load,
+ .pre_save = kbd_extended_state_pre_save,
+ .needed = kbd_extended_state_needed,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(migration_flags, KBDState),
+ VMSTATE_UINT32(obsrc, KBDState),
+ VMSTATE_UINT8(obdata, KBDState),
+ VMSTATE_UINT8(cbdata, KBDState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static int kbd_pre_save(void *opaque)
+{
+ KBDState *s = opaque;
+
+ if (s->extended_state) {
+ s->pending_tmp = s->pending;
+ } else {
+ s->pending_tmp = 0;
+ if (s->pending & KBD_PENDING_KBD) {
+ s->pending_tmp |= KBD_PENDING_KBD_COMPAT;
+ }
+ if (s->pending & KBD_PENDING_AUX) {
+ s->pending_tmp |= KBD_PENDING_AUX_COMPAT;
+ }
+ }
+ return 0;
+}
+
+static int kbd_pre_load(void *opaque)
+{
+ KBDState *s = opaque;
+
+ s->outport_present = false;
+ s->extended_state_loaded = false;
+ return 0;
+}
+
static int kbd_post_load(void *opaque, int version_id)
{
KBDState *s = opaque;
if (!s->outport_present) {
s->outport = kbd_outport_default(s);
}
- s->outport_present = false;
+ s->pending = s->pending_tmp;
+ if (!s->extended_state_loaded) {
+ s->obsrc = s->status & KBD_STAT_OBF ?
+ (s->status & KBD_STAT_MOUSE_OBF ? KBD_OBSRC_MOUSE : KBD_OBSRC_KBD) :
+ 0;
+ if (s->pending & KBD_PENDING_KBD_COMPAT) {
+ s->pending |= KBD_PENDING_KBD;
+ }
+ if (s->pending & KBD_PENDING_AUX_COMPAT) {
+ s->pending |= KBD_PENDING_AUX;
+ }
+ }
+ /* clear all unused flags */
+ s->pending &= KBD_PENDING_CTRL_KBD | KBD_PENDING_CTRL_AUX |
+ KBD_PENDING_KBD | KBD_PENDING_AUX;
return 0;
}
@@ -417,16 +596,19 @@ static const VMStateDescription vmstate_kbd = {
.name = "pckbd",
.version_id = 3,
.minimum_version_id = 3,
+ .pre_load = kbd_pre_load,
.post_load = kbd_post_load,
+ .pre_save = kbd_pre_save,
.fields = (VMStateField[]) {
VMSTATE_UINT8(write_cmd, KBDState),
VMSTATE_UINT8(status, KBDState),
VMSTATE_UINT8(mode, KBDState),
- VMSTATE_UINT8(pending, KBDState),
+ VMSTATE_UINT8(pending_tmp, KBDState),
VMSTATE_END_OF_LIST()
},
.subsections = (const VMStateDescription*[]) {
&vmstate_kbd_outport,
+ &vmstate_kbd_extended_state,
NULL
}
};
@@ -472,6 +654,8 @@ void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq,
s->irq_mouse = mouse_irq;
s->mask = mask;
+ s->extended_state = true;
+
vmstate_register(NULL, 0, &vmstate_kbd, s);
memory_region_init_io(region, NULL, &i8042_mmio_ops, s, "i8042", size);
@@ -485,6 +669,7 @@ struct ISAKBDState {
ISADevice parent_obj;
KBDState kbd;
+ bool kbd_throttle;
MemoryRegion io[2];
};
@@ -557,6 +742,13 @@ static void i8042_realizefn(DeviceState *dev, Error **errp)
s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s);
s->mouse = ps2_mouse_init(kbd_update_aux_irq, s);
+ if (isa_s->kbd_throttle && !isa_s->kbd.extended_state) {
+ warn_report(TYPE_I8042 ": can't enable kbd-throttle without"
+ " extended-state, disabling kbd-throttle");
+ } else if (isa_s->kbd_throttle) {
+ s->throttle_timer = timer_new_us(QEMU_CLOCK_VIRTUAL,
+ kbd_throttle_timeout, s);
+ }
qemu_register_reset(kbd_reset, s);
}
@@ -588,11 +780,18 @@ static void i8042_build_aml(ISADevice *isadev, Aml *scope)
aml_append(scope, mou);
}
+static Property i8042_properties[] = {
+ DEFINE_PROP_BOOL("extended-state", ISAKBDState, kbd.extended_state, true),
+ DEFINE_PROP_BOOL("kbd-throttle", ISAKBDState, kbd_throttle, false),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
static void i8042_class_initfn(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
ISADeviceClass *isa = ISA_DEVICE_CLASS(klass);
+ device_class_set_props(dc, i8042_properties);
dc->realize = i8042_realizefn;
dc->vmsd = &vmstate_kbd_isa;
isa->build_aml = i8042_build_aml;
diff --git a/hw/input/ps2.c b/hw/input/ps2.c
index 72cdb80ae1..8dd482c1f6 100644
--- a/hw/input/ps2.c
+++ b/hw/input/ps2.c
@@ -212,8 +212,12 @@ void ps2_raise_irq(PS2State *s)
void ps2_queue(PS2State *s, int b)
{
+ if (PS2_QUEUE_SIZE - s->queue.count < 1) {
+ return;
+ }
+
ps2_queue_noirq(s, b);
- s->update_irq(s->update_arg, 1);
+ ps2_raise_irq(s);
}
void ps2_queue_2(PS2State *s, int b1, int b2)
@@ -224,7 +228,7 @@ void ps2_queue_2(PS2State *s, int b1, int b2)
ps2_queue_noirq(s, b1);
ps2_queue_noirq(s, b2);
- s->update_irq(s->update_arg, 1);
+ ps2_raise_irq(s);
}
void ps2_queue_3(PS2State *s, int b1, int b2, int b3)
@@ -236,7 +240,7 @@ void ps2_queue_3(PS2State *s, int b1, int b2, int b3)
ps2_queue_noirq(s, b1);
ps2_queue_noirq(s, b2);
ps2_queue_noirq(s, b3);
- s->update_irq(s->update_arg, 1);
+ ps2_raise_irq(s);
}
void ps2_queue_4(PS2State *s, int b1, int b2, int b3, int b4)
@@ -249,7 +253,7 @@ void ps2_queue_4(PS2State *s, int b1, int b2, int b3, int b4)
ps2_queue_noirq(s, b2);
ps2_queue_noirq(s, b3);
ps2_queue_noirq(s, b4);
- s->update_irq(s->update_arg, 1);
+ ps2_raise_irq(s);
}
/* keycode is the untranslated scancode in the current scancode set. */
@@ -293,7 +297,8 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
qcode = qemu_input_key_value_to_qcode(key->key);
mod = ps2_modifier_bit(qcode);
- trace_ps2_keyboard_event(s, qcode, key->down, mod, s->modifiers);
+ trace_ps2_keyboard_event(s, qcode, key->down, mod,
+ s->modifiers, s->scancode_set, s->translate);
if (key->down) {
s->modifiers |= mod;
} else {
@@ -515,7 +520,9 @@ uint32_t ps2_read_data(PS2State *s)
/* reading deasserts IRQ */
s->update_irq(s->update_arg, 0);
/* reassert IRQs if data left */
- s->update_irq(s->update_arg, q->count != 0);
+ if (q->count) {
+ s->update_irq(s->update_arg, 1);
+ }
}
return val;
}
@@ -645,7 +652,8 @@ void ps2_keyboard_set_translation(void *opaque, int mode)
static int ps2_mouse_send_packet(PS2MouseState *s)
{
- const int needed = 3 + (s->mouse_type - 2);
+ /* IMPS/2 and IMEX send 4 bytes, PS2 sends 3 bytes */
+ const int needed = s->mouse_type ? 4 : 3;
unsigned int b;
int dx1, dy1, dz1;
diff --git a/hw/input/trace-events b/hw/input/trace-events
index 33741e74f5..e0bfe7f3ee 100644
--- a/hw/input/trace-events
+++ b/hw/input/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# adb-kbd.c
adb_device_kbd_no_key(void) "Ignoring NO_KEY"
@@ -30,7 +30,7 @@ pckbd_kbd_write_data(uint64_t val) "0x%02"PRIx64
# ps2.c
ps2_put_keycode(void *opaque, int keycode) "%p keycode 0x%02x"
-ps2_keyboard_event(void *opaque, int qcode, int down, unsigned int modifier, unsigned int modifiers) "%p qcode %d down %d modifier 0x%x modifiers 0x%x"
+ps2_keyboard_event(void *opaque, int qcode, int down, unsigned int modifier, unsigned int modifiers, int set, int xlate) "%p qcode %d down %d modifier 0x%x modifiers 0x%x set %d xlate %d"
ps2_read_data(void *opaque) "%p"
ps2_set_ledstate(void *s, int ledstate) "%p ledstate %d"
ps2_reset_keyboard(void *s) "%p"
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 626bb554b2..e56e7dd3b6 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# i8259.c
pic_update_irq(bool master, uint8_t imr, uint8_t irr, uint8_t padd) "master %d imr %"PRIu8" irr %"PRIu8" padd %"PRIu8
diff --git a/hw/isa/trace-events b/hw/isa/trace-events
index 641d69eedf..b8f877e1ed 100644
--- a/hw/isa/trace-events
+++ b/hw/isa/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# isa-superio.c
superio_create_parallel(int id, uint16_t base, unsigned int irq) "id=%d, base 0x%03x, irq %u"
diff --git a/hw/mem/Kconfig b/hw/mem/Kconfig
index a0ef2cf648..8b19fdc49f 100644
--- a/hw/mem/Kconfig
+++ b/hw/mem/Kconfig
@@ -7,6 +7,4 @@ config MEM_DEVICE
config NVDIMM
bool
- default y
- depends on (PC || PSERIES || ARM_VIRT)
select MEM_DEVICE
diff --git a/hw/mem/trace-events b/hw/mem/trace-events
index 9f6b52acd7..8b6b02b5bf 100644
--- a/hw/mem/trace-events
+++ b/hw/mem/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# pc-dimm.c
mhp_pc_dimm_assigned_slot(int slot) "%d"
diff --git a/hw/mips/jazz.c b/hw/mips/jazz.c
index dba2088ed1..1e1cf8154e 100644
--- a/hw/mips/jazz.c
+++ b/hw/mips/jazz.c
@@ -119,30 +119,6 @@ static const MemoryRegionOps dma_dummy_ops = {
#define MAGNUM_BIOS_SIZE \
(BIOS_SIZE < MAGNUM_BIOS_SIZE_MAX ? BIOS_SIZE : MAGNUM_BIOS_SIZE_MAX)
-#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY)
-static void (*real_do_transaction_failed)(CPUState *cpu, hwaddr physaddr,
- vaddr addr, unsigned size,
- MMUAccessType access_type,
- int mmu_idx, MemTxAttrs attrs,
- MemTxResult response,
- uintptr_t retaddr);
-
-static void mips_jazz_do_transaction_failed(CPUState *cs, hwaddr physaddr,
- vaddr addr, unsigned size,
- MMUAccessType access_type,
- int mmu_idx, MemTxAttrs attrs,
- MemTxResult response,
- uintptr_t retaddr)
-{
- if (access_type != MMU_INST_FETCH) {
- /* ignore invalid access (ie do not raise exception) */
- return;
- }
- (*real_do_transaction_failed)(cs, physaddr, addr, size, access_type,
- mmu_idx, attrs, response, retaddr);
-}
-#endif /* CONFIG_TCG && !CONFIG_USER_ONLY */
-
static void mips_jazz_init(MachineState *machine,
enum jazz_model_e jazz_model)
{
@@ -151,7 +127,7 @@ static void mips_jazz_init(MachineState *machine,
int bios_size, n;
Clock *cpuclk;
MIPSCPU *cpu;
- CPUClass *cc;
+ MIPSCPUClass *mcc;
CPUMIPSState *env;
qemu_irq *i8259;
rc4030_dma *dmas;
@@ -198,8 +174,6 @@ static void mips_jazz_init(MachineState *machine,
* However, we can't simply add a global memory region to catch
* everything, as this would make all accesses including instruction
* accesses be ignored and not raise exceptions.
- * So instead we hijack the do_transaction_failed method on the CPU, and
- * do not raise exceptions for data access.
*
* NOTE: this behaviour of raising exceptions for bad instruction
* fetches but not bad data accesses was added in commit 54e755588cf1e9
@@ -209,11 +183,8 @@ static void mips_jazz_init(MachineState *machine,
* we could replace this hijacking of CPU methods with a simple global
* memory region that catches all memory accesses, as we do on Malta.
*/
- cc = CPU_GET_CLASS(cpu);
-#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY)
- real_do_transaction_failed = cc->tcg_ops->do_transaction_failed;
- cc->tcg_ops->do_transaction_failed = mips_jazz_do_transaction_failed;
-#endif /* CONFIG_TCG && !CONFIG_USER_ONLY */
+ mcc = MIPS_CPU_GET_CLASS(cpu);
+ mcc->no_data_aborts = true;
/* allocate RAM */
memory_region_add_subregion(address_space, 0, machine->ram);
diff --git a/hw/misc/macio/trace-events b/hw/misc/macio/trace-events
index e4a1cc0d24..ad4b9d1c08 100644
--- a/hw/misc/macio/trace-events
+++ b/hw/misc/macio/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# cuda.c
cuda_delay_set_sr_int(void) ""
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
index a1ee67dc9a..0b61070c52 100644
--- a/hw/misc/npcm7xx_clk.c
+++ b/hw/misc/npcm7xx_clk.c
@@ -35,7 +35,7 @@
#define NPCM7XX_CLOCK_REF_HZ (25000000)
/* Register Field Definitions */
-#define NPCM7XX_CLK_WDRCR_CA9C BIT(0) /* Cortex A9 Cores */
+#define NPCM7XX_CLK_WDRCR_CA9C BIT(0) /* Cortex-A9 Cores */
#define PLLCON_LOKI BIT(31)
#define PLLCON_LOKS BIT(30)
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index 0752217636..ede413965b 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# allwinner-cpucfg.c
allwinner_cpucfg_cpu_reset(uint8_t cpu_id, uint32_t reset_addr) "id %u, reset_addr 0x%" PRIu32
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index f03450c028..9c7035bc94 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -283,9 +283,8 @@ static uint32_t imx_phy_read(IMXFECState *s, int reg)
uint32_t phy = reg / 32;
if (phy != s->phy_num) {
- qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad phy num %u\n",
- TYPE_IMX_FEC, __func__, phy);
- return 0;
+ trace_imx_phy_read_num(phy, s->phy_num);
+ return 0xffff;
}
reg %= 32;
@@ -345,8 +344,7 @@ static void imx_phy_write(IMXFECState *s, int reg, uint32_t val)
uint32_t phy = reg / 32;
if (phy != s->phy_num) {
- qemu_log_mask(LOG_GUEST_ERROR, "[%s.phy]%s: Bad phy num %u\n",
- TYPE_IMX_FEC, __func__, phy);
+ trace_imx_phy_write_num(phy, s->phy_num);
return;
}
diff --git a/hw/net/trace-events b/hw/net/trace-events
index 314e21fa99..c28b91ee1a 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# allwinner-sun8i-emac.c
allwinner_sun8i_emac_mii_write_reg(uint32_t reg, uint32_t value) "MII write: reg=0x%" PRIx32 " value=0x%" PRIx32
@@ -402,7 +402,9 @@ i82596_channel_attention(void *s) "%p: Received CHANNEL ATTENTION"
# imx_fec.c
imx_phy_read(uint32_t val, int phy, int reg) "0x%04"PRIx32" <= phy[%d].reg[%d]"
+imx_phy_read_num(int phy, int configured) "read request from unconfigured phy %d (configured %d)"
imx_phy_write(uint32_t val, int phy, int reg) "0x%04"PRIx32" => phy[%d].reg[%d]"
+imx_phy_write_num(int phy, int configured) "write request to unconfigured phy %d (configured %d)"
imx_phy_update_link(const char *s) "%s"
imx_phy_reset(void) ""
imx_fec_read_bd(uint64_t addr, int flags, int len, int data) "tx_bd 0x%"PRIx64" flags 0x%04x len %d data 0x%08x"
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 613be072c3..bd7958b9f0 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -3481,6 +3481,7 @@ static void virtio_net_device_unrealize(DeviceState *dev)
if (n->failover) {
device_listener_unregister(&n->primary_listener);
+ remove_migration_state_change_notifier(&n->migration_state);
}
max_queues = n->multiqueue ? n->max_queues : 1;
diff --git a/hw/nvram/trace-events b/hw/nvram/trace-events
index e023193295..5e33b24d47 100644
--- a/hw/nvram/trace-events
+++ b/hw/nvram/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# ds1225y.c
nvram_read(uint32_t addr, uint32_t ret) "read addr %d: 0x%02x"
diff --git a/hw/pci-host/trace-events b/hw/pci-host/trace-events
index dac86ad3f0..f4b3a50cb0 100644
--- a/hw/pci-host/trace-events
+++ b/hw/pci-host/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# grackle.c
grackle_set_irq(int irq_num, int level) "set_irq num %d level %d"
diff --git a/hw/pci/trace-events b/hw/pci/trace-events
index def4b3926d..fc777d0b5e 100644
--- a/hw/pci/trace-events
+++ b/hw/pci/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# pci.c
pci_update_mappings_del(void *d, uint32_t bus, uint32_t slot, uint32_t func, int bar, uint64_t addr, uint64_t size) "d=%p %02x:%02x.%x %d,0x%"PRIx64"+0x%"PRIx64
diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig
index e51e0e5e5a..66e0b15d9e 100644
--- a/hw/ppc/Kconfig
+++ b/hw/ppc/Kconfig
@@ -3,6 +3,7 @@ config PSERIES
imply PCI_DEVICES
imply TEST_DEVICES
imply VIRTIO_VGA
+ imply NVDIMM
select DIMM
select PCI
select SPAPR_VSCSI
diff --git a/hw/ppc/pef.c b/hw/ppc/pef.c
index 573be3ed79..cc44d5e339 100644
--- a/hw/ppc/pef.c
+++ b/hw/ppc/pef.c
@@ -41,7 +41,7 @@ struct PefGuest {
ConfidentialGuestSupport parent_obj;
};
-static int kvmppc_svm_init(Error **errp)
+static int kvmppc_svm_init(ConfidentialGuestSupport *cgs, Error **errp)
{
#ifdef CONFIG_KVM
static Error *pef_mig_blocker;
@@ -65,6 +65,8 @@ static int kvmppc_svm_init(Error **errp)
/* NB: This can fail if --only-migratable is used */
migrate_add_blocker(pef_mig_blocker, &error_fatal);
+ cgs->ready = true;
+
return 0;
#else
g_assert_not_reached();
@@ -102,7 +104,7 @@ int pef_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
return -1;
}
- return kvmppc_svm_init(errp);
+ return kvmppc_svm_init(cgs, errp);
}
int pef_kvm_reset(ConfidentialGuestSupport *cgs, Error **errp)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index c23bcc4490..4dd90b75cc 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1005,7 +1005,7 @@ static void spapr_dt_chosen(SpaprMachineState *spapr, void *fdt, bool reset)
_FDT(chosen = fdt_add_subnode(fdt, 0, "chosen"));
if (reset) {
- const char *boot_device = machine->boot_order;
+ const char *boot_device = spapr->boot_device;
char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus);
size_t cb = 0;
char *bootlist = get_boot_devices_list(&cb);
@@ -2376,8 +2376,10 @@ static SaveVMHandlers savevm_htab_handlers = {
static void spapr_boot_set(void *opaque, const char *boot_device,
Error **errp)
{
- MachineState *machine = MACHINE(opaque);
- machine->boot_order = g_strdup(boot_device);
+ SpaprMachineState *spapr = SPAPR_MACHINE(opaque);
+
+ g_free(spapr->boot_device);
+ spapr->boot_device = g_strdup(boot_device);
}
static void spapr_create_lmb_dr_connectors(SpaprMachineState *spapr)
diff --git a/hw/ppc/spapr_nvdimm.c b/hw/ppc/spapr_nvdimm.c
index 252204e25f..91de1052f2 100644
--- a/hw/ppc/spapr_nvdimm.c
+++ b/hw/ppc/spapr_nvdimm.c
@@ -35,6 +35,18 @@
/* SCM device is unable to persist memory contents */
#define PAPR_PMEM_UNARMED PPC_BIT(0)
+/*
+ * The nvdimm size should be aligned to SCM block size.
+ * The SCM block size should be aligned to SPAPR_MEMORY_BLOCK_SIZE
+ * in order to have SCM regions not to overlap with dimm memory regions.
+ * The SCM devices can have variable block sizes. For now, fixing the
+ * block size to the minimum value.
+ */
+#define SPAPR_MINIMUM_SCM_BLOCK_SIZE SPAPR_MEMORY_BLOCK_SIZE
+
+/* Have an explicit check for alignment */
+QEMU_BUILD_BUG_ON(SPAPR_MINIMUM_SCM_BLOCK_SIZE % SPAPR_MEMORY_BLOCK_SIZE);
+
bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm,
uint64_t size, Error **errp)
{
@@ -163,11 +175,11 @@ int spapr_pmem_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr,
void spapr_dt_persistent_memory(SpaprMachineState *spapr, void *fdt)
{
- int offset = fdt_subnode_offset(fdt, 0, "persistent-memory");
+ int offset = fdt_subnode_offset(fdt, 0, "ibm,persistent-memory");
GSList *iter, *nvdimms = nvdimm_get_device_list();
if (offset < 0) {
- offset = fdt_add_subnode(fdt, 0, "persistent-memory");
+ offset = fdt_add_subnode(fdt, 0, "ibm,persistent-memory");
_FDT(offset);
_FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 0x1)));
_FDT((fdt_setprop_cell(fdt, offset, "#size-cells", 0x0)));
diff --git a/hw/ppc/spapr_pci_vfio.c b/hw/ppc/spapr_pci_vfio.c
index 7817cf72ee..f3b37df8ea 100644
--- a/hw/ppc/spapr_pci_vfio.c
+++ b/hw/ppc/spapr_pci_vfio.c
@@ -46,6 +46,16 @@ void spapr_phb_vfio_reset(DeviceState *qdev)
spapr_phb_vfio_eeh_reenable(SPAPR_PCI_HOST_BRIDGE(qdev));
}
+static void spapr_eeh_pci_find_device(PCIBus *bus, PCIDevice *pdev,
+ void *opaque)
+{
+ bool *found = opaque;
+
+ if (object_dynamic_cast(OBJECT(pdev), "vfio-pci")) {
+ *found = true;
+ }
+}
+
int spapr_phb_vfio_eeh_set_option(SpaprPhbState *sphb,
unsigned int addr, int option)
{
@@ -58,17 +68,33 @@ int spapr_phb_vfio_eeh_set_option(SpaprPhbState *sphb,
break;
case RTAS_EEH_ENABLE: {
PCIHostState *phb;
- PCIDevice *pdev;
+ bool found = false;
/*
- * The EEH functionality is enabled on basis of PCI device,
- * instead of PE. We need check the validity of the PCI
- * device address.
+ * The EEH functionality is enabled per sphb level instead of
+ * per PCI device. We have already identified this specific sphb
+ * based on buid passed as argument to ibm,set-eeh-option rtas
+ * call. Now we just need to check the validity of the PCI
+ * pass-through devices (vfio-pci) under this sphb bus.
+ * We have already validated that all the devices under this sphb
+ * are from same iommu group (within same PE) before comming here.
+ *
+ * Prior to linux commit 98ba956f6a389 ("powerpc/pseries/eeh:
+ * Rework device EEH PE determination") kernel would call
+ * eeh-set-option for each device in the PE using the device's
+ * config_address as the argument rather than the PE address.
+ * Hence if we check validity of supplied config_addr whether
+ * it matches to this PHB will cause issues with older kernel
+ * versions v5.9 and older. If we return an error from
+ * eeh-set-option when the argument isn't a valid PE address
+ * then older kernels (v5.9 and older) will interpret that as
+ * EEH not being supported.
*/
phb = PCI_HOST_BRIDGE(sphb);
- pdev = pci_find_device(phb->bus,
- (addr >> 16) & 0xFF, (addr >> 8) & 0xFF);
- if (!pdev || !object_dynamic_cast(OBJECT(pdev), "vfio-pci")) {
+ pci_for_each_device(phb->bus, (addr >> 16) & 0xFF,
+ spapr_eeh_pci_find_device, &found);
+
+ if (!found) {
return RTAS_OUT_PARAM_ERROR;
}
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 03355b4c0a..b476382ae6 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -132,8 +132,8 @@ static void rtas_start_cpu(PowerPCCPU *callcpu, SpaprMachineState *spapr,
target_ulong id, start, r3;
PowerPCCPU *newcpu;
CPUPPCState *env;
- PowerPCCPUClass *pcc;
target_ulong lpcr;
+ target_ulong caller_lpcr;
if (nargs != 3 || nret != 1) {
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
@@ -152,7 +152,6 @@ static void rtas_start_cpu(PowerPCCPU *callcpu, SpaprMachineState *spapr,
}
env = &newcpu->env;
- pcc = POWERPC_CPU_GET_CLASS(newcpu);
if (!CPU(newcpu)->halted) {
rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
@@ -164,11 +163,15 @@ static void rtas_start_cpu(PowerPCCPU *callcpu, SpaprMachineState *spapr,
env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
hreg_compute_hflags(env);
- /* Enable Power-saving mode Exit Cause exceptions for the new CPU */
+ caller_lpcr = callcpu->env.spr[SPR_LPCR];
lpcr = env->spr[SPR_LPCR];
- if (!pcc->interrupts_big_endian(callcpu)) {
- lpcr |= LPCR_ILE;
- }
+
+ /* Set ILE the same way */
+ lpcr = (lpcr & ~LPCR_ILE) | (caller_lpcr & LPCR_ILE);
+
+ /* Set AIL the same way */
+ lpcr = (lpcr & ~LPCR_AIL) | (caller_lpcr & LPCR_AIL);
+
if (env->mmu_model == POWERPC_MMU_3_00) {
/*
* New cpus are expected to start in the same radix/hash mode
diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events
index b4bbfbb013..0ba3e40353 100644
--- a/hw/ppc/trace-events
+++ b/hw/ppc/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# spapr_pci.c
spapr_pci_msi(const char *msg, uint32_t ca) "%s (cfg=0x%x)"
diff --git a/hw/rdma/trace-events b/hw/rdma/trace-events
index 2022a820cb..9accb14973 100644
--- a/hw/rdma/trace-events
+++ b/hw/rdma/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# rdma_backend.c
rdma_check_dev_attr(const char *name, int max_bk, int max_fe) "%s: be=%d, fe=%d"
diff --git a/hw/rdma/vmw/trace-events b/hw/rdma/vmw/trace-events
index 323fca8456..a6c77e1e10 100644
--- a/hw/rdma/vmw/trace-events
+++ b/hw/rdma/vmw/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# pvrdma_main.c
pvrdma_regs_read(uint64_t addr, uint64_t val) "pvrdma.regs[0x%"PRIx64"]=0x%"PRIx64
diff --git a/hw/rtc/trace-events b/hw/rtc/trace-events
index 8bdcf74264..ebb311a5b0 100644
--- a/hw/rtc/trace-events
+++ b/hw/rtc/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# allwinner-rtc.c
allwinner_rtc_read(uint64_t addr, uint64_t value) "addr 0x%" PRIx64 " value 0x%" PRIx64
diff --git a/hw/s390x/trace-events b/hw/s390x/trace-events
index 8156693749..8b9213eab9 100644
--- a/hw/s390x/trace-events
+++ b/hw/s390x/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# css.c
css_enable_facility(const char *facility) "CSS: enable %s"
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 3580e7ee61..e8a547dbb7 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -1582,6 +1582,7 @@ invalid_field:
scsi_check_condition(r, SENSE_CODE(INVALID_FIELD));
}
+/* sector_num and nb_sectors expected to be in qdev blocksize */
static inline bool check_lba_range(SCSIDiskState *s,
uint64_t sector_num, uint32_t nb_sectors)
{
@@ -1614,11 +1615,12 @@ static void scsi_unmap_complete_noio(UnmapCBData *data, int ret)
assert(r->req.aiocb == NULL);
if (data->count > 0) {
- r->sector = ldq_be_p(&data->inbuf[0])
- * (s->qdev.blocksize / BDRV_SECTOR_SIZE);
- r->sector_count = (ldl_be_p(&data->inbuf[8]) & 0xffffffffULL)
- * (s->qdev.blocksize / BDRV_SECTOR_SIZE);
- if (!check_lba_range(s, r->sector, r->sector_count)) {
+ uint64_t sector_num = ldq_be_p(&data->inbuf[0]);
+ uint32_t nb_sectors = ldl_be_p(&data->inbuf[8]) & 0xffffffffULL;
+ r->sector = sector_num * (s->qdev.blocksize / BDRV_SECTOR_SIZE);
+ r->sector_count = nb_sectors * (s->qdev.blocksize / BDRV_SECTOR_SIZE);
+
+ if (!check_lba_range(s, sector_num, nb_sectors)) {
block_acct_invalid(blk_get_stats(s->qdev.conf.blk),
BLOCK_ACCT_UNMAP);
scsi_check_condition(r, SENSE_CODE(LBA_OUT_OF_RANGE));
diff --git a/hw/scsi/trace-events b/hw/scsi/trace-events
index 1c331fb189..1a27e141ae 100644
--- a/hw/scsi/trace-events
+++ b/hw/scsi/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# scsi-bus.c
scsi_req_alloc(int target, int lun, int tag) "target %d lun %d tag %d"
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
index e185d07a1d..3cc2ef89ba 100644
--- a/hw/sd/trace-events
+++ b/hw/sd/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# allwinner-sdhost.c
allwinner_sdhost_set_inserted(bool inserted) "inserted %u"
diff --git a/hw/sparc/trace-events b/hw/sparc/trace-events
index d3a30a816a..00b0212c3b 100644
--- a/hw/sparc/trace-events
+++ b/hw/sparc/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# sun4m.c
sun4m_cpu_set_irq_raise(int level) "Raise CPU IRQ %d"
diff --git a/hw/sparc64/trace-events b/hw/sparc64/trace-events
index b85d14c30c..3eb4bacf79 100644
--- a/hw/sparc64/trace-events
+++ b/hw/sparc64/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# sun4u.c
ebus_isa_irq_handler(int n, int level) "Set ISA IRQ %d level %d"
diff --git a/hw/timer/trace-events b/hw/timer/trace-events
index 029fb56280..5234c0ea9e 100644
--- a/hw/timer/trace-events
+++ b/hw/timer/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# slavio_timer.c
slavio_timer_get_out(uint64_t limit, uint32_t counthigh, uint32_t count) "limit 0x%"PRIx64" count 0x%x0x%08x"
diff --git a/hw/tpm/tpm_ppi.c b/hw/tpm/tpm_ppi.c
index 72d7a3d926..362edcc5c9 100644
--- a/hw/tpm/tpm_ppi.c
+++ b/hw/tpm/tpm_ppi.c
@@ -23,7 +23,7 @@
void tpm_ppi_reset(TPMPPI *tpmppi)
{
- if (tpmppi->buf[0x15a /* movv, docs/specs/tpm.txt */] & 0x1) {
+ if (tpmppi->buf[0x15a /* movv, docs/specs/tpm.rst */] & 0x1) {
GuestPhysBlockList guest_phys_blocks;
GuestPhysBlock *block;
diff --git a/hw/tpm/trace-events b/hw/tpm/trace-events
index 6005ecb5da..f17110458e 100644
--- a/hw/tpm/trace-events
+++ b/hw/tpm/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# tpm_crb.c
tpm_crb_mmio_read(uint64_t addr, unsigned size, uint32_t val) "CRB read 0x%016" PRIx64 " len:%u val: 0x%" PRIx32
diff --git a/hw/usb/hcd-xhci-pci.c b/hw/usb/hcd-xhci-pci.c
index 9421734d0f..e934b1a5b1 100644
--- a/hw/usb/hcd-xhci-pci.c
+++ b/hw/usb/hcd-xhci-pci.c
@@ -57,7 +57,7 @@ static void xhci_pci_intr_update(XHCIState *xhci, int n, bool enable)
}
}
-static void xhci_pci_intr_raise(XHCIState *xhci, int n, bool level)
+static bool xhci_pci_intr_raise(XHCIState *xhci, int n, bool level)
{
XHCIPciState *s = container_of(xhci, XHCIPciState, xhci);
PCIDevice *pci_dev = PCI_DEVICE(s);
@@ -67,15 +67,18 @@ static void xhci_pci_intr_raise(XHCIState *xhci, int n, bool level)
msi_enabled(pci_dev))) {
pci_set_irq(pci_dev, level);
}
- if (msix_enabled(pci_dev)) {
+
+ if (msix_enabled(pci_dev) && level) {
msix_notify(pci_dev, n);
- return;
+ return true;
}
- if (msi_enabled(pci_dev)) {
+ if (msi_enabled(pci_dev) && level) {
msi_notify(pci_dev, n);
- return;
+ return true;
}
+
+ return false;
}
static void xhci_pci_reset(DeviceState *dev)
diff --git a/hw/usb/hcd-xhci-sysbus.c b/hw/usb/hcd-xhci-sysbus.c
index 42e2574c82..a14e438196 100644
--- a/hw/usb/hcd-xhci-sysbus.c
+++ b/hw/usb/hcd-xhci-sysbus.c
@@ -16,11 +16,13 @@
#include "hw/acpi/aml-build.h"
#include "hw/irq.h"
-static void xhci_sysbus_intr_raise(XHCIState *xhci, int n, bool level)
+static bool xhci_sysbus_intr_raise(XHCIState *xhci, int n, bool level)
{
XHCISysbusState *s = container_of(xhci, XHCISysbusState, xhci);
qemu_set_irq(s->irq[n], level);
+
+ return false;
}
void xhci_sysbus_reset(DeviceState *dev)
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 46212b1e69..e01700039b 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -551,7 +551,9 @@ static void xhci_intr_update(XHCIState *xhci, int v)
level = 1;
}
if (xhci->intr_raise) {
- xhci->intr_raise(xhci, 0, level);
+ if (xhci->intr_raise(xhci, 0, level)) {
+ xhci->intr[0].iman &= ~IMAN_IP;
+ }
}
}
if (xhci->intr_update) {
@@ -579,7 +581,9 @@ static void xhci_intr_raise(XHCIState *xhci, int v)
return;
}
if (xhci->intr_raise) {
- xhci->intr_raise(xhci, v, true);
+ if (xhci->intr_raise(xhci, v, true)) {
+ xhci->intr[v].iman &= ~IMAN_IP;
+ }
}
}
diff --git a/hw/usb/hcd-xhci.h b/hw/usb/hcd-xhci.h
index 7bba361f3b..98f598382a 100644
--- a/hw/usb/hcd-xhci.h
+++ b/hw/usb/hcd-xhci.h
@@ -194,7 +194,7 @@ typedef struct XHCIState {
uint32_t flags;
uint32_t max_pstreams_mask;
void (*intr_update)(XHCIState *s, int n, bool enable);
- void (*intr_raise)(XHCIState *s, int n, bool level);
+ bool (*intr_raise)(XHCIState *s, int n, bool level);
DeviceState *hostOpaque;
/* Operational Registers */
diff --git a/hw/usb/trace-events b/hw/usb/trace-events
index 38e05fc7f4..b8287b63f1 100644
--- a/hw/usb/trace-events
+++ b/hw/usb/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# core.c
usb_packet_state_change(int bus, const char *port, int ep, void *p, const char *o, const char *n) "bus %d, port %s, ep %d, packet %p, state %s -> %s"
diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events
index 079f53acf2..0ef1b5f4a6 100644
--- a/hw/vfio/trace-events
+++ b/hw/vfio/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# pci.c
vfio_intx_interrupt(const char *name, char line) " (%s) Pin %c"
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index c62727f879..8ed19e9d0c 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# vhost.c
vhost_commit(bool started, bool changed) "Started: %d Changed: %d"
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index e02544b2df..ab516ac614 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1972,9 +1972,7 @@ static enum virtio_device_endian virtio_default_endian(void)
static enum virtio_device_endian virtio_current_cpu_endian(void)
{
- CPUClass *cc = CPU_GET_CLASS(current_cpu);
-
- if (cc->virtio_is_big_endian(current_cpu)) {
+ if (cpu_virtio_is_big_endian(current_cpu)) {
return VIRTIO_DEVICE_ENDIAN_BIG;
} else {
return VIRTIO_DEVICE_ENDIAN_LITTLE;
diff --git a/hw/watchdog/trace-events b/hw/watchdog/trace-events
index 3124ca1f1b..c3bafbffa9 100644
--- a/hw/watchdog/trace-events
+++ b/hw/watchdog/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# cmsdk-apb-watchdog.c
cmsdk_apb_watchdog_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB watchdog read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
diff --git a/hw/xen/trace-events b/hw/xen/trace-events
index e6885bc751..3da3fd8348 100644
--- a/hw/xen/trace-events
+++ b/hw/xen/trace-events
@@ -1,4 +1,4 @@
-# See docs/devel/tracing.txt for syntax documentation.
+# See docs/devel/tracing.rst for syntax documentation.
# ../../include/hw/xen/xen_common.h
xen_default_ioreq_server(void) ""