aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/9pfs/9p-handle.c1
-rw-r--r--hw/9pfs/9p-local.c3
-rw-r--r--hw/9pfs/9p-proxy.c3
-rw-r--r--hw/9pfs/xen-9p-backend.c1
-rw-r--r--hw/acpi/acpi-stub.c2
-rw-r--r--hw/acpi/core.c3
-rw-r--r--hw/acpi/memory_hotplug.c1
-rw-r--r--hw/acpi/vmgenid.c1
-rw-r--r--hw/adc/stm32f2xx_adc.c1
-rw-r--r--hw/arm/boot.c66
-rw-r--r--hw/arm/fsl-imx6.c2
-rw-r--r--hw/arm/virt.c61
-rw-r--r--hw/block/vhost-user-blk.c1
-rw-r--r--hw/char/mcf_uart.c1
-rw-r--r--hw/char/virtio-console.c1
-rw-r--r--hw/core/generic-loader.c2
-rw-r--r--hw/core/machine.c2
-rw-r--r--hw/core/qdev.c3
-rw-r--r--hw/display/milkymist-tmu2.c1
-rw-r--r--hw/display/qxl.c1
-rw-r--r--hw/display/virtio-gpu-3d.c1
-rw-r--r--hw/display/virtio-gpu-pci.c2
-rw-r--r--hw/display/xlnx_dp.c1
-rw-r--r--hw/i2c/ppc4xx_i2c.c1
-rw-r--r--hw/i386/acpi-build.c1
-rw-r--r--hw/i386/multiboot.c2
-rw-r--r--hw/i386/pc.c3
-rw-r--r--hw/i386/pc_piix.c1
-rw-r--r--hw/i386/pc_q35.c2
-rw-r--r--hw/i386/pc_sysfw.c1
-rw-r--r--hw/i386/xen/xen-hvm.c2
-rw-r--r--hw/ide/core.c2
-rw-r--r--hw/ide/sii3112.c4
-rw-r--r--hw/intc/Makefile.objs2
-rw-r--r--hw/intc/armv7m_nvic.c98
-rw-r--r--hw/intc/imx_gpcv2.c125
-rw-r--r--hw/intc/s390_flic.c257
-rw-r--r--hw/intc/s390_flic_kvm.c84
-rw-r--r--hw/intc/trace-events5
-rw-r--r--hw/intc/xics_pnv.c1
-rw-r--r--hw/intc/xics_spapr.c1
-rw-r--r--hw/ipmi/ipmi.c1
-rw-r--r--hw/mips/mips_jazz.c1
-rw-r--r--hw/mips/mips_malta.c1
-rw-r--r--hw/misc/Makefile.objs7
-rw-r--r--hw/misc/exynos4210_rng.c1
-rw-r--r--hw/misc/imx2_wdt.c89
-rw-r--r--hw/misc/imx7_ccm.c277
-rw-r--r--hw/misc/imx7_gpr.c124
-rw-r--r--hw/misc/imx7_snvs.c83
-rw-r--r--hw/misc/macio/cuda.c111
-rw-r--r--hw/misc/macio/macio.c2
-rw-r--r--hw/misc/mips_cmgcr.c1
-rw-r--r--hw/misc/mos6522.c505
-rw-r--r--hw/misc/mps2-scc.c1
-rw-r--r--hw/misc/trace-events11
-rw-r--r--hw/net/rocker/qmp-norocker.c1
-rw-r--r--hw/net/rocker/rocker.c1
-rw-r--r--hw/net/rocker/rocker_of_dpa.c1
-rw-r--r--hw/net/virtio-net.c2
-rw-r--r--hw/nios2/cpu_pic.c1
-rw-r--r--hw/nvram/eeprom_at24c.c3
-rw-r--r--hw/nvram/fw_cfg.c2
-rw-r--r--hw/pci-bridge/i82801b11.c2
-rw-r--r--hw/pci-bridge/ioh3420.c1
-rw-r--r--hw/pci-bridge/xio3130_upstream.c1
-rw-r--r--hw/pci-host/sabre.c1
-rw-r--r--hw/pci/pci-stub.c1
-rw-r--r--hw/pci/pci.c2
-rw-r--r--hw/pci/pcie_aer.c3
-rw-r--r--hw/ppc/e500.c2
-rw-r--r--hw/ppc/fdt.c1
-rw-r--r--hw/ppc/mac.h2
-rw-r--r--hw/ppc/pnv_bmc.c1
-rw-r--r--hw/ppc/pnv_xscom.c1
-rw-r--r--hw/ppc/ppc.c1
-rw-r--r--hw/ppc/spapr.c6
-rw-r--r--hw/ppc/spapr_drc.c1
-rw-r--r--hw/ppc/spapr_hcall.c3
-rw-r--r--hw/ppc/spapr_pci_vfio.c1
-rw-r--r--hw/ppc/spapr_rtc.c3
-rw-r--r--hw/ppc/virtex_ml507.c1
-rw-r--r--hw/s390x/css.c10
-rw-r--r--hw/s390x/event-facility.c4
-rw-r--r--hw/s390x/s390-ccw.c3
-rw-r--r--hw/s390x/s390-pci-bus.c233
-rw-r--r--hw/s390x/s390-pci-bus.h17
-rw-r--r--hw/s390x/s390-pci-inst.c103
-rw-r--r--hw/s390x/s390-skeys.c2
-rw-r--r--hw/s390x/s390-stattrib.c2
-rw-r--r--hw/s390x/s390-virtio-ccw.c7
-rw-r--r--hw/s390x/virtio-ccw.c4
-rw-r--r--hw/scsi/esp.c1
-rw-r--r--hw/scsi/scsi-bus.c1
-rw-r--r--hw/scsi/vhost-scsi-common.c1
-rw-r--r--hw/sd/sdhci-internal.h23
-rw-r--r--hw/sd/sdhci.c231
-rw-r--r--hw/smbios/smbios-stub.c2
-rw-r--r--hw/smbios/smbios.c1
-rw-r--r--hw/sparc64/niagara.c1
-rw-r--r--hw/sparc64/sun4u_iommu.c1
-rw-r--r--hw/ssi/stm32f2xx_spi.c1
-rw-r--r--hw/timer/imx_gpt.c25
-rw-r--r--hw/timer/m48t59.c1
-rw-r--r--hw/timer/mc146818rtc.c2
-rw-r--r--hw/tpm/tpm_emulator.c5
-rw-r--r--hw/tpm/tpm_int.h2
-rw-r--r--hw/tpm/tpm_ioctl.h2
-rw-r--r--hw/usb/Makefile.objs1
-rw-r--r--hw/usb/ccid-card-passthru.c1
-rw-r--r--hw/usb/chipidea.c176
-rw-r--r--hw/usb/xen-usb.c4
-rw-r--r--hw/vfio/pci.c1
-rw-r--r--hw/virtio/virtio-balloon.c1
-rw-r--r--hw/watchdog/watchdog.c2
-rw-r--r--hw/xen/xen-common.c1
-rw-r--r--hw/xen/xen_devconfig.c1
-rw-r--r--hw/xtensa/xtensa_memory.h1
-rw-r--r--hw/xtensa/xtfpga.c2
119 files changed, 2561 insertions, 328 deletions
diff --git a/hw/9pfs/9p-handle.c b/hw/9pfs/9p-handle.c
index c1681d3c8a..4dc0d2bed1 100644
--- a/hw/9pfs/9p-handle.c
+++ b/hw/9pfs/9p-handle.c
@@ -22,6 +22,7 @@
#include "qemu/xattr.h"
#include "qemu/cutils.h"
#include "qemu/error-report.h"
+#include "qemu/option.h"
#include <linux/fs.h>
#ifdef CONFIG_LINUX_MAGIC_H
#include <linux/magic.h>
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index b25c185ff0..b37b1db453 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -8,7 +8,6 @@
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
- *
*/
#include "qemu/osdep.h"
@@ -23,8 +22,10 @@
#include <sys/socket.h>
#include <sys/un.h>
#include "qemu/xattr.h"
+#include "qapi/error.h"
#include "qemu/cutils.h"
#include "qemu/error-report.h"
+#include "qemu/option.h"
#include <libgen.h>
#include <linux/fs.h>
#ifdef CONFIG_LINUX_MAGIC_H
diff --git a/hw/9pfs/9p-proxy.c b/hw/9pfs/9p-proxy.c
index f030c6a428..e2e03292de 100644
--- a/hw/9pfs/9p-proxy.c
+++ b/hw/9pfs/9p-proxy.c
@@ -9,12 +9,15 @@
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*/
+
#include "qemu/osdep.h"
#include <sys/socket.h>
#include <sys/un.h>
#include "9p.h"
+#include "qapi/error.h"
#include "qemu/cutils.h"
#include "qemu/error-report.h"
+#include "qemu/option.h"
#include "fsdev/qemu-fsdev.h"
#include "9p-proxy.h"
diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c
index 14f0d6a50e..95e50c4dfc 100644
--- a/hw/9pfs/xen-9p-backend.c
+++ b/hw/9pfs/xen-9p-backend.c
@@ -15,6 +15,7 @@
#include "hw/xen/xen_backend.h"
#include "hw/9pfs/xen-9pfs.h"
#include "qemu/config-file.h"
+#include "qemu/option.h"
#include "fsdev/qemu-fsdev.h"
#define VERSIONS "1"
diff --git a/hw/acpi/acpi-stub.c b/hw/acpi/acpi-stub.c
index 26bd22f7ec..4c9d081ed4 100644
--- a/hw/acpi/acpi-stub.c
+++ b/hw/acpi/acpi-stub.c
@@ -19,8 +19,8 @@
*/
#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "qapi/qmp/qerror.h"
-#include "qmp-commands.h"
#include "hw/acpi/acpi.h"
void acpi_table_add(const QemuOpts *opts, Error **errp)
diff --git a/hw/acpi/core.c b/hw/acpi/core.c
index eb9b76f70b..b50b3ca772 100644
--- a/hw/acpi/core.c
+++ b/hw/acpi/core.c
@@ -18,16 +18,19 @@
* Contributions after 2012-01-13 are licensed under the terms of the
* GNU GPL, version 2 or (at your option) any later version.
*/
+
#include "qemu/osdep.h"
#include "sysemu/sysemu.h"
#include "hw/hw.h"
#include "hw/acpi/acpi.h"
#include "hw/nvram/fw_cfg.h"
#include "qemu/config-file.h"
+#include "qapi/error.h"
#include "qapi/opts-visitor.h"
#include "qapi-visit.h"
#include "qapi-event.h"
#include "qemu/error-report.h"
+#include "qemu/option.h"
struct acpi_table_header {
uint16_t _length; /* our length, not actual part of the hdr */
diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
index cda2c9dd06..ea958a0e99 100644
--- a/hw/acpi/memory_hotplug.c
+++ b/hw/acpi/memory_hotplug.c
@@ -6,6 +6,7 @@
#include "hw/qdev-core.h"
#include "trace.h"
#include "qapi-event.h"
+#include "qapi/error.h"
#define MEMORY_SLOTS_NUMBER "MDNR"
#define MEMORY_HOTPLUG_IO_REGION "HPMR"
diff --git a/hw/acpi/vmgenid.c b/hw/acpi/vmgenid.c
index ba6f47b67b..f25eafc0ec 100644
--- a/hw/acpi/vmgenid.c
+++ b/hw/acpi/vmgenid.c
@@ -11,6 +11,7 @@
*/
#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "qmp-commands.h"
#include "hw/acpi/acpi.h"
#include "hw/acpi/aml-build.h"
diff --git a/hw/adc/stm32f2xx_adc.c b/hw/adc/stm32f2xx_adc.c
index 13f31ad2f7..329a8aa673 100644
--- a/hw/adc/stm32f2xx_adc.c
+++ b/hw/adc/stm32f2xx_adc.c
@@ -25,7 +25,6 @@
#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "hw/hw.h"
-#include "qapi/error.h"
#include "qemu/log.h"
#include "hw/adc/stm32f2xx_adc.h"
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index bb244ec359..05108bc42f 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -22,6 +22,7 @@
#include "elf.h"
#include "sysemu/device_tree.h"
#include "qemu/config-file.h"
+#include "qemu/option.h"
#include "exec/address-spaces.h"
/* Kernel boot protocol is specified in the kernel docs
@@ -385,6 +386,69 @@ static void set_kernel_args_old(const struct arm_boot_info *info)
}
}
+static void fdt_add_psci_node(void *fdt)
+{
+ uint32_t cpu_suspend_fn;
+ uint32_t cpu_off_fn;
+ uint32_t cpu_on_fn;
+ uint32_t migrate_fn;
+ ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(0));
+ const char *psci_method;
+ int64_t psci_conduit;
+
+ psci_conduit = object_property_get_int(OBJECT(armcpu),
+ "psci-conduit",
+ &error_abort);
+ switch (psci_conduit) {
+ case QEMU_PSCI_CONDUIT_DISABLED:
+ return;
+ case QEMU_PSCI_CONDUIT_HVC:
+ psci_method = "hvc";
+ break;
+ case QEMU_PSCI_CONDUIT_SMC:
+ psci_method = "smc";
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ qemu_fdt_add_subnode(fdt, "/psci");
+ if (armcpu->psci_version == 2) {
+ const char comp[] = "arm,psci-0.2\0arm,psci";
+ qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp));
+
+ cpu_off_fn = QEMU_PSCI_0_2_FN_CPU_OFF;
+ if (arm_feature(&armcpu->env, ARM_FEATURE_AARCH64)) {
+ cpu_suspend_fn = QEMU_PSCI_0_2_FN64_CPU_SUSPEND;
+ cpu_on_fn = QEMU_PSCI_0_2_FN64_CPU_ON;
+ migrate_fn = QEMU_PSCI_0_2_FN64_MIGRATE;
+ } else {
+ cpu_suspend_fn = QEMU_PSCI_0_2_FN_CPU_SUSPEND;
+ cpu_on_fn = QEMU_PSCI_0_2_FN_CPU_ON;
+ migrate_fn = QEMU_PSCI_0_2_FN_MIGRATE;
+ }
+ } else {
+ qemu_fdt_setprop_string(fdt, "/psci", "compatible", "arm,psci");
+
+ cpu_suspend_fn = QEMU_PSCI_0_1_FN_CPU_SUSPEND;
+ cpu_off_fn = QEMU_PSCI_0_1_FN_CPU_OFF;
+ cpu_on_fn = QEMU_PSCI_0_1_FN_CPU_ON;
+ migrate_fn = QEMU_PSCI_0_1_FN_MIGRATE;
+ }
+
+ /* We adopt the PSCI spec's nomenclature, and use 'conduit' to refer
+ * to the instruction that should be used to invoke PSCI functions.
+ * However, the device tree binding uses 'method' instead, so that is
+ * what we should use here.
+ */
+ qemu_fdt_setprop_string(fdt, "/psci", "method", psci_method);
+
+ qemu_fdt_setprop_cell(fdt, "/psci", "cpu_suspend", cpu_suspend_fn);
+ qemu_fdt_setprop_cell(fdt, "/psci", "cpu_off", cpu_off_fn);
+ qemu_fdt_setprop_cell(fdt, "/psci", "cpu_on", cpu_on_fn);
+ qemu_fdt_setprop_cell(fdt, "/psci", "migrate", migrate_fn);
+}
+
/**
* load_dtb() - load a device tree binary image into memory
* @addr: the address to load the image at
@@ -541,6 +605,8 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
}
}
+ fdt_add_psci_node(fdt);
+
if (binfo->modify_dtb) {
binfo->modify_dtb(binfo, fdt);
}
diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
index b0d4088290..e6559a8b12 100644
--- a/hw/arm/fsl-imx6.c
+++ b/hw/arm/fsl-imx6.c
@@ -93,7 +93,7 @@ static void fsl_imx6_init(Object *obj)
}
for (i = 0; i < FSL_IMX6_NUM_ESDHCS; i++) {
- object_initialize(&s->esdhc[i], sizeof(s->esdhc[i]), TYPE_SYSBUS_SDHCI);
+ object_initialize(&s->esdhc[i], sizeof(s->esdhc[i]), TYPE_IMX_USDHC);
qdev_set_parent_bus(DEVICE(&s->esdhc[i]), sysbus_get_default());
snprintf(name, NAME_SIZE, "sdhc%d", i + 1);
object_property_add_child(obj, name, OBJECT(&s->esdhc[i]), NULL);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index b334c82eda..dbb3c8036a 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -244,66 +244,6 @@ static void create_fdt(VirtMachineState *vms)
}
}
-static void fdt_add_psci_node(const VirtMachineState *vms)
-{
- uint32_t cpu_suspend_fn;
- uint32_t cpu_off_fn;
- uint32_t cpu_on_fn;
- uint32_t migrate_fn;
- void *fdt = vms->fdt;
- ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(0));
- const char *psci_method;
-
- switch (vms->psci_conduit) {
- case QEMU_PSCI_CONDUIT_DISABLED:
- return;
- case QEMU_PSCI_CONDUIT_HVC:
- psci_method = "hvc";
- break;
- case QEMU_PSCI_CONDUIT_SMC:
- psci_method = "smc";
- break;
- default:
- g_assert_not_reached();
- }
-
- qemu_fdt_add_subnode(fdt, "/psci");
- if (armcpu->psci_version == 2) {
- const char comp[] = "arm,psci-0.2\0arm,psci";
- qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp));
-
- cpu_off_fn = QEMU_PSCI_0_2_FN_CPU_OFF;
- if (arm_feature(&armcpu->env, ARM_FEATURE_AARCH64)) {
- cpu_suspend_fn = QEMU_PSCI_0_2_FN64_CPU_SUSPEND;
- cpu_on_fn = QEMU_PSCI_0_2_FN64_CPU_ON;
- migrate_fn = QEMU_PSCI_0_2_FN64_MIGRATE;
- } else {
- cpu_suspend_fn = QEMU_PSCI_0_2_FN_CPU_SUSPEND;
- cpu_on_fn = QEMU_PSCI_0_2_FN_CPU_ON;
- migrate_fn = QEMU_PSCI_0_2_FN_MIGRATE;
- }
- } else {
- qemu_fdt_setprop_string(fdt, "/psci", "compatible", "arm,psci");
-
- cpu_suspend_fn = QEMU_PSCI_0_1_FN_CPU_SUSPEND;
- cpu_off_fn = QEMU_PSCI_0_1_FN_CPU_OFF;
- cpu_on_fn = QEMU_PSCI_0_1_FN_CPU_ON;
- migrate_fn = QEMU_PSCI_0_1_FN_MIGRATE;
- }
-
- /* We adopt the PSCI spec's nomenclature, and use 'conduit' to refer
- * to the instruction that should be used to invoke PSCI functions.
- * However, the device tree binding uses 'method' instead, so that is
- * what we should use here.
- */
- qemu_fdt_setprop_string(fdt, "/psci", "method", psci_method);
-
- qemu_fdt_setprop_cell(fdt, "/psci", "cpu_suspend", cpu_suspend_fn);
- qemu_fdt_setprop_cell(fdt, "/psci", "cpu_off", cpu_off_fn);
- qemu_fdt_setprop_cell(fdt, "/psci", "cpu_on", cpu_on_fn);
- qemu_fdt_setprop_cell(fdt, "/psci", "migrate", migrate_fn);
-}
-
static void fdt_add_timer_nodes(const VirtMachineState *vms)
{
/* On real hardware these interrupts are level-triggered.
@@ -1409,7 +1349,6 @@ static void machvirt_init(MachineState *machine)
}
fdt_add_timer_nodes(vms);
fdt_add_cpu_nodes(vms);
- fdt_add_psci_node(vms);
memory_region_allocate_system_memory(ram, NULL, "mach-virt.ram",
machine->ram_size);
diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index b53b4c9c57..f840f07dfe 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -19,7 +19,6 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
-#include "qemu/typedefs.h"
#include "qemu/cutils.h"
#include "qom/object.h"
#include "hw/qdev-core.h"
diff --git a/hw/char/mcf_uart.c b/hw/char/mcf_uart.c
index 56fa402b58..faae083e78 100644
--- a/hw/char/mcf_uart.c
+++ b/hw/char/mcf_uart.c
@@ -11,7 +11,6 @@
#include "hw/m68k/mcf.h"
#include "chardev/char-fe.h"
#include "exec/address-spaces.h"
-#include "qapi/error.h"
typedef struct {
SysBusDevice parent_obj;
diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c
index 172c72d06c..4be5d4ee52 100644
--- a/hw/char/virtio-console.c
+++ b/hw/char/virtio-console.c
@@ -16,6 +16,7 @@
#include "trace.h"
#include "hw/virtio/virtio-serial.h"
#include "qapi-event.h"
+#include "qapi/error.h"
#define TYPE_VIRTIO_CONSOLE_SERIAL_PORT "virtserialport"
#define VIRTIO_CONSOLE(obj) \
diff --git a/hw/core/generic-loader.c b/hw/core/generic-loader.c
index 46012673c3..cb0e68486d 100644
--- a/hw/core/generic-loader.c
+++ b/hw/core/generic-loader.c
@@ -105,7 +105,7 @@ static void generic_loader_realize(DeviceState *dev, Error **errp)
error_setg(errp, "data can not be specified when setting a "
"program counter");
return;
- } else if (!s->cpu_num) {
+ } else if (s->cpu_num == CPU_NONE) {
error_setg(errp, "cpu_num must be specified when setting a "
"program counter");
return;
diff --git a/hw/core/machine.c b/hw/core/machine.c
index cdc1163dc6..5d445839e8 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -520,7 +520,7 @@ static void machine_class_init(ObjectClass *oc, void *data)
object_class_property_set_description(oc, "accel",
"Accelerator list", &error_abort);
- object_class_property_add(oc, "kernel-irqchip", "OnOffSplit",
+ object_class_property_add(oc, "kernel-irqchip", "on|off|split",
NULL, machine_set_kernel_irqchip,
NULL, NULL, &error_abort);
object_class_property_set_description(oc, "kernel-irqchip",
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 11f8a27a69..7ed1f431f0 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -28,10 +28,11 @@
#include "qemu/osdep.h"
#include "hw/qdev.h"
#include "sysemu/sysemu.h"
+#include "qapi/error.h"
#include "qapi/qmp/qerror.h"
#include "qapi/visitor.h"
-#include "qapi/qmp/qjson.h"
#include "qemu/error-report.h"
+#include "qemu/option.h"
#include "hw/hotplug.h"
#include "hw/boards.h"
#include "hw/sysbus.h"
diff --git a/hw/display/milkymist-tmu2.c b/hw/display/milkymist-tmu2.c
index 59120ddb67..3ce44fdfce 100644
--- a/hw/display/milkymist-tmu2.c
+++ b/hw/display/milkymist-tmu2.c
@@ -28,6 +28,7 @@
#include "hw/hw.h"
#include "hw/sysbus.h"
#include "trace.h"
+#include "qapi/error.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index b9fa067f6e..a71714ccb4 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -21,6 +21,7 @@
#include "qemu/osdep.h"
#include <zlib.h>
+#include "qapi/error.h"
#include "qemu-common.h"
#include "qemu/timer.h"
#include "qemu/queue.h"
diff --git a/hw/display/virtio-gpu-3d.c b/hw/display/virtio-gpu-3d.c
index 8c106a662d..7db84efe89 100644
--- a/hw/display/virtio-gpu-3d.c
+++ b/hw/display/virtio-gpu-3d.c
@@ -17,7 +17,6 @@
#include "trace.h"
#include "hw/virtio/virtio.h"
#include "hw/virtio/virtio-gpu.h"
-#include "qapi/error.h"
#ifdef CONFIG_VIRGL
diff --git a/hw/display/virtio-gpu-pci.c b/hw/display/virtio-gpu-pci.c
index 3519dc80b1..cece4aa495 100644
--- a/hw/display/virtio-gpu-pci.c
+++ b/hw/display/virtio-gpu-pci.c
@@ -10,7 +10,9 @@
* See the COPYING file in the top-level directory.
*
*/
+
#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "hw/pci/pci.h"
#include "hw/virtio/virtio.h"
#include "hw/virtio/virtio-bus.h"
diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c
index ead4e1a0e4..6715b9cc2b 100644
--- a/hw/display/xlnx_dp.c
+++ b/hw/display/xlnx_dp.c
@@ -23,6 +23,7 @@
*/
#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "qemu/log.h"
#include "hw/display/xlnx_dp.h"
diff --git a/hw/i2c/ppc4xx_i2c.c b/hw/i2c/ppc4xx_i2c.c
index e873a445da..ab64d196be 100644
--- a/hw/i2c/ppc4xx_i2c.c
+++ b/hw/i2c/ppc4xx_i2c.c
@@ -25,7 +25,6 @@
*/
#include "qemu/osdep.h"
-#include "qapi/error.h"
#include "qemu-common.h"
#include "qemu/log.h"
#include "cpu.h"
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index ed78c4ed9f..deb440f286 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -22,6 +22,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
+#include "qapi/qmp/qnum.h"
#include "acpi-build.h"
#include "qemu-common.h"
#include "qemu/bitmap.h"
diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c
index c7b70c91d5..46d9c68bf5 100644
--- a/hw/i386/multiboot.c
+++ b/hw/i386/multiboot.c
@@ -23,7 +23,7 @@
*/
#include "qemu/osdep.h"
-#include "qemu-common.h"
+#include "qemu/option.h"
#include "cpu.h"
#include "hw/hw.h"
#include "hw/nvram/fw_cfg.h"
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index ccc50baa85..55e69d66fe 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -21,6 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+
#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/i386/pc.h"
@@ -58,12 +59,14 @@
#include "qemu/bitmap.h"
#include "qemu/config-file.h"
#include "qemu/error-report.h"
+#include "qemu/option.h"
#include "hw/acpi/acpi.h"
#include "hw/acpi/cpu_hotplug.h"
#include "hw/boards.h"
#include "hw/pci/pci_host.h"
#include "acpi-build.h"
#include "hw/mem/pc-dimm.h"
+#include "qapi/error.h"
#include "qapi/visitor.h"
#include "qapi-visit.h"
#include "qom/cpu.h"
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index a25619dfbf..456dc9e9f0 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -47,6 +47,7 @@
#include "exec/address-spaces.h"
#include "hw/acpi/acpi.h"
#include "cpu.h"
+#include "qapi/error.h"
#include "qemu/error-report.h"
#ifdef CONFIG_XEN
#include <xen/hvm/hvm_info_table.h>
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index ed3a0b8ff7..aba7541a82 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -27,6 +27,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+
#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/loader.h"
@@ -48,6 +49,7 @@
#include "hw/ide/pci.h"
#include "hw/ide/ahci.h"
#include "hw/usb.h"
+#include "qapi/error.h"
#include "qemu/error-report.h"
#include "sysemu/numa.h"
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
index 6b183747fc..4325575e7d 100644
--- a/hw/i386/pc_sysfw.c
+++ b/hw/i386/pc_sysfw.c
@@ -27,6 +27,7 @@
#include "qapi/error.h"
#include "sysemu/block-backend.h"
#include "qemu/error-report.h"
+#include "qemu/option.h"
#include "hw/sysbus.h"
#include "hw/hw.h"
#include "hw/i386/pc.h"
diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
index 8028bed6fd..bfdbe55580 100644
--- a/hw/i386/xen/xen-hvm.c
+++ b/hw/i386/xen/xen-hvm.c
@@ -17,7 +17,7 @@
#include "hw/xen/xen_common.h"
#include "hw/xen/xen_backend.h"
#include "qmp-commands.h"
-
+#include "qapi/error.h"
#include "qemu/error-report.h"
#include "qemu/range.h"
#include "sysemu/xen-mapcache.h"
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 5be72d41dc..257b429381 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -22,6 +22,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+
#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/pci/pci.h"
@@ -33,6 +34,7 @@
#include "sysemu/dma.h"
#include "hw/block/block.h"
#include "sysemu/block-backend.h"
+#include "qapi/error.h"
#include "qemu/cutils.h"
#include "hw/ide/internal.h"
diff --git a/hw/ide/sii3112.c b/hw/ide/sii3112.c
index 17aa930e39..e3896c65b4 100644
--- a/hw/ide/sii3112.c
+++ b/hw/ide/sii3112.c
@@ -12,8 +12,8 @@
* http://wiki.osdev.org/User:Quok/Silicon_Image_Datasheets
*/
-#include <qemu/osdep.h>
-#include <hw/ide/pci.h>
+#include "qemu/osdep.h"
+#include "hw/ide/pci.h"
#include "trace.h"
#define TYPE_SII3112_PCI "sii3112"
diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index 571e094a14..0e9963f5ee 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -6,7 +6,7 @@ common-obj-$(CONFIG_XILINX) += xilinx_intc.o
common-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-pmu-iomod-intc.o
common-obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp-ipi.o
common-obj-$(CONFIG_ETRAXFS) += etraxfs_pic.o
-common-obj-$(CONFIG_IMX) += imx_avic.o
+common-obj-$(CONFIG_IMX) += imx_avic.o imx_gpcv2.o
common-obj-$(CONFIG_LM32) += lm32_pic.o
common-obj-$(CONFIG_REALVIEW) += realview_gic.o
common-obj-$(CONFIG_SLAVIO) += slavio_intctl.o
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 8ca6ceeb9b..360889d30b 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -503,8 +503,25 @@ static void armv7m_nvic_clear_pending(void *opaque, int irq, bool secure)
}
}
-void armv7m_nvic_set_pending(void *opaque, int irq, bool secure)
+static void do_armv7m_nvic_set_pending(void *opaque, int irq, bool secure,
+ bool derived)
{
+ /* Pend an exception, including possibly escalating it to HardFault.
+ *
+ * This function handles both "normal" pending of interrupts and
+ * exceptions, and also derived exceptions (ones which occur as
+ * a result of trying to take some other exception).
+ *
+ * If derived == true, the caller guarantees that we are part way through
+ * trying to take an exception (but have not yet called
+ * armv7m_nvic_acknowledge_irq() to make it active), and so:
+ * - s->vectpending is the "original exception" we were trying to take
+ * - irq is the "derived exception"
+ * - nvic_exec_prio(s) gives the priority before exception entry
+ * Here we handle the prioritization logic which the pseudocode puts
+ * in the DerivedLateArrival() function.
+ */
+
NVICState *s = (NVICState *)opaque;
bool banked = exc_is_banked(irq);
VecInfo *vec;
@@ -514,7 +531,44 @@ void armv7m_nvic_set_pending(void *opaque, int irq, bool secure)
vec = (banked && secure) ? &s->sec_vectors[irq] : &s->vectors[irq];
- trace_nvic_set_pending(irq, secure, vec->enabled, vec->prio);
+ trace_nvic_set_pending(irq, secure, derived, vec->enabled, vec->prio);
+
+ if (derived) {
+ /* Derived exceptions are always synchronous. */
+ assert(irq >= ARMV7M_EXCP_HARD && irq < ARMV7M_EXCP_PENDSV);
+
+ if (irq == ARMV7M_EXCP_DEBUG &&
+ exc_group_prio(s, vec->prio, secure) >= nvic_exec_prio(s)) {
+ /* DebugMonitorFault, but its priority is lower than the
+ * preempted exception priority: just ignore it.
+ */
+ return;
+ }
+
+ if (irq == ARMV7M_EXCP_HARD && vec->prio >= s->vectpending_prio) {
+ /* If this is a terminal exception (one which means we cannot
+ * take the original exception, like a failure to read its
+ * vector table entry), then we must take the derived exception.
+ * If the derived exception can't take priority over the
+ * original exception, then we go into Lockup.
+ *
+ * For QEMU, we rely on the fact that a derived exception is
+ * terminal if and only if it's reported to us as HardFault,
+ * which saves having to have an extra argument is_terminal
+ * that we'd only use in one place.
+ */
+ cpu_abort(&s->cpu->parent_obj,
+ "Lockup: can't take terminal derived exception "
+ "(original exception priority %d)\n",
+ s->vectpending_prio);
+ }
+ /* We now continue with the same code as for a normal pending
+ * exception, which will cause us to pend the derived exception.
+ * We'll then take either the original or the derived exception
+ * based on which is higher priority by the usual mechanism
+ * for selecting the highest priority pending interrupt.
+ */
+ }
if (irq >= ARMV7M_EXCP_HARD && irq < ARMV7M_EXCP_PENDSV) {
/* If a synchronous exception is pending then it may be
@@ -585,25 +639,31 @@ void armv7m_nvic_set_pending(void *opaque, int irq, bool secure)
}
}
+void armv7m_nvic_set_pending(void *opaque, int irq, bool secure)
+{
+ do_armv7m_nvic_set_pending(opaque, irq, secure, false);
+}
+
+void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure)
+{
+ do_armv7m_nvic_set_pending(opaque, irq, secure, true);
+}
+
/* Make pending IRQ active. */
-bool armv7m_nvic_acknowledge_irq(void *opaque)
+void armv7m_nvic_acknowledge_irq(void *opaque)
{
NVICState *s = (NVICState *)opaque;
CPUARMState *env = &s->cpu->env;
const int pending = s->vectpending;
const int running = nvic_exec_prio(s);
VecInfo *vec;
- bool targets_secure;
assert(pending > ARMV7M_EXCP_RESET && pending < s->num_irq);
if (s->vectpending_is_s_banked) {
vec = &s->sec_vectors[pending];
- targets_secure = true;
} else {
vec = &s->vectors[pending];
- targets_secure = !exc_is_banked(s->vectpending) &&
- exc_targets_secure(s, s->vectpending);
}
assert(vec->enabled);
@@ -611,7 +671,7 @@ bool armv7m_nvic_acknowledge_irq(void *opaque)
assert(s->vectpending_prio < running);
- trace_nvic_acknowledge_irq(pending, s->vectpending_prio, targets_secure);
+ trace_nvic_acknowledge_irq(pending, s->vectpending_prio);
vec->active = 1;
vec->pending = 0;
@@ -619,8 +679,28 @@ bool armv7m_nvic_acknowledge_irq(void *opaque)
write_v7m_exception(env, s->vectpending);
nvic_irq_update(s);
+}
+
+void armv7m_nvic_get_pending_irq_info(void *opaque,
+ int *pirq, bool *ptargets_secure)
+{
+ NVICState *s = (NVICState *)opaque;
+ const int pending = s->vectpending;
+ bool targets_secure;
+
+ assert(pending > ARMV7M_EXCP_RESET && pending < s->num_irq);
+
+ if (s->vectpending_is_s_banked) {
+ targets_secure = true;
+ } else {
+ targets_secure = !exc_is_banked(pending) &&
+ exc_targets_secure(s, pending);
+ }
+
+ trace_nvic_get_pending_irq_info(pending, targets_secure);
- return targets_secure;
+ *ptargets_secure = targets_secure;
+ *pirq = pending;
}
int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
diff --git a/hw/intc/imx_gpcv2.c b/hw/intc/imx_gpcv2.c
new file mode 100644
index 0000000000..4eb9ce2668
--- /dev/null
+++ b/hw/intc/imx_gpcv2.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2018, Impinj, Inc.
+ *
+ * i.MX7 GPCv2 block emulation code
+ *
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.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 "hw/intc/imx_gpcv2.h"
+#include "qemu/log.h"
+
+#define GPC_PU_PGC_SW_PUP_REQ 0x0f8
+#define GPC_PU_PGC_SW_PDN_REQ 0x104
+
+#define USB_HSIC_PHY_SW_Pxx_REQ BIT(4)
+#define USB_OTG2_PHY_SW_Pxx_REQ BIT(3)
+#define USB_OTG1_PHY_SW_Pxx_REQ BIT(2)
+#define PCIE_PHY_SW_Pxx_REQ BIT(1)
+#define MIPI_PHY_SW_Pxx_REQ BIT(0)
+
+
+static void imx_gpcv2_reset(DeviceState *dev)
+{
+ IMXGPCv2State *s = IMX_GPCV2(dev);
+
+ memset(s->regs, 0, sizeof(s->regs));
+}
+
+static uint64_t imx_gpcv2_read(void *opaque, hwaddr offset,
+ unsigned size)
+{
+ IMXGPCv2State *s = opaque;
+
+ return s->regs[offset / sizeof(uint32_t)];
+}
+
+static void imx_gpcv2_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+ IMXGPCv2State *s = opaque;
+ const size_t idx = offset / sizeof(uint32_t);
+
+ s->regs[idx] = value;
+
+ /*
+ * Real HW will clear those bits once as a way to indicate that
+ * power up request is complete
+ */
+ if (offset == GPC_PU_PGC_SW_PUP_REQ ||
+ offset == GPC_PU_PGC_SW_PDN_REQ) {
+ s->regs[idx] &= ~(USB_HSIC_PHY_SW_Pxx_REQ |
+ USB_OTG2_PHY_SW_Pxx_REQ |
+ USB_OTG1_PHY_SW_Pxx_REQ |
+ PCIE_PHY_SW_Pxx_REQ |
+ MIPI_PHY_SW_Pxx_REQ);
+ }
+}
+
+static const struct MemoryRegionOps imx_gpcv2_ops = {
+ .read = imx_gpcv2_read,
+ .write = imx_gpcv2_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ /*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the real
+ * device but in practice there is no reason for a guest to access
+ * this device unaligned.
+ */
+ .min_access_size = 4,
+ .max_access_size = 4,
+ .unaligned = false,
+ },
+};
+
+static void imx_gpcv2_init(Object *obj)
+{
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+ IMXGPCv2State *s = IMX_GPCV2(obj);
+
+ memory_region_init_io(&s->iomem,
+ obj,
+ &imx_gpcv2_ops,
+ s,
+ TYPE_IMX_GPCV2 ".iomem",
+ sizeof(s->regs));
+ sysbus_init_mmio(sd, &s->iomem);
+}
+
+static const VMStateDescription vmstate_imx_gpcv2 = {
+ .name = TYPE_IMX_GPCV2,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(regs, IMXGPCv2State, GPC_NUM),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static void imx_gpcv2_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = imx_gpcv2_reset;
+ dc->vmsd = &vmstate_imx_gpcv2;
+ dc->desc = "i.MX GPCv2 Module";
+}
+
+static const TypeInfo imx_gpcv2_info = {
+ .name = TYPE_IMX_GPCV2,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IMXGPCv2State),
+ .instance_init = imx_gpcv2_init,
+ .class_init = imx_gpcv2_class_init,
+};
+
+static void imx_gpcv2_register_type(void)
+{
+ type_register_static(&imx_gpcv2_info);
+}
+type_init(imx_gpcv2_register_type)
diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
index 6eaf178d79..a85a149c6d 100644
--- a/hw/intc/s390_flic.c
+++ b/hw/intc/s390_flic.c
@@ -22,16 +22,36 @@
#include "qapi/error.h"
#include "hw/s390x/s390-virtio-ccw.h"
+S390FLICStateClass *s390_get_flic_class(S390FLICState *fs)
+{
+ static S390FLICStateClass *class;
+
+ if (!class) {
+ /* we only have one flic device, so this is fine to cache */
+ class = S390_FLIC_COMMON_GET_CLASS(fs);
+ }
+ return class;
+}
+
+QEMUS390FLICState *s390_get_qemu_flic(S390FLICState *fs)
+{
+ static QEMUS390FLICState *flic;
+
+ if (!flic) {
+ /* we only have one flic device, so this is fine to cache */
+ flic = QEMU_S390_FLIC(fs);
+ }
+ return flic;
+}
+
S390FLICState *s390_get_flic(void)
{
static S390FLICState *fs;
if (!fs) {
- fs = S390_FLIC_COMMON(object_resolve_path(TYPE_KVM_S390_FLIC, NULL));
- if (!fs) {
- fs = S390_FLIC_COMMON(object_resolve_path(TYPE_QEMU_S390_FLIC,
- NULL));
- }
+ fs = S390_FLIC_COMMON(object_resolve_path_type("",
+ TYPE_S390_FLIC_COMMON,
+ NULL));
}
return fs;
}
@@ -40,8 +60,11 @@ void s390_flic_init(void)
{
DeviceState *dev;
- dev = s390_flic_kvm_create();
- if (!dev) {
+ if (kvm_enabled()) {
+ dev = qdev_create(NULL, TYPE_KVM_S390_FLIC);
+ object_property_add_child(qdev_get_machine(), TYPE_KVM_S390_FLIC,
+ OBJECT(dev), NULL);
+ } else {
dev = qdev_create(NULL, TYPE_QEMU_S390_FLIC);
object_property_add_child(qdev_get_machine(), TYPE_QEMU_S390_FLIC,
OBJECT(dev), NULL);
@@ -78,14 +101,41 @@ static void qemu_s390_release_adapter_routes(S390FLICState *fs,
static int qemu_s390_clear_io_flic(S390FLICState *fs, uint16_t subchannel_id,
uint16_t subchannel_nr)
{
- /* Fixme TCG */
- return -ENOSYS;
+ QEMUS390FLICState *flic = s390_get_qemu_flic(fs);
+ QEMUS390FlicIO *cur, *next;
+ uint8_t isc;
+
+ g_assert(qemu_mutex_iothread_locked());
+ if (!(flic->pending & FLIC_PENDING_IO)) {
+ return 0;
+ }
+
+ /* check all iscs */
+ for (isc = 0; isc < 8; isc++) {
+ if (QLIST_EMPTY(&flic->io[isc])) {
+ continue;
+ }
+
+ /* search and delete any matching one */
+ QLIST_FOREACH_SAFE(cur, &flic->io[isc], next, next) {
+ if (cur->id == subchannel_id && cur->nr == subchannel_nr) {
+ QLIST_REMOVE(cur, next);
+ g_free(cur);
+ }
+ }
+
+ /* update our indicator bit */
+ if (QLIST_EMPTY(&flic->io[isc])) {
+ flic->pending &= ~ISC_TO_PENDING_IO(isc);
+ }
+ }
+ return 0;
}
static int qemu_s390_modify_ais_mode(S390FLICState *fs, uint8_t isc,
uint16_t mode)
{
- QEMUS390FLICState *flic = QEMU_S390_FLIC(fs);
+ QEMUS390FLICState *flic = s390_get_qemu_flic(fs);
switch (mode) {
case SIC_IRQ_MODE_ALL:
@@ -106,7 +156,8 @@ static int qemu_s390_modify_ais_mode(S390FLICState *fs, uint8_t isc,
static int qemu_s390_inject_airq(S390FLICState *fs, uint8_t type,
uint8_t isc, uint8_t flags)
{
- QEMUS390FLICState *flic = QEMU_S390_FLIC(fs);
+ QEMUS390FLICState *flic = s390_get_qemu_flic(fs);
+ S390FLICStateClass *fsc = s390_get_flic_class(fs);
bool flag = flags & S390_ADAPTER_SUPPRESSIBLE;
uint32_t io_int_word = (isc << 27) | IO_INT_WORD_AI;
@@ -115,7 +166,7 @@ static int qemu_s390_inject_airq(S390FLICState *fs, uint8_t type,
return 0;
}
- s390_io_interrupt(0, 0, 0, io_int_word);
+ fsc->inject_io(fs, 0, 0, 0, io_int_word);
if (flag && (flic->simm & AIS_MODE_MASK(isc))) {
flic->nimm |= AIS_MODE_MASK(isc);
@@ -126,12 +177,180 @@ static int qemu_s390_inject_airq(S390FLICState *fs, uint8_t type,
return 0;
}
+static void qemu_s390_flic_notify(uint32_t type)
+{
+ CPUState *cs;
+
+ /*
+ * We have to make all CPUs see CPU_INTERRUPT_HARD, so they might
+ * consider it. We will kick all running CPUs and only relevant
+ * sleeping ones.
+ */
+ CPU_FOREACH(cs) {
+ S390CPU *cpu = S390_CPU(cs);
+
+ cs->interrupt_request |= CPU_INTERRUPT_HARD;
+
+ /* ignore CPUs that are not sleeping */
+ if (s390_cpu_get_state(cpu) != CPU_STATE_OPERATING &&
+ s390_cpu_get_state(cpu) != CPU_STATE_LOAD) {
+ continue;
+ }
+
+ /* we always kick running CPUs for now, this is tricky */
+ if (cs->halted) {
+ /* don't check for subclasses, CPUs double check when waking up */
+ if (type & FLIC_PENDING_SERVICE) {
+ if (!(cpu->env.psw.mask & PSW_MASK_EXT)) {
+ continue;
+ }
+ } else if (type & FLIC_PENDING_IO) {
+ if (!(cpu->env.psw.mask & PSW_MASK_IO)) {
+ continue;
+ }
+ } else if (type & FLIC_PENDING_MCHK_CR) {
+ if (!(cpu->env.psw.mask & PSW_MASK_MCHECK)) {
+ continue;
+ }
+ }
+ }
+ cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+ }
+}
+
+uint32_t qemu_s390_flic_dequeue_service(QEMUS390FLICState *flic)
+{
+ uint32_t tmp;
+
+ g_assert(qemu_mutex_iothread_locked());
+ g_assert(flic->pending & FLIC_PENDING_SERVICE);
+ tmp = flic->service_param;
+ flic->service_param = 0;
+ flic->pending &= ~FLIC_PENDING_SERVICE;
+
+ return tmp;
+}
+
+/* caller has to free the returned object */
+QEMUS390FlicIO *qemu_s390_flic_dequeue_io(QEMUS390FLICState *flic, uint64_t cr6)
+{
+ QEMUS390FlicIO *io;
+ uint8_t isc;
+
+ g_assert(qemu_mutex_iothread_locked());
+ if (!(flic->pending & CR6_TO_PENDING_IO(cr6))) {
+ return NULL;
+ }
+
+ for (isc = 0; isc < 8; isc++) {
+ if (QLIST_EMPTY(&flic->io[isc]) || !(cr6 & ISC_TO_ISC_BITS(isc))) {
+ continue;
+ }
+ io = QLIST_FIRST(&flic->io[isc]);
+ QLIST_REMOVE(io, next);
+
+ /* update our indicator bit */
+ if (QLIST_EMPTY(&flic->io[isc])) {
+ flic->pending &= ~ISC_TO_PENDING_IO(isc);
+ }
+ return io;
+ }
+
+ return NULL;
+}
+
+void qemu_s390_flic_dequeue_crw_mchk(QEMUS390FLICState *flic)
+{
+ g_assert(qemu_mutex_iothread_locked());
+ g_assert(flic->pending & FLIC_PENDING_MCHK_CR);
+ flic->pending &= ~FLIC_PENDING_MCHK_CR;
+}
+
+static void qemu_s390_inject_service(S390FLICState *fs, uint32_t parm)
+{
+ QEMUS390FLICState *flic = s390_get_qemu_flic(fs);
+
+ g_assert(qemu_mutex_iothread_locked());
+ /* multiplexing is good enough for sclp - kvm does it internally as well */
+ flic->service_param |= parm;
+ flic->pending |= FLIC_PENDING_SERVICE;
+
+ qemu_s390_flic_notify(FLIC_PENDING_SERVICE);
+}
+
+static void qemu_s390_inject_io(S390FLICState *fs, uint16_t subchannel_id,
+ uint16_t subchannel_nr, uint32_t io_int_parm,
+ uint32_t io_int_word)
+{
+ const uint8_t isc = IO_INT_WORD_ISC(io_int_word);
+ QEMUS390FLICState *flic = s390_get_qemu_flic(fs);
+ QEMUS390FlicIO *io;
+
+ g_assert(qemu_mutex_iothread_locked());
+ io = g_new0(QEMUS390FlicIO, 1);
+ io->id = subchannel_id;
+ io->nr = subchannel_nr;
+ io->parm = io_int_parm;
+ io->word = io_int_word;
+
+ QLIST_INSERT_HEAD(&flic->io[isc], io, next);
+ flic->pending |= ISC_TO_PENDING_IO(isc);
+
+ qemu_s390_flic_notify(ISC_TO_PENDING_IO(isc));
+}
+
+static void qemu_s390_inject_crw_mchk(S390FLICState *fs)
+{
+ QEMUS390FLICState *flic = s390_get_qemu_flic(fs);
+
+ g_assert(qemu_mutex_iothread_locked());
+ flic->pending |= FLIC_PENDING_MCHK_CR;
+
+ qemu_s390_flic_notify(FLIC_PENDING_MCHK_CR);
+}
+
+bool qemu_s390_flic_has_service(QEMUS390FLICState *flic)
+{
+ /* called without lock via cc->has_work, will be validated under lock */
+ return !!(flic->pending & FLIC_PENDING_SERVICE);
+}
+
+bool qemu_s390_flic_has_io(QEMUS390FLICState *flic, uint64_t cr6)
+{
+ /* called without lock via cc->has_work, will be validated under lock */
+ return !!(flic->pending & CR6_TO_PENDING_IO(cr6));
+}
+
+bool qemu_s390_flic_has_crw_mchk(QEMUS390FLICState *flic)
+{
+ /* called without lock via cc->has_work, will be validated under lock */
+ return !!(flic->pending & FLIC_PENDING_MCHK_CR);
+}
+
+bool qemu_s390_flic_has_any(QEMUS390FLICState *flic)
+{
+ g_assert(qemu_mutex_iothread_locked());
+ return !!flic->pending;
+}
+
static void qemu_s390_flic_reset(DeviceState *dev)
{
QEMUS390FLICState *flic = QEMU_S390_FLIC(dev);
+ QEMUS390FlicIO *cur, *next;
+ int isc;
+ g_assert(qemu_mutex_iothread_locked());
flic->simm = 0;
flic->nimm = 0;
+ flic->pending = 0;
+
+ /* remove all pending io interrupts */
+ for (isc = 0; isc < 8; isc++) {
+ QLIST_FOREACH_SAFE(cur, &flic->io[isc], next, next) {
+ QLIST_REMOVE(cur, next);
+ g_free(cur);
+ }
+ }
}
bool ais_needed(void *opaque)
@@ -153,6 +372,16 @@ static const VMStateDescription qemu_s390_flic_vmstate = {
}
};
+static void qemu_s390_flic_instance_init(Object *obj)
+{
+ QEMUS390FLICState *flic = QEMU_S390_FLIC(obj);
+ int isc;
+
+ for (isc = 0; isc < 8; isc++) {
+ QLIST_INIT(&flic->io[isc]);
+ }
+}
+
static void qemu_s390_flic_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
@@ -167,6 +396,9 @@ static void qemu_s390_flic_class_init(ObjectClass *oc, void *data)
fsc->clear_io_irq = qemu_s390_clear_io_flic;
fsc->modify_ais_mode = qemu_s390_modify_ais_mode;
fsc->inject_airq = qemu_s390_inject_airq;
+ fsc->inject_service = qemu_s390_inject_service;
+ fsc->inject_io = qemu_s390_inject_io;
+ fsc->inject_crw_mchk = qemu_s390_inject_crw_mchk;
}
static Property s390_flic_common_properties[] = {
@@ -201,6 +433,7 @@ static const TypeInfo qemu_s390_flic_info = {
.name = TYPE_QEMU_S390_FLIC,
.parent = TYPE_S390_FLIC_COMMON,
.instance_size = sizeof(QEMUS390FLICState),
+ .instance_init = qemu_s390_flic_instance_init,
.class_init = qemu_s390_flic_class_init,
};
diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c
index d208cb81c4..3f804ad52e 100644
--- a/hw/intc/s390_flic_kvm.c
+++ b/hw/intc/s390_flic_kvm.c
@@ -35,16 +35,15 @@ typedef struct KVMS390FLICState {
bool clear_io_supported;
} KVMS390FLICState;
-DeviceState *s390_flic_kvm_create(void)
+static KVMS390FLICState *s390_get_kvm_flic(S390FLICState *fs)
{
- DeviceState *dev = NULL;
+ static KVMS390FLICState *flic;
- if (kvm_enabled()) {
- dev = qdev_create(NULL, TYPE_KVM_S390_FLIC);
- object_property_add_child(qdev_get_machine(), TYPE_KVM_S390_FLIC,
- OBJECT(dev), NULL);
+ if (!flic) {
+ /* we only have one flic device, so this is fine to cache */
+ flic = KVM_S390_FLIC(fs);
}
- return dev;
+ return flic;
}
/**
@@ -123,20 +122,70 @@ static int flic_enqueue_irqs(void *buf, uint64_t len,
return rc ? -errno : 0;
}
-int kvm_s390_inject_flic(struct kvm_s390_irq *irq)
+static void kvm_s390_inject_flic(S390FLICState *fs, struct kvm_s390_irq *irq)
{
- static KVMS390FLICState *flic;
+ static bool use_flic = true;
+ int r;
+
+ if (use_flic) {
+ r = flic_enqueue_irqs(irq, sizeof(*irq), s390_get_kvm_flic(fs));
+ if (r == -ENOSYS) {
+ use_flic = false;
+ }
+ if (!r) {
+ return;
+ }
+ }
+ /* fallback to legacy KVM IOCTL in case FLIC fails */
+ kvm_s390_floating_interrupt_legacy(irq);
+}
+
+static void kvm_s390_inject_service(S390FLICState *fs, uint32_t parm)
+{
+ struct kvm_s390_irq irq = {
+ .type = KVM_S390_INT_SERVICE,
+ .u.ext.ext_params = parm,
+ };
+
+ kvm_s390_inject_flic(fs, &irq);
+}
- if (unlikely(!flic)) {
- flic = KVM_S390_FLIC(s390_get_flic());
+static void kvm_s390_inject_io(S390FLICState *fs, uint16_t subchannel_id,
+ uint16_t subchannel_nr, uint32_t io_int_parm,
+ uint32_t io_int_word)
+{
+ struct kvm_s390_irq irq = {
+ .u.io.subchannel_id = subchannel_id,
+ .u.io.subchannel_nr = subchannel_nr,
+ .u.io.io_int_parm = io_int_parm,
+ .u.io.io_int_word = io_int_word,
+ };
+
+ if (io_int_word & IO_INT_WORD_AI) {
+ irq.type = KVM_S390_INT_IO(1, 0, 0, 0);
+ } else {
+ irq.type = KVM_S390_INT_IO(0, (subchannel_id & 0xff00) >> 8,
+ (subchannel_id & 0x0006),
+ subchannel_nr);
}
- return flic_enqueue_irqs(irq, sizeof(*irq), flic);
+ kvm_s390_inject_flic(fs, &irq);
+}
+
+static void kvm_s390_inject_crw_mchk(S390FLICState *fs)
+{
+ struct kvm_s390_irq irq = {
+ .type = KVM_S390_MCHK,
+ .u.mchk.cr14 = CR14_CHANNEL_REPORT_SC,
+ .u.mchk.mcic = s390_build_validity_mcic() | MCIC_SC_CP,
+ };
+
+ kvm_s390_inject_flic(fs, &irq);
}
static int kvm_s390_clear_io_flic(S390FLICState *fs, uint16_t subchannel_id,
uint16_t subchannel_nr)
{
- KVMS390FLICState *flic = KVM_S390_FLIC(fs);
+ KVMS390FLICState *flic = s390_get_kvm_flic(fs);
int rc;
uint32_t sid = subchannel_id << 16 | subchannel_nr;
struct kvm_device_attr attr = {
@@ -154,7 +203,7 @@ static int kvm_s390_clear_io_flic(S390FLICState *fs, uint16_t subchannel_id,
static int kvm_s390_modify_ais_mode(S390FLICState *fs, uint8_t isc,
uint16_t mode)
{
- KVMS390FLICState *flic = KVM_S390_FLIC(fs);
+ KVMS390FLICState *flic = s390_get_kvm_flic(fs);
struct kvm_s390_ais_req req = {
.isc = isc,
.mode = mode,
@@ -174,7 +223,7 @@ static int kvm_s390_modify_ais_mode(S390FLICState *fs, uint8_t isc,
static int kvm_s390_inject_airq(S390FLICState *fs, uint8_t type,
uint8_t isc, uint8_t flags)
{
- KVMS390FLICState *flic = KVM_S390_FLIC(fs);
+ KVMS390FLICState *flic = s390_get_kvm_flic(fs);
uint32_t id = css_get_adapter_id(type, isc);
struct kvm_device_attr attr = {
.group = KVM_DEV_FLIC_AIRQ_INJECT,
@@ -263,7 +312,7 @@ static int kvm_s390_io_adapter_map(S390FLICState *fs, uint32_t id,
.group = KVM_DEV_FLIC_ADAPTER_MODIFY,
.addr = (uint64_t)&req,
};
- KVMS390FLICState *flic = KVM_S390_FLIC(fs);
+ KVMS390FLICState *flic = s390_get_kvm_flic(fs);
int r;
if (!kvm_gsi_routing_enabled()) {
@@ -614,6 +663,9 @@ static void kvm_s390_flic_class_init(ObjectClass *oc, void *data)
fsc->clear_io_irq = kvm_s390_clear_io_flic;
fsc->modify_ais_mode = kvm_s390_modify_ais_mode;
fsc->inject_airq = kvm_s390_inject_airq;
+ fsc->inject_service = kvm_s390_inject_service;
+ fsc->inject_io = kvm_s390_inject_io;
+ fsc->inject_crw_mchk = kvm_s390_inject_crw_mchk;
}
static const TypeInfo kvm_s390_flic_info = {
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index be769186fc..4092d2825e 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -177,10 +177,11 @@ nvic_set_prio(int irq, bool secure, uint8_t prio) "NVIC set irq %d secure-bank %
nvic_irq_update(int vectpending, int pendprio, int exception_prio, int level) "NVIC vectpending %d pending prio %d exception_prio %d: setting irq line to %d"
nvic_escalate_prio(int irq, int irqprio, int runprio) "NVIC escalating irq %d to HardFault: insufficient priority %d >= %d"
nvic_escalate_disabled(int irq) "NVIC escalating irq %d to HardFault: disabled"
-nvic_set_pending(int irq, bool secure, int en, int prio) "NVIC set pending irq %d secure-bank %d (enabled: %d priority %d)"
+nvic_set_pending(int irq, bool secure, bool derived, int en, int prio) "NVIC set pending irq %d secure-bank %d derived %d (enabled: %d priority %d)"
nvic_clear_pending(int irq, bool secure, int en, int prio) "NVIC clear pending irq %d secure-bank %d (enabled: %d priority %d)"
nvic_set_pending_level(int irq) "NVIC set pending: irq %d higher prio than vectpending: setting irq line to 1"
-nvic_acknowledge_irq(int irq, int prio, bool targets_secure) "NVIC acknowledge IRQ: %d now active (prio %d targets_secure %d)"
+nvic_acknowledge_irq(int irq, int prio) "NVIC acknowledge IRQ: %d now active (prio %d)"
+nvic_get_pending_irq_info(int irq, bool secure) "NVIC next IRQ %d: targets_secure: %d"
nvic_complete_irq(int irq, bool secure) "NVIC complete IRQ %d (secure %d)"
nvic_set_irq_level(int irq, int level) "NVIC external irq %d level set to %d"
nvic_sysreg_read(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
diff --git a/hw/intc/xics_pnv.c b/hw/intc/xics_pnv.c
index 2a955a8946..c87de2189c 100644
--- a/hw/intc/xics_pnv.c
+++ b/hw/intc/xics_pnv.c
@@ -19,7 +19,6 @@
#include "qemu/osdep.h"
#include "sysemu/sysemu.h"
-#include "qapi/error.h"
#include "qemu/log.h"
#include "hw/ppc/xics.h"
diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
index 5a0967caf4..2e27b92b87 100644
--- a/hw/intc/xics_spapr.c
+++ b/hw/intc/xics_spapr.c
@@ -34,7 +34,6 @@
#include "hw/ppc/xics.h"
#include "hw/ppc/fdt.h"
#include "qapi/visitor.h"
-#include "qapi/error.h"
/*
* Guest interfaces
diff --git a/hw/ipmi/ipmi.c b/hw/ipmi/ipmi.c
index b27babd504..adbbf6e4a6 100644
--- a/hw/ipmi/ipmi.c
+++ b/hw/ipmi/ipmi.c
@@ -28,6 +28,7 @@
#include "sysemu/sysemu.h"
#include "qmp-commands.h"
#include "qom/object_interfaces.h"
+#include "qapi/error.h"
#include "qapi/visitor.h"
static uint32_t ipmi_current_uuid = 1;
diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
index 596f3c210e..b09871a814 100644
--- a/hw/mips/mips_jazz.c
+++ b/hw/mips/mips_jazz.c
@@ -45,6 +45,7 @@
#include "hw/sysbus.h"
#include "exec/address-spaces.h"
#include "sysemu/qtest.h"
+#include "qapi/error.h"
#include "qemu/error-report.h"
#include "qemu/help_option.h"
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index 7ca8ba2086..6f0deb99e7 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -51,6 +51,7 @@
#include "hw/sysbus.h" /* SysBusDevice */
#include "qemu/host-utils.h"
#include "sysemu/qtest.h"
+#include "qapi/error.h"
#include "qemu/error-report.h"
#include "hw/empty_slot.h"
#include "sysemu/kvm.h"
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index d517f83e81..f33b37a8e5 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -17,6 +17,9 @@ common-obj-$(CONFIG_INTEGRATOR_DEBUG) += arm_integrator_debug.o
common-obj-$(CONFIG_A9SCU) += a9scu.o
common-obj-$(CONFIG_ARM11SCU) += arm11scu.o
+# Mac devices
+common-obj-$(CONFIG_MOS6522) += mos6522.o
+
# PKUnity SoC devices
common-obj-$(CONFIG_PUV3) += puv3_pm.o
@@ -33,6 +36,10 @@ obj-$(CONFIG_IMX) += imx31_ccm.o
obj-$(CONFIG_IMX) += imx25_ccm.o
obj-$(CONFIG_IMX) += imx6_ccm.o
obj-$(CONFIG_IMX) += imx6_src.o
+obj-$(CONFIG_IMX) += imx7_ccm.o
+obj-$(CONFIG_IMX) += imx2_wdt.o
+obj-$(CONFIG_IMX) += imx7_snvs.o
+obj-$(CONFIG_IMX) += imx7_gpr.o
obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
obj-$(CONFIG_MAINSTONE) += mst_fpga.o
diff --git a/hw/misc/exynos4210_rng.c b/hw/misc/exynos4210_rng.c
index 31ebe38e26..4ecbebd2d7 100644
--- a/hw/misc/exynos4210_rng.c
+++ b/hw/misc/exynos4210_rng.c
@@ -20,6 +20,7 @@
#include "qemu/osdep.h"
#include "crypto/random.h"
#include "hw/sysbus.h"
+#include "qapi/error.h"
#include "qemu/log.h"
#define DEBUG_EXYNOS_RNG 0
diff --git a/hw/misc/imx2_wdt.c b/hw/misc/imx2_wdt.c
new file mode 100644
index 0000000000..e47e442592
--- /dev/null
+++ b/hw/misc/imx2_wdt.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2018, Impinj, Inc.
+ *
+ * i.MX2 Watchdog IP block
+ *
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.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/bitops.h"
+#include "sysemu/watchdog.h"
+
+#include "hw/misc/imx2_wdt.h"
+
+#define IMX2_WDT_WCR_WDA BIT(5) /* -> External Reset WDOG_B */
+#define IMX2_WDT_WCR_SRS BIT(4) /* -> Software Reset Signal */
+
+static uint64_t imx2_wdt_read(void *opaque, hwaddr addr,
+ unsigned int size)
+{
+ return 0;
+}
+
+static void imx2_wdt_write(void *opaque, hwaddr addr,
+ uint64_t value, unsigned int size)
+{
+ if (addr == IMX2_WDT_WCR &&
+ (value & (IMX2_WDT_WCR_WDA | IMX2_WDT_WCR_SRS))) {
+ watchdog_perform_action();
+ }
+}
+
+static const MemoryRegionOps imx2_wdt_ops = {
+ .read = imx2_wdt_read,
+ .write = imx2_wdt_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ /*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the
+ * real device but in practice there is no reason for a guest
+ * to access this device unaligned.
+ */
+ .min_access_size = 4,
+ .max_access_size = 4,
+ .unaligned = false,
+ },
+};
+
+static void imx2_wdt_realize(DeviceState *dev, Error **errp)
+{
+ IMX2WdtState *s = IMX2_WDT(dev);
+
+ memory_region_init_io(&s->mmio, OBJECT(dev),
+ &imx2_wdt_ops, s,
+ TYPE_IMX2_WDT".mmio",
+ IMX2_WDT_REG_NUM * sizeof(uint16_t));
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
+}
+
+static void imx2_wdt_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = imx2_wdt_realize;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+}
+
+static const TypeInfo imx2_wdt_info = {
+ .name = TYPE_IMX2_WDT,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IMX2WdtState),
+ .class_init = imx2_wdt_class_init,
+};
+
+static WatchdogTimerModel model = {
+ .wdt_name = "imx2-watchdog",
+ .wdt_description = "i.MX2 Watchdog",
+};
+
+static void imx2_wdt_register_type(void)
+{
+ watchdog_add_model(&model);
+ type_register_static(&imx2_wdt_info);
+}
+type_init(imx2_wdt_register_type)
diff --git a/hw/misc/imx7_ccm.c b/hw/misc/imx7_ccm.c
new file mode 100644
index 0000000000..d90c48bfec
--- /dev/null
+++ b/hw/misc/imx7_ccm.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2018, Impinj, Inc.
+ *
+ * i.MX7 CCM, PMU and ANALOG IP blocks emulation code
+ *
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.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/log.h"
+
+#include "hw/misc/imx7_ccm.h"
+
+static void imx7_analog_reset(DeviceState *dev)
+{
+ IMX7AnalogState *s = IMX7_ANALOG(dev);
+
+ memset(s->pmu, 0, sizeof(s->pmu));
+ memset(s->analog, 0, sizeof(s->analog));
+
+ s->analog[ANALOG_PLL_ARM] = 0x00002042;
+ s->analog[ANALOG_PLL_DDR] = 0x0060302c;
+ s->analog[ANALOG_PLL_DDR_SS] = 0x00000000;
+ s->analog[ANALOG_PLL_DDR_NUM] = 0x06aaac4d;
+ s->analog[ANALOG_PLL_DDR_DENOM] = 0x100003ec;
+ s->analog[ANALOG_PLL_480] = 0x00002000;
+ s->analog[ANALOG_PLL_480A] = 0x52605a56;
+ s->analog[ANALOG_PLL_480B] = 0x52525216;
+ s->analog[ANALOG_PLL_ENET] = 0x00001fc0;
+ s->analog[ANALOG_PLL_AUDIO] = 0x0001301b;
+ s->analog[ANALOG_PLL_AUDIO_SS] = 0x00000000;
+ s->analog[ANALOG_PLL_AUDIO_NUM] = 0x05f5e100;
+ s->analog[ANALOG_PLL_AUDIO_DENOM] = 0x2964619c;
+ s->analog[ANALOG_PLL_VIDEO] = 0x0008201b;
+ s->analog[ANALOG_PLL_VIDEO_SS] = 0x00000000;
+ s->analog[ANALOG_PLL_VIDEO_NUM] = 0x0000f699;
+ s->analog[ANALOG_PLL_VIDEO_DENOM] = 0x000f4240;
+ s->analog[ANALOG_PLL_MISC0] = 0x00000000;
+
+ /* all PLLs need to be locked */
+ s->analog[ANALOG_PLL_ARM] |= ANALOG_PLL_LOCK;
+ s->analog[ANALOG_PLL_DDR] |= ANALOG_PLL_LOCK;
+ s->analog[ANALOG_PLL_480] |= ANALOG_PLL_LOCK;
+ s->analog[ANALOG_PLL_480A] |= ANALOG_PLL_LOCK;
+ s->analog[ANALOG_PLL_480B] |= ANALOG_PLL_LOCK;
+ s->analog[ANALOG_PLL_ENET] |= ANALOG_PLL_LOCK;
+ s->analog[ANALOG_PLL_AUDIO] |= ANALOG_PLL_LOCK;
+ s->analog[ANALOG_PLL_VIDEO] |= ANALOG_PLL_LOCK;
+ s->analog[ANALOG_PLL_MISC0] |= ANALOG_PLL_LOCK;
+
+ /*
+ * Since I couldn't find any info about this in the reference
+ * manual the value of this register is based strictly on matching
+ * what Linux kernel expects it to be.
+ */
+ s->analog[ANALOG_DIGPROG] = 0x720000;
+ /*
+ * Set revision to be 1.0 (Arbitrary choice, no particular
+ * reason).
+ */
+ s->analog[ANALOG_DIGPROG] |= 0x000010;
+}
+
+static void imx7_ccm_reset(DeviceState *dev)
+{
+ IMX7CCMState *s = IMX7_CCM(dev);
+
+ memset(s->ccm, 0, sizeof(s->ccm));
+}
+
+#define CCM_INDEX(offset) (((offset) & ~(hwaddr)0xF) / sizeof(uint32_t))
+#define CCM_BITOP(offset) ((offset) & (hwaddr)0xF)
+
+enum {
+ CCM_BITOP_NONE = 0x00,
+ CCM_BITOP_SET = 0x04,
+ CCM_BITOP_CLR = 0x08,
+ CCM_BITOP_TOG = 0x0C,
+};
+
+static uint64_t imx7_set_clr_tog_read(void *opaque, hwaddr offset,
+ unsigned size)
+{
+ const uint32_t *mmio = opaque;
+
+ return mmio[CCM_INDEX(offset)];
+}
+
+static void imx7_set_clr_tog_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+ const uint8_t bitop = CCM_BITOP(offset);
+ const uint32_t index = CCM_INDEX(offset);
+ uint32_t *mmio = opaque;
+
+ switch (bitop) {
+ case CCM_BITOP_NONE:
+ mmio[index] = value;
+ break;
+ case CCM_BITOP_SET:
+ mmio[index] |= value;
+ break;
+ case CCM_BITOP_CLR:
+ mmio[index] &= ~value;
+ break;
+ case CCM_BITOP_TOG:
+ mmio[index] ^= value;
+ break;
+ };
+}
+
+static const struct MemoryRegionOps imx7_set_clr_tog_ops = {
+ .read = imx7_set_clr_tog_read,
+ .write = imx7_set_clr_tog_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ /*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the real
+ * device but in practice there is no reason for a guest to access
+ * this device unaligned.
+ */
+ .min_access_size = 4,
+ .max_access_size = 4,
+ .unaligned = false,
+ },
+};
+
+static const struct MemoryRegionOps imx7_digprog_ops = {
+ .read = imx7_set_clr_tog_read,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ .unaligned = false,
+ },
+};
+
+static void imx7_ccm_init(Object *obj)
+{
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+ IMX7CCMState *s = IMX7_CCM(obj);
+
+ memory_region_init_io(&s->iomem,
+ obj,
+ &imx7_set_clr_tog_ops,
+ s->ccm,
+ TYPE_IMX7_CCM ".ccm",
+ sizeof(s->ccm));
+
+ sysbus_init_mmio(sd, &s->iomem);
+}
+
+static void imx7_analog_init(Object *obj)
+{
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+ IMX7AnalogState *s = IMX7_ANALOG(obj);
+
+ memory_region_init(&s->mmio.container, obj, TYPE_IMX7_ANALOG,
+ 0x10000);
+
+ memory_region_init_io(&s->mmio.analog,
+ obj,
+ &imx7_set_clr_tog_ops,
+ s->analog,
+ TYPE_IMX7_ANALOG,
+ sizeof(s->analog));
+
+ memory_region_add_subregion(&s->mmio.container,
+ 0x60, &s->mmio.analog);
+
+ memory_region_init_io(&s->mmio.pmu,
+ obj,
+ &imx7_set_clr_tog_ops,
+ s->pmu,
+ TYPE_IMX7_ANALOG ".pmu",
+ sizeof(s->pmu));
+
+ memory_region_add_subregion(&s->mmio.container,
+ 0x200, &s->mmio.pmu);
+
+ memory_region_init_io(&s->mmio.digprog,
+ obj,
+ &imx7_digprog_ops,
+ &s->analog[ANALOG_DIGPROG],
+ TYPE_IMX7_ANALOG ".digprog",
+ sizeof(uint32_t));
+
+ memory_region_add_subregion_overlap(&s->mmio.container,
+ 0x800, &s->mmio.digprog, 10);
+
+
+ sysbus_init_mmio(sd, &s->mmio.container);
+}
+
+static const VMStateDescription vmstate_imx7_ccm = {
+ .name = TYPE_IMX7_CCM,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(ccm, IMX7CCMState, CCM_MAX),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static uint32_t imx7_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
+{
+ /*
+ * This function is "consumed" by GPT emulation code, however on
+ * i.MX7 each GPT block can have their own clock root. This means
+ * that this functions needs somehow to know requester's identity
+ * and the way to pass it: be it via additional IMXClk constants
+ * or by adding another argument to this method needs to be
+ * figured out
+ */
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Not implemented\n",
+ TYPE_IMX7_CCM, __func__);
+ return 0;
+}
+
+static void imx7_ccm_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
+
+ dc->reset = imx7_ccm_reset;
+ dc->vmsd = &vmstate_imx7_ccm;
+ dc->desc = "i.MX7 Clock Control Module";
+
+ ccm->get_clock_frequency = imx7_ccm_get_clock_frequency;
+}
+
+static const TypeInfo imx7_ccm_info = {
+ .name = TYPE_IMX7_CCM,
+ .parent = TYPE_IMX_CCM,
+ .instance_size = sizeof(IMX7CCMState),
+ .instance_init = imx7_ccm_init,
+ .class_init = imx7_ccm_class_init,
+};
+
+static const VMStateDescription vmstate_imx7_analog = {
+ .name = TYPE_IMX7_ANALOG,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(analog, IMX7AnalogState, ANALOG_MAX),
+ VMSTATE_UINT32_ARRAY(pmu, IMX7AnalogState, PMU_MAX),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static void imx7_analog_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = imx7_analog_reset;
+ dc->vmsd = &vmstate_imx7_analog;
+ dc->desc = "i.MX7 Analog Module";
+}
+
+static const TypeInfo imx7_analog_info = {
+ .name = TYPE_IMX7_ANALOG,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IMX7AnalogState),
+ .instance_init = imx7_analog_init,
+ .class_init = imx7_analog_class_init,
+};
+
+static void imx7_ccm_register_type(void)
+{
+ type_register_static(&imx7_ccm_info);
+ type_register_static(&imx7_analog_info);
+}
+type_init(imx7_ccm_register_type)
diff --git a/hw/misc/imx7_gpr.c b/hw/misc/imx7_gpr.c
new file mode 100644
index 0000000000..c2a9df29c6
--- /dev/null
+++ b/hw/misc/imx7_gpr.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2018, Impinj, Inc.
+ *
+ * i.MX7 GPR IP block emulation code
+ *
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.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.
+ *
+ * Bare minimum emulation code needed to support being able to shut
+ * down linux guest gracefully.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/misc/imx7_gpr.h"
+#include "qemu/log.h"
+#include "sysemu/sysemu.h"
+
+#include "trace.h"
+
+enum IMX7GPRRegisters {
+ IOMUXC_GPR0 = 0x00,
+ IOMUXC_GPR1 = 0x04,
+ IOMUXC_GPR2 = 0x08,
+ IOMUXC_GPR3 = 0x0c,
+ IOMUXC_GPR4 = 0x10,
+ IOMUXC_GPR5 = 0x14,
+ IOMUXC_GPR6 = 0x18,
+ IOMUXC_GPR7 = 0x1c,
+ IOMUXC_GPR8 = 0x20,
+ IOMUXC_GPR9 = 0x24,
+ IOMUXC_GPR10 = 0x28,
+ IOMUXC_GPR11 = 0x2c,
+ IOMUXC_GPR12 = 0x30,
+ IOMUXC_GPR13 = 0x34,
+ IOMUXC_GPR14 = 0x38,
+ IOMUXC_GPR15 = 0x3c,
+ IOMUXC_GPR16 = 0x40,
+ IOMUXC_GPR17 = 0x44,
+ IOMUXC_GPR18 = 0x48,
+ IOMUXC_GPR19 = 0x4c,
+ IOMUXC_GPR20 = 0x50,
+ IOMUXC_GPR21 = 0x54,
+ IOMUXC_GPR22 = 0x58,
+};
+
+#define IMX7D_GPR1_IRQ_MASK BIT(12)
+#define IMX7D_GPR1_ENET1_TX_CLK_SEL_MASK BIT(13)
+#define IMX7D_GPR1_ENET2_TX_CLK_SEL_MASK BIT(14)
+#define IMX7D_GPR1_ENET_TX_CLK_SEL_MASK (0x3 << 13)
+#define IMX7D_GPR1_ENET1_CLK_DIR_MASK BIT(17)
+#define IMX7D_GPR1_ENET2_CLK_DIR_MASK BIT(18)
+#define IMX7D_GPR1_ENET_CLK_DIR_MASK (0x3 << 17)
+
+#define IMX7D_GPR5_CSI_MUX_CONTROL_MIPI BIT(4)
+#define IMX7D_GPR12_PCIE_PHY_REFCLK_SEL BIT(5)
+#define IMX7D_GPR22_PCIE_PHY_PLL_LOCKED BIT(31)
+
+
+static uint64_t imx7_gpr_read(void *opaque, hwaddr offset, unsigned size)
+{
+ trace_imx7_gpr_read(offset);
+
+ if (offset == IOMUXC_GPR22) {
+ return IMX7D_GPR22_PCIE_PHY_PLL_LOCKED;
+ }
+
+ return 0;
+}
+
+static void imx7_gpr_write(void *opaque, hwaddr offset,
+ uint64_t v, unsigned size)
+{
+ trace_imx7_gpr_write(offset, v);
+}
+
+static const struct MemoryRegionOps imx7_gpr_ops = {
+ .read = imx7_gpr_read,
+ .write = imx7_gpr_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ /*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the
+ * real device but in practice there is no reason for a guest
+ * to access this device unaligned.
+ */
+ .min_access_size = 4,
+ .max_access_size = 4,
+ .unaligned = false,
+ },
+};
+
+static void imx7_gpr_init(Object *obj)
+{
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+ IMX7GPRState *s = IMX7_GPR(obj);
+
+ memory_region_init_io(&s->mmio, obj, &imx7_gpr_ops, s,
+ TYPE_IMX7_GPR, 64 * 1024);
+ sysbus_init_mmio(sd, &s->mmio);
+}
+
+static void imx7_gpr_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->desc = "i.MX7 General Purpose Registers Module";
+}
+
+static const TypeInfo imx7_gpr_info = {
+ .name = TYPE_IMX7_GPR,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IMX7GPRState),
+ .instance_init = imx7_gpr_init,
+ .class_init = imx7_gpr_class_init,
+};
+
+static void imx7_gpr_register_type(void)
+{
+ type_register_static(&imx7_gpr_info);
+}
+type_init(imx7_gpr_register_type)
diff --git a/hw/misc/imx7_snvs.c b/hw/misc/imx7_snvs.c
new file mode 100644
index 0000000000..4df482b282
--- /dev/null
+++ b/hw/misc/imx7_snvs.c
@@ -0,0 +1,83 @@
+/*
+ * IMX7 Secure Non-Volatile Storage
+ *
+ * Copyright (c) 2018, Impinj, Inc.
+ *
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.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.
+ *
+ * Bare minimum emulation code needed to support being able to shut
+ * down linux guest gracefully.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/misc/imx7_snvs.h"
+#include "qemu/log.h"
+#include "sysemu/sysemu.h"
+
+static uint64_t imx7_snvs_read(void *opaque, hwaddr offset, unsigned size)
+{
+ return 0;
+}
+
+static void imx7_snvs_write(void *opaque, hwaddr offset,
+ uint64_t v, unsigned size)
+{
+ const uint32_t value = v;
+ const uint32_t mask = SNVS_LPCR_TOP | SNVS_LPCR_DP_EN;
+
+ if (offset == SNVS_LPCR && ((value & mask) == mask)) {
+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
+ }
+}
+
+static const struct MemoryRegionOps imx7_snvs_ops = {
+ .read = imx7_snvs_read,
+ .write = imx7_snvs_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ /*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the real
+ * device but in practice there is no reason for a guest to access
+ * this device unaligned.
+ */
+ .min_access_size = 4,
+ .max_access_size = 4,
+ .unaligned = false,
+ },
+};
+
+static void imx7_snvs_init(Object *obj)
+{
+ SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+ IMX7SNVSState *s = IMX7_SNVS(obj);
+
+ memory_region_init_io(&s->mmio, obj, &imx7_snvs_ops, s,
+ TYPE_IMX7_SNVS, 0x1000);
+
+ sysbus_init_mmio(sd, &s->mmio);
+}
+
+static void imx7_snvs_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->desc = "i.MX7 Secure Non-Volatile Storage Module";
+}
+
+static const TypeInfo imx7_snvs_info = {
+ .name = TYPE_IMX7_SNVS,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IMX7SNVSState),
+ .instance_init = imx7_snvs_init,
+ .class_init = imx7_snvs_class_init,
+};
+
+static void imx7_snvs_register_type(void)
+{
+ type_register_static(&imx7_snvs_info);
+}
+type_init(imx7_snvs_register_type)
diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c
index 008d8bd4d5..a185252144 100644
--- a/hw/misc/macio/cuda.c
+++ b/hw/misc/macio/cuda.c
@@ -145,21 +145,29 @@ static void cuda_update_irq(CUDAState *s)
}
}
-static uint64_t get_tb(uint64_t time, uint64_t freq)
+static uint64_t get_counter_value(CUDAState *s, CUDATimer *ti)
{
- return muldiv64(time, freq, NANOSECONDS_PER_SECOND);
+ /* Reverse of the tb calculation algorithm that Mac OS X uses on bootup */
+ uint64_t tb_diff = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
+ s->tb_frequency, NANOSECONDS_PER_SECOND) -
+ ti->load_time;
+
+ return (tb_diff * 0xBF401675E5DULL) / (s->tb_frequency << 24);
}
-static unsigned int get_counter(CUDATimer *ti)
+static uint64_t get_counter_load_time(CUDAState *s, CUDATimer *ti)
+{
+ uint64_t load_time = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
+ s->tb_frequency, NANOSECONDS_PER_SECOND);
+ return load_time;
+}
+
+static unsigned int get_counter(CUDAState *s, CUDATimer *ti)
{
int64_t d;
unsigned int counter;
- uint64_t tb_diff;
- uint64_t current_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- /* Reverse of the tb calculation algorithm that Mac OS X uses on bootup. */
- tb_diff = get_tb(current_time, ti->frequency) - ti->load_time;
- d = (tb_diff * 0xBF401675E5DULL) / (ti->frequency << 24);
+ d = get_counter_value(s, ti);
if (ti->index == 0) {
/* the timer goes down from latch to -1 (period of latch + 2) */
@@ -178,42 +186,42 @@ static unsigned int get_counter(CUDATimer *ti)
static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val)
{
CUDA_DPRINTF("T%d.counter=%d\n", 1 + ti->index, val);
- ti->load_time = get_tb(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
- s->frequency);
+ ti->load_time = get_counter_load_time(s, ti);
ti->counter_value = val;
cuda_timer_update(s, ti, ti->load_time);
}
-static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time)
+static int64_t get_next_irq_time(CUDATimer *ti, int64_t current_time)
{
int64_t d, next_time;
unsigned int counter;
/* current counter value */
- d = muldiv64(current_time - s->load_time,
- CUDA_TIMER_FREQ, NANOSECONDS_PER_SECOND);
+ d = muldiv64(current_time - ti->load_time,
+ ti->frequency, NANOSECONDS_PER_SECOND);
/* the timer goes down from latch to -1 (period of latch + 2) */
- if (d <= (s->counter_value + 1)) {
- counter = (s->counter_value - d) & 0xffff;
+ if (d <= (ti->counter_value + 1)) {
+ counter = (ti->counter_value - d) & 0xffff;
} else {
- counter = (d - (s->counter_value + 1)) % (s->latch + 2);
- counter = (s->latch - counter) & 0xffff;
+ counter = (d - (ti->counter_value + 1)) % (ti->latch + 2);
+ counter = (ti->latch - counter) & 0xffff;
}
/* Note: we consider the irq is raised on 0 */
if (counter == 0xffff) {
- next_time = d + s->latch + 1;
+ next_time = d + ti->latch + 1;
} else if (counter == 0) {
- next_time = d + s->latch + 2;
+ next_time = d + ti->latch + 2;
} else {
next_time = d + counter;
}
CUDA_DPRINTF("latch=%d counter=%" PRId64 " delta_next=%" PRId64 "\n",
- s->latch, d, next_time - d);
- next_time = muldiv64(next_time, NANOSECONDS_PER_SECOND, CUDA_TIMER_FREQ) +
- s->load_time;
- if (next_time <= current_time)
+ ti->latch, d, next_time - d);
+ next_time = muldiv64(next_time, NANOSECONDS_PER_SECOND, ti->frequency) +
+ ti->load_time;
+ if (next_time <= current_time) {
next_time = current_time + 1;
+ }
return next_time;
}
@@ -275,7 +283,7 @@ static void cuda_delay_set_sr_int(CUDAState *s)
timer_mod(s->sr_delay_timer, expire);
}
-static uint32_t cuda_readb(void *opaque, hwaddr addr)
+static uint64_t cuda_read(void *opaque, hwaddr addr, unsigned size)
{
CUDAState *s = opaque;
uint32_t val;
@@ -295,12 +303,12 @@ static uint32_t cuda_readb(void *opaque, hwaddr addr)
val = s->dira;
break;
case CUDA_REG_T1CL:
- val = get_counter(&s->timers[0]) & 0xff;
+ val = get_counter(s, &s->timers[0]) & 0xff;
s->ifr &= ~T1_INT;
cuda_update_irq(s);
break;
case CUDA_REG_T1CH:
- val = get_counter(&s->timers[0]) >> 8;
+ val = get_counter(s, &s->timers[0]) >> 8;
cuda_update_irq(s);
break;
case CUDA_REG_T1LL:
@@ -311,12 +319,12 @@ static uint32_t cuda_readb(void *opaque, hwaddr addr)
val = (s->timers[0].latch >> 8) & 0xff;
break;
case CUDA_REG_T2CL:
- val = get_counter(&s->timers[1]) & 0xff;
+ val = get_counter(s, &s->timers[1]) & 0xff;
s->ifr &= ~T2_INT;
cuda_update_irq(s);
break;
case CUDA_REG_T2CH:
- val = get_counter(&s->timers[1]) >> 8;
+ val = get_counter(s, &s->timers[1]) >> 8;
break;
case CUDA_REG_SR:
val = s->sr;
@@ -350,7 +358,7 @@ static uint32_t cuda_readb(void *opaque, hwaddr addr)
return val;
}
-static void cuda_writeb(void *opaque, hwaddr addr, uint32_t val)
+static void cuda_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
{
CUDAState *s = opaque;
@@ -359,11 +367,11 @@ static void cuda_writeb(void *opaque, hwaddr addr, uint32_t val)
switch(addr) {
case CUDA_REG_B:
- s->b = val;
+ s->b = (s->b & ~s->dirb) | (val & s->dirb);
cuda_update(s);
break;
case CUDA_REG_A:
- s->a = val;
+ s->a = (s->a & ~s->dira) | (val & s->dira);
break;
case CUDA_REG_DIRB:
s->dirb = val;
@@ -406,7 +414,6 @@ static void cuda_writeb(void *opaque, hwaddr addr, uint32_t val)
case CUDA_REG_ACR:
s->acr = val;
cuda_timer_update(s, &s->timers[0], qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
- cuda_update(s);
break;
case CUDA_REG_PCR:
s->pcr = val;
@@ -780,38 +787,14 @@ static void cuda_receive_packet_from_host(CUDAState *s,
}
}
-static void cuda_writew (void *opaque, hwaddr addr, uint32_t value)
-{
-}
-
-static void cuda_writel (void *opaque, hwaddr addr, uint32_t value)
-{
-}
-
-static uint32_t cuda_readw (void *opaque, hwaddr addr)
-{
- return 0;
-}
-
-static uint32_t cuda_readl (void *opaque, hwaddr addr)
-{
- return 0;
-}
-
static const MemoryRegionOps cuda_ops = {
- .old_mmio = {
- .write = {
- cuda_writeb,
- cuda_writew,
- cuda_writel,
- },
- .read = {
- cuda_readb,
- cuda_readw,
- cuda_readl,
- },
+ .read = cuda_read,
+ .write = cuda_write,
+ .endianness = DEVICE_BIG_ENDIAN,
+ .valid = {
+ .min_access_size = 1,
+ .max_access_size = 1,
},
- .endianness = DEVICE_NATIVE_ENDIAN,
};
static bool cuda_timer_exist(void *opaque, int version_id)
@@ -903,7 +886,7 @@ static void cuda_realizefn(DeviceState *dev, Error **errp)
struct tm tm;
s->timers[0].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_timer1, s);
- s->timers[0].frequency = s->frequency;
+ s->timers[0].frequency = CUDA_TIMER_FREQ;
s->timers[1].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_timer2, s);
s->timers[1].frequency = (SCALE_US * 6000) / 4700;
@@ -934,7 +917,7 @@ static void cuda_initfn(Object *obj)
}
static Property cuda_properties[] = {
- DEFINE_PROP_UINT64("frequency", CUDAState, frequency, 0),
+ DEFINE_PROP_UINT64("timebase-frequency", CUDAState, tb_frequency, 0),
DEFINE_PROP_END_OF_LIST()
};
diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c
index 44f91d1e7f..a639b09e00 100644
--- a/hw/misc/macio/macio.c
+++ b/hw/misc/macio/macio.c
@@ -451,7 +451,7 @@ void macio_init(PCIDevice *d,
macio_state->escc_mem = escc_mem;
/* Note: this code is strongly inspirated from the corresponding code
in PearPC */
- qdev_prop_set_uint64(DEVICE(&macio_state->cuda), "frequency",
+ qdev_prop_set_uint64(DEVICE(&macio_state->cuda), "timebase-frequency",
macio_state->frequency);
qdev_init_nofail(DEVICE(d));
diff --git a/hw/misc/mips_cmgcr.c b/hw/misc/mips_cmgcr.c
index 211f6097fd..d019d41a3c 100644
--- a/hw/misc/mips_cmgcr.c
+++ b/hw/misc/mips_cmgcr.c
@@ -10,7 +10,6 @@
*/
#include "qemu/osdep.h"
-#include "qapi/error.h"
#include "qemu/log.h"
#include "hw/hw.h"
#include "hw/sysbus.h"
diff --git a/hw/misc/mos6522.c b/hw/misc/mos6522.c
new file mode 100644
index 0000000000..8ad9fc831e
--- /dev/null
+++ b/hw/misc/mos6522.c
@@ -0,0 +1,505 @@
+/*
+ * QEMU MOS6522 VIA emulation
+ *
+ * Copyright (c) 2004-2007 Fabrice Bellard
+ * Copyright (c) 2007 Jocelyn Mayer
+ * Copyright (c) 2018 Mark Cave-Ayland
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "hw/hw.h"
+#include "hw/input/adb.h"
+#include "hw/misc/mos6522.h"
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "qemu/cutils.h"
+#include "qemu/log.h"
+#include "trace.h"
+
+/* XXX: implement all timer modes */
+
+static void mos6522_timer_update(MOS6522State *s, MOS6522Timer *ti,
+ int64_t current_time);
+
+static void mos6522_update_irq(MOS6522State *s)
+{
+ if (s->ifr & s->ier & (SR_INT | T1_INT | T2_INT)) {
+ qemu_irq_raise(s->irq);
+ } else {
+ qemu_irq_lower(s->irq);
+ }
+}
+
+static uint64_t get_counter_value(MOS6522State *s, MOS6522Timer *ti)
+{
+ MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(s);
+
+ if (ti->index == 0) {
+ return mdc->get_timer1_counter_value(s, ti);
+ } else {
+ return mdc->get_timer2_counter_value(s, ti);
+ }
+}
+
+static uint64_t get_load_time(MOS6522State *s, MOS6522Timer *ti)
+{
+ MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(s);
+
+ if (ti->index == 0) {
+ return mdc->get_timer1_load_time(s, ti);
+ } else {
+ return mdc->get_timer2_load_time(s, ti);
+ }
+}
+
+static unsigned int get_counter(MOS6522State *s, MOS6522Timer *ti)
+{
+ int64_t d;
+ unsigned int counter;
+
+ d = get_counter_value(s, ti);
+
+ if (ti->index == 0) {
+ /* the timer goes down from latch to -1 (period of latch + 2) */
+ if (d <= (ti->counter_value + 1)) {
+ counter = (ti->counter_value - d) & 0xffff;
+ } else {
+ counter = (d - (ti->counter_value + 1)) % (ti->latch + 2);
+ counter = (ti->latch - counter) & 0xffff;
+ }
+ } else {
+ counter = (ti->counter_value - d) & 0xffff;
+ }
+ return counter;
+}
+
+static void set_counter(MOS6522State *s, MOS6522Timer *ti, unsigned int val)
+{
+ trace_mos6522_set_counter(1 + ti->index, val);
+ ti->load_time = get_load_time(s, ti);
+ ti->counter_value = val;
+ mos6522_timer_update(s, ti, ti->load_time);
+}
+
+static int64_t get_next_irq_time(MOS6522State *s, MOS6522Timer *ti,
+ int64_t current_time)
+{
+ int64_t d, next_time;
+ unsigned int counter;
+
+ /* current counter value */
+ d = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - ti->load_time,
+ ti->frequency, NANOSECONDS_PER_SECOND);
+
+ /* the timer goes down from latch to -1 (period of latch + 2) */
+ if (d <= (ti->counter_value + 1)) {
+ counter = (ti->counter_value - d) & 0xffff;
+ } else {
+ counter = (d - (ti->counter_value + 1)) % (ti->latch + 2);
+ counter = (ti->latch - counter) & 0xffff;
+ }
+
+ /* Note: we consider the irq is raised on 0 */
+ if (counter == 0xffff) {
+ next_time = d + ti->latch + 1;
+ } else if (counter == 0) {
+ next_time = d + ti->latch + 2;
+ } else {
+ next_time = d + counter;
+ }
+ trace_mos6522_get_next_irq_time(ti->latch, d, next_time - d);
+ next_time = muldiv64(next_time, NANOSECONDS_PER_SECOND, ti->frequency) +
+ ti->load_time;
+ if (next_time <= current_time) {
+ next_time = current_time + 1;
+ }
+ return next_time;
+}
+
+static void mos6522_timer_update(MOS6522State *s, MOS6522Timer *ti,
+ int64_t current_time)
+{
+ if (!ti->timer) {
+ return;
+ }
+ if (ti->index == 0 && (s->acr & T1MODE) != T1MODE_CONT) {
+ timer_del(ti->timer);
+ } else {
+ ti->next_irq_time = get_next_irq_time(s, ti, current_time);
+ timer_mod(ti->timer, ti->next_irq_time);
+ }
+}
+
+static void mos6522_timer1(void *opaque)
+{
+ MOS6522State *s = opaque;
+ MOS6522Timer *ti = &s->timers[0];
+
+ mos6522_timer_update(s, ti, ti->next_irq_time);
+ s->ifr |= T1_INT;
+ mos6522_update_irq(s);
+}
+
+static void mos6522_timer2(void *opaque)
+{
+ MOS6522State *s = opaque;
+ MOS6522Timer *ti = &s->timers[1];
+
+ mos6522_timer_update(s, ti, ti->next_irq_time);
+ s->ifr |= T2_INT;
+ mos6522_update_irq(s);
+}
+
+static void mos6522_set_sr_int(MOS6522State *s)
+{
+ trace_mos6522_set_sr_int();
+ s->ifr |= SR_INT;
+ mos6522_update_irq(s);
+}
+
+static uint64_t mos6522_get_counter_value(MOS6522State *s, MOS6522Timer *ti)
+{
+ uint64_t d;
+
+ d = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - ti->load_time,
+ ti->frequency, NANOSECONDS_PER_SECOND);
+
+ return d;
+}
+
+static uint64_t mos6522_get_load_time(MOS6522State *s, MOS6522Timer *ti)
+{
+ uint64_t load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+
+ return load_time;
+}
+
+static void mos6522_portA_write(MOS6522State *s)
+{
+ qemu_log_mask(LOG_UNIMP, "portA_write unimplemented");
+}
+
+static void mos6522_portB_write(MOS6522State *s)
+{
+ qemu_log_mask(LOG_UNIMP, "portB_write unimplemented");
+}
+
+uint64_t mos6522_read(void *opaque, hwaddr addr, unsigned size)
+{
+ MOS6522State *s = opaque;
+ uint32_t val;
+
+ switch (addr) {
+ case VIA_REG_B:
+ val = s->b;
+ break;
+ case VIA_REG_A:
+ val = s->a;
+ break;
+ case VIA_REG_DIRB:
+ val = s->dirb;
+ break;
+ case VIA_REG_DIRA:
+ val = s->dira;
+ break;
+ case VIA_REG_T1CL:
+ val = get_counter(s, &s->timers[0]) & 0xff;
+ s->ifr &= ~T1_INT;
+ mos6522_update_irq(s);
+ break;
+ case VIA_REG_T1CH:
+ val = get_counter(s, &s->timers[0]) >> 8;
+ mos6522_update_irq(s);
+ break;
+ case VIA_REG_T1LL:
+ val = s->timers[0].latch & 0xff;
+ break;
+ case VIA_REG_T1LH:
+ /* XXX: check this */
+ val = (s->timers[0].latch >> 8) & 0xff;
+ break;
+ case VIA_REG_T2CL:
+ val = get_counter(s, &s->timers[1]) & 0xff;
+ s->ifr &= ~T2_INT;
+ mos6522_update_irq(s);
+ break;
+ case VIA_REG_T2CH:
+ val = get_counter(s, &s->timers[1]) >> 8;
+ break;
+ case VIA_REG_SR:
+ val = s->sr;
+ s->ifr &= ~(SR_INT | CB1_INT | CB2_INT);
+ mos6522_update_irq(s);
+ break;
+ case VIA_REG_ACR:
+ val = s->acr;
+ break;
+ case VIA_REG_PCR:
+ val = s->pcr;
+ break;
+ case VIA_REG_IFR:
+ val = s->ifr;
+ if (s->ifr & s->ier) {
+ val |= 0x80;
+ }
+ break;
+ case VIA_REG_IER:
+ val = s->ier | 0x80;
+ break;
+ default:
+ case VIA_REG_ANH:
+ val = s->anh;
+ break;
+ }
+
+ if (addr != VIA_REG_IFR || val != 0) {
+ trace_mos6522_read(addr, val);
+ }
+
+ return val;
+}
+
+void mos6522_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+ MOS6522State *s = opaque;
+ MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(s);
+
+ trace_mos6522_write(addr, val);
+
+ switch (addr) {
+ case VIA_REG_B:
+ s->b = (s->b & ~s->dirb) | (val & s->dirb);
+ mdc->portB_write(s);
+ break;
+ case VIA_REG_A:
+ s->a = (s->a & ~s->dira) | (val & s->dira);
+ mdc->portA_write(s);
+ break;
+ case VIA_REG_DIRB:
+ s->dirb = val;
+ break;
+ case VIA_REG_DIRA:
+ s->dira = val;
+ break;
+ case VIA_REG_T1CL:
+ s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
+ mos6522_timer_update(s, &s->timers[0],
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
+ break;
+ case VIA_REG_T1CH:
+ s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
+ s->ifr &= ~T1_INT;
+ set_counter(s, &s->timers[0], s->timers[0].latch);
+ break;
+ case VIA_REG_T1LL:
+ s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
+ mos6522_timer_update(s, &s->timers[0],
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
+ break;
+ case VIA_REG_T1LH:
+ s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
+ s->ifr &= ~T1_INT;
+ mos6522_timer_update(s, &s->timers[0],
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
+ break;
+ case VIA_REG_T2CL:
+ s->timers[1].latch = (s->timers[1].latch & 0xff00) | val;
+ break;
+ case VIA_REG_T2CH:
+ /* To ensure T2 generates an interrupt on zero crossing with the
+ common timer code, write the value directly from the latch to
+ the counter */
+ s->timers[1].latch = (s->timers[1].latch & 0xff) | (val << 8);
+ s->ifr &= ~T2_INT;
+ set_counter(s, &s->timers[1], s->timers[1].latch);
+ break;
+ case VIA_REG_SR:
+ s->sr = val;
+ break;
+ case VIA_REG_ACR:
+ s->acr = val;
+ mos6522_timer_update(s, &s->timers[0],
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
+ break;
+ case VIA_REG_PCR:
+ s->pcr = val;
+ break;
+ case VIA_REG_IFR:
+ /* reset bits */
+ s->ifr &= ~val;
+ mos6522_update_irq(s);
+ break;
+ case VIA_REG_IER:
+ if (val & IER_SET) {
+ /* set bits */
+ s->ier |= val & 0x7f;
+ } else {
+ /* reset bits */
+ s->ier &= ~val;
+ }
+ mos6522_update_irq(s);
+ break;
+ default:
+ case VIA_REG_ANH:
+ s->anh = val;
+ break;
+ }
+}
+
+static const MemoryRegionOps mos6522_ops = {
+ .read = mos6522_read,
+ .write = mos6522_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid = {
+ .min_access_size = 1,
+ .max_access_size = 1,
+ },
+};
+
+static bool mos6522_timer_exist(void *opaque, int version_id)
+{
+ MOS6522Timer *s = opaque;
+
+ return s->timer != NULL;
+}
+
+static const VMStateDescription vmstate_mos6522_timer = {
+ .name = "mos6522_timer",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT16(latch, MOS6522Timer),
+ VMSTATE_UINT16(counter_value, MOS6522Timer),
+ VMSTATE_INT64(load_time, MOS6522Timer),
+ VMSTATE_INT64(next_irq_time, MOS6522Timer),
+ VMSTATE_TIMER_PTR_TEST(timer, MOS6522Timer, mos6522_timer_exist),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_mos6522 = {
+ .name = "mos6522",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(a, MOS6522State),
+ VMSTATE_UINT8(b, MOS6522State),
+ VMSTATE_UINT8(dira, MOS6522State),
+ VMSTATE_UINT8(dirb, MOS6522State),
+ VMSTATE_UINT8(sr, MOS6522State),
+ VMSTATE_UINT8(acr, MOS6522State),
+ VMSTATE_UINT8(pcr, MOS6522State),
+ VMSTATE_UINT8(ifr, MOS6522State),
+ VMSTATE_UINT8(ier, MOS6522State),
+ VMSTATE_UINT8(anh, MOS6522State),
+ VMSTATE_STRUCT_ARRAY(timers, MOS6522State, 2, 1,
+ vmstate_mos6522_timer, MOS6522Timer),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void mos6522_reset(DeviceState *dev)
+{
+ MOS6522State *s = MOS6522(dev);
+
+ s->b = 0;
+ s->a = 0;
+ s->dirb = 0xff;
+ s->dira = 0;
+ s->sr = 0;
+ s->acr = 0;
+ s->pcr = 0;
+ s->ifr = 0;
+ s->ier = 0;
+ /* s->ier = T1_INT | SR_INT; */
+ s->anh = 0;
+
+ s->timers[0].latch = 0xffff;
+ set_counter(s, &s->timers[0], 0xffff);
+
+ s->timers[1].latch = 0xffff;
+}
+
+static void mos6522_realize(DeviceState *dev, Error **errp)
+{
+ MOS6522State *s = MOS6522(dev);
+
+ s->timers[0].frequency = s->frequency;
+ s->timers[1].frequency = s->frequency;
+}
+
+static void mos6522_init(Object *obj)
+{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ MOS6522State *s = MOS6522(obj);
+ int i;
+
+ memory_region_init_io(&s->mem, obj, &mos6522_ops, s, "mos6522", 0x10);
+ sysbus_init_mmio(sbd, &s->mem);
+ sysbus_init_irq(sbd, &s->irq);
+
+ for (i = 0; i < ARRAY_SIZE(s->timers); i++) {
+ s->timers[i].index = i;
+ }
+
+ s->timers[0].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, mos6522_timer1, s);
+ s->timers[1].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, mos6522_timer2, s);
+}
+
+static Property mos6522_properties[] = {
+ DEFINE_PROP_UINT64("frequency", MOS6522State, frequency, 0),
+ DEFINE_PROP_END_OF_LIST()
+};
+
+static void mos6522_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ MOS6522DeviceClass *mdc = MOS6522_DEVICE_CLASS(oc);
+
+ dc->realize = mos6522_realize;
+ dc->reset = mos6522_reset;
+ dc->vmsd = &vmstate_mos6522;
+ dc->props = mos6522_properties;
+ mdc->parent_realize = dc->realize;
+ mdc->set_sr_int = mos6522_set_sr_int;
+ mdc->portB_write = mos6522_portB_write;
+ mdc->portA_write = mos6522_portA_write;
+ mdc->get_timer1_counter_value = mos6522_get_counter_value;
+ mdc->get_timer2_counter_value = mos6522_get_counter_value;
+ mdc->get_timer1_load_time = mos6522_get_load_time;
+ mdc->get_timer2_load_time = mos6522_get_load_time;
+}
+
+static const TypeInfo mos6522_type_info = {
+ .name = TYPE_MOS6522,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(MOS6522State),
+ .instance_init = mos6522_init,
+ .abstract = true,
+ .class_size = sizeof(MOS6522DeviceClass),
+ .class_init = mos6522_class_init,
+};
+
+static void mos6522_register_types(void)
+{
+ type_register_static(&mos6522_type_info);
+}
+
+type_init(mos6522_register_types)
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
index 32be2a9df1..6a9d251f18 100644
--- a/hw/misc/mps2-scc.c
+++ b/hw/misc/mps2-scc.c
@@ -19,7 +19,6 @@
#include "qemu/osdep.h"
#include "qemu/log.h"
-#include "qapi/error.h"
#include "trace.h"
#include "hw/sysbus.h"
#include "hw/registerfields.h"
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
index 616579a403..b340d4e81c 100644
--- a/hw/misc/trace-events
+++ b/hw/misc/trace-events
@@ -66,3 +66,14 @@ mps2_scc_cfg_read(unsigned function, unsigned device, uint32_t value) "MPS2 SCC
msf2_sysreg_write(uint64_t offset, uint32_t val, uint32_t prev) "msf2-sysreg write: addr 0x%08" HWADDR_PRIx " data 0x%" PRIx32 " prev 0x%" PRIx32
msf2_sysreg_read(uint64_t offset, uint32_t val) "msf2-sysreg read: addr 0x%08" HWADDR_PRIx " data 0x%08" PRIx32
msf2_sysreg_write_pll_status(void) "Invalid write to read only PLL status register"
+
+#hw/misc/imx7_gpr.c
+imx7_gpr_read(uint64_t offset) "addr 0x%08" HWADDR_PRIx
+imx7_gpr_write(uint64_t offset, uint64_t value) "addr 0x%08" HWADDR_PRIx "value 0x%08" HWADDR_PRIx
+
+# hw/misc/mos6522.c
+mos6522_set_counter(int index, unsigned int val) "T%d.counter=%d"
+mos6522_get_next_irq_time(uint16_t latch, int64_t d, int64_t delta) "latch=%d counter=0x%"PRId64 " delta_next=0x%"PRId64
+mos6522_set_sr_int(void) "set sr_int"
+mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64
+mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x"
diff --git a/hw/net/rocker/qmp-norocker.c b/hw/net/rocker/qmp-norocker.c
index 6acbcdb02b..94c1e480ae 100644
--- a/hw/net/rocker/qmp-norocker.c
+++ b/hw/net/rocker/qmp-norocker.c
@@ -18,6 +18,7 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qmp-commands.h"
+#include "qapi/error.h"
#include "qapi/qmp/qerror.h"
RockerSwitch *qmp_query_rocker(const char *name, Error **errp)
diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c
index 823a29df03..a2a76c2a74 100644
--- a/hw/net/rocker/rocker.c
+++ b/hw/net/rocker/rocker.c
@@ -21,6 +21,7 @@
#include "hw/pci/msix.h"
#include "net/net.h"
#include "net/eth.h"
+#include "qapi/error.h"
#include "qemu/iov.h"
#include "qemu/bitops.h"
#include "qmp-commands.h"
diff --git a/hw/net/rocker/rocker_of_dpa.c b/hw/net/rocker/rocker_of_dpa.c
index 191a58e0a7..9339df2d09 100644
--- a/hw/net/rocker/rocker_of_dpa.c
+++ b/hw/net/rocker/rocker_of_dpa.c
@@ -16,6 +16,7 @@
#include "qemu/osdep.h"
#include "net/eth.h"
+#include "qapi/error.h"
#include "qemu/iov.h"
#include "qemu/timer.h"
#include "qmp-commands.h"
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 38674b08aa..369d40b378 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -22,7 +22,7 @@
#include "hw/virtio/virtio-net.h"
#include "net/vhost_net.h"
#include "hw/virtio/virtio-bus.h"
-#include "qapi/qmp/qjson.h"
+#include "qapi/error.h"
#include "qapi-event.h"
#include "hw/virtio/virtio-access.h"
#include "migration/misc.h"
diff --git a/hw/nios2/cpu_pic.c b/hw/nios2/cpu_pic.c
index 0f95987ef3..6bccce2f32 100644
--- a/hw/nios2/cpu_pic.c
+++ b/hw/nios2/cpu_pic.c
@@ -19,7 +19,6 @@
*/
#include "qemu/osdep.h"
-#include "qapi/error.h"
#include "qemu-common.h"
#include "cpu.h"
diff --git a/hw/nvram/eeprom_at24c.c b/hw/nvram/eeprom_at24c.c
index efa3621ac6..22183f5360 100644
--- a/hw/nvram/eeprom_at24c.c
+++ b/hw/nvram/eeprom_at24c.c
@@ -7,9 +7,8 @@
* the LICENSE file in the top-level directory.
*/
-#include <string.h>
-
#include "qemu/osdep.h"
+
#include "qapi/error.h"
#include "hw/hw.h"
#include "hw/i2c/i2c.h"
diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c
index 4313484b21..2a0739d0e9 100644
--- a/hw/nvram/fw_cfg.c
+++ b/hw/nvram/fw_cfg.c
@@ -21,6 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+
#include "qemu/osdep.h"
#include "hw/hw.h"
#include "sysemu/sysemu.h"
@@ -31,6 +32,7 @@
#include "hw/sysbus.h"
#include "trace.h"
#include "qemu/error-report.h"
+#include "qemu/option.h"
#include "qemu/config-file.h"
#include "qemu/cutils.h"
#include "qapi/error.h"
diff --git a/hw/pci-bridge/i82801b11.c b/hw/pci-bridge/i82801b11.c
index 620b43518e..10e590e5c6 100644
--- a/hw/pci-bridge/i82801b11.c
+++ b/hw/pci-bridge/i82801b11.c
@@ -44,8 +44,6 @@
#include "qemu/osdep.h"
#include "hw/pci/pci.h"
#include "hw/i386/ich9.h"
-#include "qapi/error.h"
-
/*****************************************************************************/
/* ICH9 DMI-to-PCI bridge */
diff --git a/hw/pci-bridge/ioh3420.c b/hw/pci-bridge/ioh3420.c
index a7bfbdd238..a451d74ee6 100644
--- a/hw/pci-bridge/ioh3420.c
+++ b/hw/pci-bridge/ioh3420.c
@@ -25,7 +25,6 @@
#include "hw/pci/msi.h"
#include "hw/pci/pcie.h"
#include "ioh3420.h"
-#include "qapi/error.h"
#define PCI_DEVICE_ID_IOH_EPORT 0x3420 /* D0:F0 express mode */
#define PCI_DEVICE_ID_IOH_REV 0x2
diff --git a/hw/pci-bridge/xio3130_upstream.c b/hw/pci-bridge/xio3130_upstream.c
index 556f471a83..bca2f9a5ea 100644
--- a/hw/pci-bridge/xio3130_upstream.c
+++ b/hw/pci-bridge/xio3130_upstream.c
@@ -24,7 +24,6 @@
#include "hw/pci/msi.h"
#include "hw/pci/pcie.h"
#include "xio3130_upstream.h"
-#include "qapi/error.h"
#define PCI_DEVICE_ID_TI_XIO3130U 0x8232 /* upstream port */
#define XIO3130_REVISION 0x2
diff --git a/hw/pci-host/sabre.c b/hw/pci-host/sabre.c
index 2268a41dd9..e2f4ee480e 100644
--- a/hw/pci-host/sabre.c
+++ b/hw/pci-host/sabre.c
@@ -34,7 +34,6 @@
#include "hw/pci-host/sabre.h"
#include "sysemu/sysemu.h"
#include "exec/address-spaces.h"
-#include "qapi/error.h"
#include "qemu/log.h"
#include "trace.h"
diff --git a/hw/pci/pci-stub.c b/hw/pci/pci-stub.c
index d5ce00748e..74ce7316da 100644
--- a/hw/pci/pci-stub.c
+++ b/hw/pci/pci-stub.c
@@ -21,6 +21,7 @@
#include "qemu/osdep.h"
#include "sysemu/sysemu.h"
#include "monitor/monitor.h"
+#include "qapi/error.h"
#include "qapi/qmp/qerror.h"
#include "hw/pci/pci.h"
#include "qmp-commands.h"
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index ef4342293e..e006b6ac71 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -21,6 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+
#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/pci/pci.h"
@@ -40,6 +41,7 @@
#include "exec/address-spaces.h"
#include "hw/hotplug.h"
#include "hw/boards.h"
+#include "qapi/error.h"
#include "qemu/cutils.h"
//#define DEBUG_PCI
diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c
index b009be7f17..939da0b778 100644
--- a/hw/pci/pcie_aer.c
+++ b/hw/pci/pcie_aer.c
@@ -20,8 +20,7 @@
#include "qemu/osdep.h"
#include "sysemu/sysemu.h"
-#include "qapi/qmp/types.h"
-#include "qapi/qmp/qjson.h"
+#include "qapi/qmp/qdict.h"
#include "monitor/monitor.h"
#include "hw/pci/pci_bridge.h"
#include "hw/pci/pcie.h"
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 343bba93ce..a40d3ec3e3 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -16,7 +16,6 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
-#include "qemu-common.h"
#include "e500.h"
#include "e500-ccsr.h"
#include "net/net.h"
@@ -36,6 +35,7 @@
#include "hw/sysbus.h"
#include "exec/address-spaces.h"
#include "qemu/host-utils.h"
+#include "qemu/option.h"
#include "hw/pci-host/ppce500.h"
#include "qemu/error-report.h"
#include "hw/platform-bus.h"
diff --git a/hw/ppc/fdt.c b/hw/ppc/fdt.c
index 38a7234b46..2ffc5866e4 100644
--- a/hw/ppc/fdt.c
+++ b/hw/ppc/fdt.c
@@ -8,7 +8,6 @@
*/
#include "qemu/osdep.h"
-#include "qapi/error.h"
#include "target/ppc/cpu.h"
#include "hw/ppc/fdt.h"
diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h
index b501af1653..fa78115c95 100644
--- a/hw/ppc/mac.h
+++ b/hw/ppc/mac.h
@@ -99,7 +99,7 @@ typedef struct CUDAState {
CUDATimer timers[2];
uint32_t tick_offset;
- uint64_t frequency;
+ uint64_t tb_frequency;
uint8_t last_b;
uint8_t last_acr;
diff --git a/hw/ppc/pnv_bmc.c b/hw/ppc/pnv_bmc.c
index b2cf441ee7..4b76d34f0a 100644
--- a/hw/ppc/pnv_bmc.c
+++ b/hw/ppc/pnv_bmc.c
@@ -20,7 +20,6 @@
#include "hw/hw.h"
#include "sysemu/sysemu.h"
#include "target/ppc/cpu.h"
-#include "qapi/error.h"
#include "qemu/log.h"
#include "hw/ipmi/ipmi.h"
#include "hw/ppc/fdt.h"
diff --git a/hw/ppc/pnv_xscom.c b/hw/ppc/pnv_xscom.c
index 99c40efecd..46fae41f32 100644
--- a/hw/ppc/pnv_xscom.c
+++ b/hw/ppc/pnv_xscom.c
@@ -17,7 +17,6 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
-#include "qapi/error.h"
#include "hw/hw.h"
#include "qemu/log.h"
#include "sysemu/hw_accel.h"
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index 7ec35de5ae..ec4be25f49 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -33,7 +33,6 @@
#include "hw/timer/m48t59.h"
#include "qemu/log.h"
#include "qemu/error-report.h"
-#include "qapi/error.h"
#include "hw/loader.h"
#include "sysemu/kvm.h"
#include "kvm_ppc.h"
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 32a876be56..9f29434819 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -74,7 +74,6 @@
#include "hw/compat.h"
#include "qemu/cutils.h"
#include "hw/ppc/spapr_cpu_core.h"
-#include "qmp-commands.h"
#include <libfdt.h>
@@ -465,7 +464,8 @@ static int spapr_populate_memory(sPAPRMachineState *spapr, void *fdt)
}
}
if (!mem_start) {
- /* ppc_spapr_init() checks for rma_size <= node0_size already */
+ /* spapr_machine_init() checks for rma_size <= node0_size
+ * already */
spapr_populate_memory_node(fdt, i, 0, spapr->rma_size);
mem_start += spapr->rma_size;
node_size -= spapr->rma_size;
@@ -2310,7 +2310,7 @@ static void spapr_set_vsmt_mode(sPAPRMachineState *spapr, Error **errp)
* the value that we'd get with KVM on POWER8, the
* overwhelmingly common case in production systems.
*/
- spapr->vsmt = 8;
+ spapr->vsmt = MAX(8, smp_threads);
}
/* KVM: If necessary, set the SMT mode: */
diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
index e3b122968e..aa251133de 100644
--- a/hw/ppc/spapr_drc.c
+++ b/hw/ppc/spapr_drc.c
@@ -12,6 +12,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
+#include "qapi/qmp/qnull.h"
#include "cpu.h"
#include "qemu/cutils.h"
#include "hw/ppc/spapr_drc.h"
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 4d0e6eb0cf..76422cfac1 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -1635,7 +1635,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
spapr->cas_legacy_guest_workaround = !spapr_ovec_test(ov1_guest,
OV1_PPC_3_00);
if (!spapr->cas_reboot) {
- /* If ppc_spapr_reset() did not set up a HPT but one is necessary
+ /* If spapr_machine_reset() did not set up a HPT but one is necessary
* (because the guest isn't going to use radix) then set it up here. */
if ((spapr->patb_entry & PATBE1_GR) && !guest_radix) {
/* legacy hash or new hash: */
@@ -1697,6 +1697,7 @@ static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu,
switch (safe_indirect_branch) {
case SPAPR_CAP_FIXED:
characteristics |= H_CPU_CHAR_BCCTRL_SERIALISED;
+ break;
default: /* broken */
assert(safe_indirect_branch == SPAPR_CAP_BROKEN);
break;
diff --git a/hw/ppc/spapr_pci_vfio.c b/hw/ppc/spapr_pci_vfio.c
index 053efb03bd..71491dbd28 100644
--- a/hw/ppc/spapr_pci_vfio.c
+++ b/hw/ppc/spapr_pci_vfio.c
@@ -19,7 +19,6 @@
#include "qemu/osdep.h"
#include <linux/vfio.h>
-#include "qapi/error.h"
#include "qemu-common.h"
#include "cpu.h"
#include "hw/ppc/spapr.h"
diff --git a/hw/ppc/spapr_rtc.c b/hw/ppc/spapr_rtc.c
index 9ec3078691..cfdb274bfd 100644
--- a/hw/ppc/spapr_rtc.c
+++ b/hw/ppc/spapr_rtc.c
@@ -23,14 +23,15 @@
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
- *
*/
+
#include "qemu/osdep.h"
#include "cpu.h"
#include "qemu/timer.h"
#include "sysemu/sysemu.h"
#include "hw/ppc/spapr.h"
#include "qapi-event.h"
+#include "qapi/error.h"
#include "qemu/cutils.h"
void spapr_rtc_read(sPAPRRTCState *rtc, struct tm *tm, uint32_t *ns)
diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c
index 485d9affb2..77a1778e07 100644
--- a/hw/ppc/virtex_ml507.c
+++ b/hw/ppc/virtex_ml507.c
@@ -37,6 +37,7 @@
#include "elf.h"
#include "qemu/error-report.h"
#include "qemu/log.h"
+#include "qemu/option.h"
#include "exec/address-spaces.h"
#include "hw/ppc/ppc.h"
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 1c526fd7e2..301bf1772f 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -439,7 +439,7 @@ static int s390_io_adapter_map(AdapterInfo *adapter, uint64_t map_addr,
bool do_map)
{
S390FLICState *fs = s390_get_flic();
- S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
+ S390FLICStateClass *fsc = s390_get_flic_class(fs);
return fsc->io_adapter_map(fs, adapter->adapter_id, map_addr, do_map);
}
@@ -520,7 +520,7 @@ void css_register_io_adapters(CssIoAdapterType type, bool swap, bool maskable,
int ret, isc;
IoAdapter *adapter;
S390FLICState *fs = s390_get_flic();
- S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
+ S390FLICStateClass *fsc = s390_get_flic_class(fs);
/*
* Disallow multiple registrations for the same device type.
@@ -566,7 +566,7 @@ static void css_clear_io_interrupt(uint16_t subchannel_id,
Error *err = NULL;
static bool no_clear_irq;
S390FLICState *fs = s390_get_flic();
- S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
+ S390FLICStateClass *fsc = s390_get_flic_class(fs);
int r;
if (unlikely(no_clear_irq)) {
@@ -640,7 +640,7 @@ void css_conditional_io_interrupt(SubchDev *sch)
int css_do_sic(CPUS390XState *env, uint8_t isc, uint16_t mode)
{
S390FLICState *fs = s390_get_flic();
- S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
+ S390FLICStateClass *fsc = s390_get_flic_class(fs);
int r;
if (env->psw.mask & PSW_MASK_PSTATE) {
@@ -666,7 +666,7 @@ out:
void css_adapter_interrupt(CssIoAdapterType type, uint8_t isc)
{
S390FLICState *fs = s390_get_flic();
- S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
+ S390FLICStateClass *fsc = s390_get_flic_class(fs);
uint32_t io_int_word = (isc << 27) | IO_INT_WORD_AI;
IoAdapter *adapter = channel_subsys.io_adapters[type][isc];
diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c
index b0f71f4554..155a69467b 100644
--- a/hw/s390x/event-facility.c
+++ b/hw/s390x/event-facility.c
@@ -293,10 +293,10 @@ static void write_event_mask(SCLPEventFacility *ef, SCCB *sccb)
ef->receive_mask = be32_to_cpu(tmp_mask);
/* return the SCLP's capability masks to the guest */
- tmp_mask = cpu_to_be32(get_host_send_mask(ef));
+ tmp_mask = cpu_to_be32(get_host_receive_mask(ef));
copy_mask(WEM_RECEIVE_MASK(we_mask, mask_length), (uint8_t *)&tmp_mask,
mask_length, sizeof(tmp_mask));
- tmp_mask = cpu_to_be32(get_host_receive_mask(ef));
+ tmp_mask = cpu_to_be32(get_host_send_mask(ef));
copy_mask(WEM_SEND_MASK(we_mask, mask_length), (uint8_t *)&tmp_mask,
mask_length, sizeof(tmp_mask));
diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c
index 4a9d4d2534..7fc1c603c0 100644
--- a/hw/s390x/s390-ccw.c
+++ b/hw/s390x/s390-ccw.c
@@ -10,10 +10,11 @@
* or (at your option) any later version. See the COPYING file in the
* top-level directory.
*/
+
#include "qemu/osdep.h"
+#include <libgen.h>
#include "qapi/error.h"
#include "hw/sysbus.h"
-#include "libgen.h"
#include "hw/s390x/css.h"
#include "hw/s390x/css-bridge.h"
#include "hw/s390x/s390-ccw.h"
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index 7d9c65e719..77a50cab36 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -309,49 +309,187 @@ static uint64_t get_st_pto(uint64_t entry)
: 0;
}
-static uint64_t s390_guest_io_table_walk(uint64_t guest_iota,
- uint64_t guest_dma_address)
+static bool rt_entry_isvalid(uint64_t entry)
{
- uint64_t sto_a, pto_a, px_a;
- uint64_t sto, pto, pte;
- uint32_t rtx, sx, px;
-
- rtx = calc_rtx(guest_dma_address);
- sx = calc_sx(guest_dma_address);
- px = calc_px(guest_dma_address);
-
- sto_a = guest_iota + rtx * sizeof(uint64_t);
- sto = address_space_ldq(&address_space_memory, sto_a,
- MEMTXATTRS_UNSPECIFIED, NULL);
- sto = get_rt_sto(sto);
- if (!sto) {
- pte = 0;
+ return (entry & ZPCI_TABLE_VALID_MASK) == ZPCI_TABLE_VALID;
+}
+
+static bool pt_entry_isvalid(uint64_t entry)
+{
+ return (entry & ZPCI_PTE_VALID_MASK) == ZPCI_PTE_VALID;
+}
+
+static bool entry_isprotected(uint64_t entry)
+{
+ return (entry & ZPCI_TABLE_PROT_MASK) == ZPCI_TABLE_PROTECTED;
+}
+
+/* ett is expected table type, -1 page table, 0 segment table, 1 region table */
+static uint64_t get_table_index(uint64_t iova, int8_t ett)
+{
+ switch (ett) {
+ case ZPCI_ETT_PT:
+ return calc_px(iova);
+ case ZPCI_ETT_ST:
+ return calc_sx(iova);
+ case ZPCI_ETT_RT:
+ return calc_rtx(iova);
+ }
+
+ return -1;
+}
+
+static bool entry_isvalid(uint64_t entry, int8_t ett)
+{
+ switch (ett) {
+ case ZPCI_ETT_PT:
+ return pt_entry_isvalid(entry);
+ case ZPCI_ETT_ST:
+ case ZPCI_ETT_RT:
+ return rt_entry_isvalid(entry);
+ }
+
+ return false;
+}
+
+/* Return true if address translation is done */
+static bool translate_iscomplete(uint64_t entry, int8_t ett)
+{
+ switch (ett) {
+ case 0:
+ return (entry & ZPCI_TABLE_FC) ? true : false;
+ case 1:
+ return false;
+ }
+
+ return true;
+}
+
+static uint64_t get_frame_size(int8_t ett)
+{
+ switch (ett) {
+ case ZPCI_ETT_PT:
+ return 1ULL << 12;
+ case ZPCI_ETT_ST:
+ return 1ULL << 20;
+ case ZPCI_ETT_RT:
+ return 1ULL << 31;
+ }
+
+ return 0;
+}
+
+static uint64_t get_next_table_origin(uint64_t entry, int8_t ett)
+{
+ switch (ett) {
+ case ZPCI_ETT_PT:
+ return entry & ZPCI_PTE_ADDR_MASK;
+ case ZPCI_ETT_ST:
+ return get_st_pto(entry);
+ case ZPCI_ETT_RT:
+ return get_rt_sto(entry);
+ }
+
+ return 0;
+}
+
+/**
+ * table_translate: do translation within one table and return the following
+ * table origin
+ *
+ * @entry: the entry being translated, the result is stored in this.
+ * @to: the address of table origin.
+ * @ett: expected table type, 1 region table, 0 segment table and -1 page table.
+ * @error: error code
+ */
+static uint64_t table_translate(S390IOTLBEntry *entry, uint64_t to, int8_t ett,
+ uint16_t *error)
+{
+ uint64_t tx, te, nto = 0;
+ uint16_t err = 0;
+
+ tx = get_table_index(entry->iova, ett);
+ te = address_space_ldq(&address_space_memory, to + tx * sizeof(uint64_t),
+ MEMTXATTRS_UNSPECIFIED, NULL);
+
+ if (!te) {
+ err = ERR_EVENT_INVALTE;
+ goto out;
+ }
+
+ if (!entry_isvalid(te, ett)) {
+ entry->perm &= IOMMU_NONE;
+ goto out;
+ }
+
+ if (ett == ZPCI_ETT_RT && ((te & ZPCI_TABLE_LEN_RTX) != ZPCI_TABLE_LEN_RTX
+ || te & ZPCI_TABLE_OFFSET_MASK)) {
+ err = ERR_EVENT_INVALTL;
goto out;
}
- pto_a = sto + sx * sizeof(uint64_t);
- pto = address_space_ldq(&address_space_memory, pto_a,
- MEMTXATTRS_UNSPECIFIED, NULL);
- pto = get_st_pto(pto);
- if (!pto) {
- pte = 0;
+ nto = get_next_table_origin(te, ett);
+ if (!nto) {
+ err = ERR_EVENT_TT;
goto out;
}
- px_a = pto + px * sizeof(uint64_t);
- pte = address_space_ldq(&address_space_memory, px_a,
- MEMTXATTRS_UNSPECIFIED, NULL);
+ if (entry_isprotected(te)) {
+ entry->perm &= IOMMU_RO;
+ } else {
+ entry->perm &= IOMMU_RW;
+ }
+ if (translate_iscomplete(te, ett)) {
+ switch (ett) {
+ case ZPCI_ETT_PT:
+ entry->translated_addr = te & ZPCI_PTE_ADDR_MASK;
+ break;
+ case ZPCI_ETT_ST:
+ entry->translated_addr = (te & ZPCI_SFAA_MASK) |
+ (entry->iova & ~ZPCI_SFAA_MASK);
+ break;
+ }
+ nto = 0;
+ }
out:
- return pte;
+ if (err) {
+ entry->perm = IOMMU_NONE;
+ *error = err;
+ }
+ entry->len = get_frame_size(ett);
+ return nto;
+}
+
+uint16_t s390_guest_io_table_walk(uint64_t g_iota, hwaddr addr,
+ S390IOTLBEntry *entry)
+{
+ uint64_t to = s390_pci_get_table_origin(g_iota);
+ int8_t ett = 1;
+ uint16_t error = 0;
+
+ entry->iova = addr & PAGE_MASK;
+ entry->translated_addr = 0;
+ entry->perm = IOMMU_RW;
+
+ if (entry_isprotected(g_iota)) {
+ entry->perm &= IOMMU_RO;
+ }
+
+ while (to) {
+ to = table_translate(entry, to, ett--, &error);
+ }
+
+ return error;
}
static IOMMUTLBEntry s390_translate_iommu(IOMMUMemoryRegion *mr, hwaddr addr,
IOMMUAccessFlags flag)
{
- uint64_t pte;
- uint32_t flags;
S390PCIIOMMU *iommu = container_of(mr, S390PCIIOMMU, iommu_mr);
+ S390IOTLBEntry *entry;
+ uint64_t iova = addr & PAGE_MASK;
+ uint16_t error = 0;
IOMMUTLBEntry ret = {
.target_as = &address_space_memory,
.iova = 0,
@@ -374,26 +512,31 @@ static IOMMUTLBEntry s390_translate_iommu(IOMMUMemoryRegion *mr, hwaddr addr,
DPRINTF("iommu trans addr 0x%" PRIx64 "\n", addr);
if (addr < iommu->pba || addr > iommu->pal) {
- return ret;
+ error = ERR_EVENT_OORANGE;
+ goto err;
}
- pte = s390_guest_io_table_walk(s390_pci_get_table_origin(iommu->g_iota),
- addr);
- if (!pte) {
- return ret;
- }
-
- flags = pte & ZPCI_PTE_FLAG_MASK;
- ret.iova = addr;
- ret.translated_addr = pte & ZPCI_PTE_ADDR_MASK;
- ret.addr_mask = 0xfff;
-
- if (flags & ZPCI_PTE_INVALID) {
- ret.perm = IOMMU_NONE;
+ entry = g_hash_table_lookup(iommu->iotlb, &iova);
+ if (entry) {
+ ret.iova = entry->iova;
+ ret.translated_addr = entry->translated_addr;
+ ret.addr_mask = entry->len - 1;
+ ret.perm = entry->perm;
} else {
- ret.perm = IOMMU_RW;
+ ret.iova = iova;
+ ret.addr_mask = ~PAGE_MASK;
+ ret.perm = IOMMU_NONE;
}
+ if (flag != IOMMU_NONE && !(flag & ret.perm)) {
+ error = ERR_EVENT_TPROTE;
+ }
+err:
+ if (error) {
+ iommu->pbdev->state = ZPCI_FS_ERROR;
+ s390_pci_generate_error_event(error, iommu->pbdev->fh,
+ iommu->pbdev->fid, addr, 0);
+ }
return ret;
}
@@ -435,6 +578,8 @@ static S390PCIIOMMU *s390_pci_get_iommu(S390pciState *s, PCIBus *bus,
PCI_FUNC(devfn));
memory_region_init(&iommu->mr, OBJECT(iommu), mr_name, UINT64_MAX);
address_space_init(&iommu->as, &iommu->mr, as_name);
+ iommu->iotlb = g_hash_table_new_full(g_int64_hash, g_int64_equal,
+ NULL, g_free);
table->iommu[PCI_SLOT(devfn)] = iommu;
g_free(mr_name);
@@ -524,6 +669,7 @@ void s390_pci_iommu_enable(S390PCIIOMMU *iommu)
void s390_pci_iommu_disable(S390PCIIOMMU *iommu)
{
iommu->enabled = false;
+ g_hash_table_remove_all(iommu->iotlb);
memory_region_del_subregion(&iommu->mr, MEMORY_REGION(&iommu->iommu_mr));
object_unparent(OBJECT(&iommu->iommu_mr));
}
@@ -539,6 +685,7 @@ static void s390_pci_iommu_free(S390pciState *s, PCIBus *bus, int32_t devfn)
}
table->iommu[PCI_SLOT(devfn)] = NULL;
+ g_hash_table_destroy(iommu->iotlb);
address_space_destroy(&iommu->as);
object_unparent(OBJECT(&iommu->mr));
object_unparent(OBJECT(iommu));
diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h
index 2993f0ddef..1f7f9b5814 100644
--- a/hw/s390x/s390-pci-bus.h
+++ b/hw/s390x/s390-pci-bus.h
@@ -148,6 +148,8 @@ enum ZpciIoatDtype {
#define ZPCI_STE_FLAG_MASK 0x7ffULL
#define ZPCI_STE_ADDR_MASK (~ZPCI_STE_FLAG_MASK)
+#define ZPCI_SFAA_MASK (~((1ULL << 20) - 1))
+
/* I/O Page tables */
#define ZPCI_PTE_VALID_MASK 0x400
#define ZPCI_PTE_INVALID 0x400
@@ -165,10 +167,15 @@ enum ZpciIoatDtype {
#define ZPCI_TABLE_INVALID 0x20
#define ZPCI_TABLE_PROTECTED 0x200
#define ZPCI_TABLE_UNPROTECTED 0x000
+#define ZPCI_TABLE_FC 0x400
#define ZPCI_TABLE_VALID_MASK 0x20
#define ZPCI_TABLE_PROT_MASK 0x200
+#define ZPCI_ETT_RT 1
+#define ZPCI_ETT_ST 0
+#define ZPCI_ETT_PT -1
+
/* PCI Function States
*
* reserved: default; device has just been plugged or is in progress of being
@@ -253,6 +260,13 @@ typedef struct S390MsixInfo {
uint32_t pba_offset;
} S390MsixInfo;
+typedef struct S390IOTLBEntry {
+ uint64_t iova;
+ uint64_t translated_addr;
+ uint64_t len;
+ uint64_t perm;
+} S390IOTLBEntry;
+
typedef struct S390PCIBusDevice S390PCIBusDevice;
typedef struct S390PCIIOMMU {
Object parent_obj;
@@ -264,6 +278,7 @@ typedef struct S390PCIIOMMU {
uint64_t g_iota;
uint64_t pba;
uint64_t pal;
+ GHashTable *iotlb;
} S390PCIIOMMU;
typedef struct S390PCIIOMMUTable {
@@ -320,6 +335,8 @@ void s390_pci_iommu_enable(S390PCIIOMMU *iommu);
void s390_pci_iommu_disable(S390PCIIOMMU *iommu);
void s390_pci_generate_error_event(uint16_t pec, uint32_t fh, uint32_t fid,
uint64_t faddr, uint32_t e);
+uint16_t s390_guest_io_table_walk(uint64_t g_iota, hwaddr addr,
+ S390IOTLBEntry *entry);
S390PCIBusDevice *s390_pci_find_dev_by_idx(S390pciState *s, uint32_t idx);
S390PCIBusDevice *s390_pci_find_dev_by_fh(S390pciState *s, uint32_t fh);
S390PCIBusDevice *s390_pci_find_dev_by_fid(S390pciState *s, uint32_t fid);
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index be449210d9..3fcc330fe3 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -571,27 +571,65 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
return 0;
}
+static void s390_pci_update_iotlb(S390PCIIOMMU *iommu, S390IOTLBEntry *entry)
+{
+ S390IOTLBEntry *cache = g_hash_table_lookup(iommu->iotlb, &entry->iova);
+ IOMMUTLBEntry notify = {
+ .target_as = &address_space_memory,
+ .iova = entry->iova,
+ .translated_addr = entry->translated_addr,
+ .perm = entry->perm,
+ .addr_mask = ~PAGE_MASK,
+ };
+
+ if (entry->perm == IOMMU_NONE) {
+ if (!cache) {
+ return;
+ }
+ g_hash_table_remove(iommu->iotlb, &entry->iova);
+ } else {
+ if (cache) {
+ if (cache->perm == entry->perm &&
+ cache->translated_addr == entry->translated_addr) {
+ return;
+ }
+
+ notify.perm = IOMMU_NONE;
+ memory_region_notify_iommu(&iommu->iommu_mr, notify);
+ notify.perm = entry->perm;
+ }
+
+ cache = g_new(S390IOTLBEntry, 1);
+ cache->iova = entry->iova;
+ cache->translated_addr = entry->translated_addr;
+ cache->len = PAGE_SIZE;
+ cache->perm = entry->perm;
+ g_hash_table_replace(iommu->iotlb, &cache->iova, cache);
+ }
+
+ memory_region_notify_iommu(&iommu->iommu_mr, notify);
+}
+
int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
{
CPUS390XState *env = &cpu->env;
uint32_t fh;
+ uint16_t error = 0;
S390PCIBusDevice *pbdev;
S390PCIIOMMU *iommu;
+ S390IOTLBEntry entry;
hwaddr start, end;
- IOMMUTLBEntry entry;
- IOMMUMemoryRegion *iommu_mr;
- IOMMUMemoryRegionClass *imrc;
cpu_synchronize_state(CPU(cpu));
if (env->psw.mask & PSW_MASK_PSTATE) {
s390_program_interrupt(env, PGM_PRIVILEGED, 4, ra);
- goto out;
+ return 0;
}
if (r2 & 0x1) {
s390_program_interrupt(env, PGM_SPECIFICATION, 4, ra);
- goto out;
+ return 0;
}
fh = env->regs[r1] >> 32;
@@ -602,7 +640,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
if (!pbdev) {
DPRINTF("rpcit no pci dev\n");
setcc(cpu, ZPCI_PCI_LS_INVAL_HANDLE);
- goto out;
+ return 0;
}
switch (pbdev->state) {
@@ -622,44 +660,37 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra)
iommu = pbdev->iommu;
if (!iommu->g_iota) {
- pbdev->state = ZPCI_FS_ERROR;
- setcc(cpu, ZPCI_PCI_LS_ERR);
- s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);
- s390_pci_generate_error_event(ERR_EVENT_INVALAS, pbdev->fh, pbdev->fid,
- start, 0);
- goto out;
+ error = ERR_EVENT_INVALAS;
+ goto err;
}
if (end < iommu->pba || start > iommu->pal) {
- pbdev->state = ZPCI_FS_ERROR;
- setcc(cpu, ZPCI_PCI_LS_ERR);
- s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);
- s390_pci_generate_error_event(ERR_EVENT_OORANGE, pbdev->fh, pbdev->fid,
- start, 0);
- goto out;
+ error = ERR_EVENT_OORANGE;
+ goto err;
}
- iommu_mr = &iommu->iommu_mr;
- imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
-
while (start < end) {
- entry = imrc->translate(iommu_mr, start, IOMMU_NONE);
-
- if (!entry.translated_addr) {
- pbdev->state = ZPCI_FS_ERROR;
- setcc(cpu, ZPCI_PCI_LS_ERR);
- s390_set_status_code(env, r1, ZPCI_PCI_ST_INSUF_RES);
- s390_pci_generate_error_event(ERR_EVENT_SERR, pbdev->fh, pbdev->fid,
- start, ERR_EVENT_Q_BIT);
- goto out;
+ error = s390_guest_io_table_walk(iommu->g_iota, start, &entry);
+ if (error) {
+ break;
}
- memory_region_notify_iommu(iommu_mr, entry);
- start += entry.addr_mask + 1;
+ start += entry.len;
+ while (entry.iova < start && entry.iova < end) {
+ s390_pci_update_iotlb(iommu, &entry);
+ entry.iova += PAGE_SIZE;
+ entry.translated_addr += PAGE_SIZE;
+ }
+ }
+err:
+ if (error) {
+ pbdev->state = ZPCI_FS_ERROR;
+ setcc(cpu, ZPCI_PCI_LS_ERR);
+ s390_set_status_code(env, r1, ZPCI_PCI_ST_FUNC_IN_ERR);
+ s390_pci_generate_error_event(error, pbdev->fh, pbdev->fid, start, 0);
+ } else {
+ setcc(cpu, ZPCI_PCI_LS_OK);
}
-
- setcc(cpu, ZPCI_PCI_LS_OK);
-out:
return 0;
}
@@ -834,6 +865,8 @@ static int reg_ioat(CPUS390XState *env, S390PCIIOMMU *iommu, ZpciFib fib,
uint8_t dt = (g_iota >> 2) & 0x7;
uint8_t t = (g_iota >> 11) & 0x1;
+ pba &= ~0xfff;
+ pal |= 0xfff;
if (pba > pal || pba < ZPCI_SDMA_ADDR || pal > ZPCI_EDMA_ADDR) {
s390_program_interrupt(env, PGM_OPERAND, 6, ra);
return -EINVAL;
diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c
index 53ad5d38d4..bdb6c18a0f 100644
--- a/hw/s390x/s390-skeys.c
+++ b/hw/s390x/s390-skeys.c
@@ -13,6 +13,8 @@
#include "hw/boards.h"
#include "qmp-commands.h"
#include "hw/s390x/storage-keys.h"
+#include "qapi/error.h"
+#include "qapi/qmp/qdict.h"
#include "qemu/error-report.h"
#include "sysemu/kvm.h"
#include "migration/register.h"
diff --git a/hw/s390x/s390-stattrib.c b/hw/s390x/s390-stattrib.c
index 2902f54f11..a1d2135a60 100644
--- a/hw/s390x/s390-stattrib.c
+++ b/hw/s390x/s390-stattrib.c
@@ -12,13 +12,13 @@
#include "qemu/osdep.h"
#include "hw/boards.h"
#include "cpu.h"
-#include "qmp-commands.h"
#include "migration/qemu-file.h"
#include "migration/register.h"
#include "hw/s390x/storage-attributes.h"
#include "qemu/error-report.h"
#include "exec/ram_addr.h"
#include "qapi/error.h"
+#include "qapi/qmp/qdict.h"
#define CMMA_BLOCK_SIZE (1 << 10)
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 3807dcb097..4abbe89847 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -12,7 +12,6 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
-#include "qemu-common.h"
#include "cpu.h"
#include "hw/boards.h"
#include "exec/address-spaces.h"
@@ -24,6 +23,7 @@
#include "virtio-ccw.h"
#include "qemu/config-file.h"
#include "qemu/error-report.h"
+#include "qemu/option.h"
#include "s390-pci-bus.h"
#include "hw/s390x/storage-keys.h"
#include "hw/s390x/storage-attributes.h"
@@ -33,7 +33,6 @@
#include "hw/s390x/css-bridge.h"
#include "migration/register.h"
#include "cpu_models.h"
-#include "qapi/qmp/qerror.h"
#include "hw/nmi.h"
S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
@@ -78,10 +77,6 @@ static void s390_init_cpus(MachineState *machine)
MachineClass *mc = MACHINE_GET_CLASS(machine);
int i;
- if (tcg_enabled() && max_cpus > 1) {
- error_report("WARNING: SMP support on s390x is experimental!");
- }
-
/* initialize possible_cpus */
mc->possible_cpu_arch_ids(machine);
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 3d8f26949b..8f7fbc2ab7 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -1111,7 +1111,7 @@ static int virtio_ccw_setup_irqroutes(VirtioCcwDevice *dev, int nvqs)
VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
int ret;
S390FLICState *fs = s390_get_flic();
- S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
+ S390FLICStateClass *fsc = s390_get_flic_class(fs);
ret = virtio_ccw_get_mappings(dev);
if (ret) {
@@ -1129,7 +1129,7 @@ static int virtio_ccw_setup_irqroutes(VirtioCcwDevice *dev, int nvqs)
static void virtio_ccw_release_irqroutes(VirtioCcwDevice *dev, int nvqs)
{
S390FLICState *fs = s390_get_flic();
- S390FLICStateClass *fsc = S390_FLIC_COMMON_GET_CLASS(fs);
+ S390FLICStateClass *fsc = s390_get_flic_class(fs);
fsc->release_adapter_routes(fs, &dev->routes);
}
diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c
index ee586e7d6c..45975c21e8 100644
--- a/hw/scsi/esp.c
+++ b/hw/scsi/esp.c
@@ -27,7 +27,6 @@
#include "hw/sysbus.h"
#include "hw/scsi/esp.h"
#include "trace.h"
-#include "qapi/error.h"
#include "qemu/log.h"
/*
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index 05e501efd3..b7bafbed6e 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -2,6 +2,7 @@
#include "hw/hw.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
+#include "qemu/option.h"
#include "hw/scsi/scsi.h"
#include "scsi/constants.h"
#include "hw/qdev.h"
diff --git a/hw/scsi/vhost-scsi-common.c b/hw/scsi/vhost-scsi-common.c
index d434b3e99a..77e9897244 100644
--- a/hw/scsi/vhost-scsi-common.c
+++ b/hw/scsi/vhost-scsi-common.c
@@ -16,7 +16,6 @@
*/
#include "qemu/osdep.h"
-#include "qapi/error.h"
#include "qemu/error-report.h"
#include "migration/migration.h"
#include "hw/virtio/vhost.h"
diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
index fc807f08f3..0991acd724 100644
--- a/hw/sd/sdhci-internal.h
+++ b/hw/sd/sdhci-internal.h
@@ -84,12 +84,18 @@
/* R/W Host control Register 0x0 */
#define SDHC_HOSTCTL 0x28
+#define SDHC_CTRL_LED 0x01
#define SDHC_CTRL_DMA_CHECK_MASK 0x18
#define SDHC_CTRL_SDMA 0x00
#define SDHC_CTRL_ADMA1_32 0x08
#define SDHC_CTRL_ADMA2_32 0x10
#define SDHC_CTRL_ADMA2_64 0x18
#define SDHC_DMA_TYPE(x) ((x) & SDHC_CTRL_DMA_CHECK_MASK)
+#define SDHC_CTRL_4BITBUS 0x02
+#define SDHC_CTRL_8BITBUS 0x20
+#define SDHC_CTRL_CDTEST_INS 0x40
+#define SDHC_CTRL_CDTEST_EN 0x80
+
/* R/W Power Control Register 0x0 */
#define SDHC_PWRCON 0x29
@@ -226,4 +232,21 @@ enum {
sdhc_gap_write = 2 /* SDHC stopped at block gap during write operation */
};
+extern const VMStateDescription sdhci_vmstate;
+
+
+#define ESDHC_MIX_CTRL 0x48
+#define ESDHC_VENDOR_SPEC 0xc0
+#define ESDHC_DLL_CTRL 0x60
+
+#define ESDHC_TUNING_CTRL 0xcc
+#define ESDHC_TUNE_CTRL_STATUS 0x68
+#define ESDHC_WTMK_LVL 0x44
+
+/* Undocumented register used by guests working around erratum ERR004536 */
+#define ESDHC_UNDOCUMENTED_REG27 0x6c
+
+#define ESDHC_CTRL_4BITBUS (0x1 << 1)
+#define ESDHC_CTRL_8BITBUS (0x2 << 1)
+
#endif
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index fac7fa5c72..ee95e78aeb 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -32,7 +32,6 @@
#include "qemu/bitops.h"
#include "hw/sd/sdhci.h"
#include "sdhci-internal.h"
-#include "qapi/error.h"
#include "qemu/log.h"
#include "trace.h"
@@ -244,7 +243,8 @@ static void sdhci_send_command(SDHCIState *s)
}
}
- if ((s->norintstsen & SDHC_NISEN_TRSCMP) &&
+ if (!(s->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) &&
+ (s->norintstsen & SDHC_NISEN_TRSCMP) &&
(s->cmdreg & SDHC_CMD_RESPONSE) == SDHC_CMD_RSP_WITH_BUSY) {
s->norintsts |= SDHC_NIS_TRSCMP;
}
@@ -1189,6 +1189,8 @@ static void sdhci_initfn(SDHCIState *s)
s->insert_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_raise_insertion_irq, s);
s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_data_transfer, s);
+
+ s->io_ops = &sdhci_mmio_ops;
}
static void sdhci_uninitfn(SDHCIState *s)
@@ -1396,6 +1398,10 @@ static void sdhci_sysbus_realize(DeviceState *dev, Error ** errp)
}
sysbus_init_irq(sbd, &s->irq);
+
+ memory_region_init_io(&s->iomem, OBJECT(s), s->io_ops, s, "sdhci",
+ SDHC_REGISTERS_MAP_SIZE);
+
sysbus_init_mmio(sbd, &s->iomem);
}
@@ -1447,11 +1453,232 @@ static const TypeInfo sdhci_bus_info = {
.class_init = sdhci_bus_class_init,
};
+static uint64_t usdhc_read(void *opaque, hwaddr offset, unsigned size)
+{
+ SDHCIState *s = SYSBUS_SDHCI(opaque);
+ uint32_t ret;
+ uint16_t hostctl;
+
+ switch (offset) {
+ default:
+ return sdhci_read(opaque, offset, size);
+
+ case SDHC_HOSTCTL:
+ /*
+ * For a detailed explanation on the following bit
+ * manipulation code see comments in a similar part of
+ * usdhc_write()
+ */
+ hostctl = SDHC_DMA_TYPE(s->hostctl) << (8 - 3);
+
+ if (s->hostctl & SDHC_CTRL_8BITBUS) {
+ hostctl |= ESDHC_CTRL_8BITBUS;
+ }
+
+ if (s->hostctl & SDHC_CTRL_4BITBUS) {
+ hostctl |= ESDHC_CTRL_4BITBUS;
+ }
+
+ ret = hostctl;
+ ret |= (uint32_t)s->blkgap << 16;
+ ret |= (uint32_t)s->wakcon << 24;
+
+ break;
+
+ case ESDHC_DLL_CTRL:
+ case ESDHC_TUNE_CTRL_STATUS:
+ case ESDHC_UNDOCUMENTED_REG27:
+ case ESDHC_TUNING_CTRL:
+ case ESDHC_VENDOR_SPEC:
+ case ESDHC_MIX_CTRL:
+ case ESDHC_WTMK_LVL:
+ ret = 0;
+ break;
+ }
+
+ return ret;
+}
+
+static void
+usdhc_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
+{
+ SDHCIState *s = SYSBUS_SDHCI(opaque);
+ uint8_t hostctl;
+ uint32_t value = (uint32_t)val;
+
+ switch (offset) {
+ case ESDHC_DLL_CTRL:
+ case ESDHC_TUNE_CTRL_STATUS:
+ case ESDHC_UNDOCUMENTED_REG27:
+ case ESDHC_TUNING_CTRL:
+ case ESDHC_WTMK_LVL:
+ case ESDHC_VENDOR_SPEC:
+ break;
+
+ case SDHC_HOSTCTL:
+ /*
+ * Here's What ESDHCI has at offset 0x28 (SDHC_HOSTCTL)
+ *
+ * 7 6 5 4 3 2 1 0
+ * |-----------+--------+--------+-----------+----------+---------|
+ * | Card | Card | Endian | DATA3 | Data | Led |
+ * | Detect | Detect | Mode | as Card | Transfer | Control |
+ * | Signal | Test | | Detection | Width | |
+ * | Selection | Level | | Pin | | |
+ * |-----------+--------+--------+-----------+----------+---------|
+ *
+ * and 0x29
+ *
+ * 15 10 9 8
+ * |----------+------|
+ * | Reserved | DMA |
+ * | | Sel. |
+ * | | |
+ * |----------+------|
+ *
+ * and here's what SDCHI spec expects those offsets to be:
+ *
+ * 0x28 (Host Control Register)
+ *
+ * 7 6 5 4 3 2 1 0
+ * |--------+--------+----------+------+--------+----------+---------|
+ * | Card | Card | Extended | DMA | High | Data | LED |
+ * | Detect | Detect | Data | Sel. | Speed | Transfer | Control |
+ * | Signal | Test | Transfer | | Enable | Width | |
+ * | Sel. | Level | Width | | | | |
+ * |--------+--------+----------+------+--------+----------+---------|
+ *
+ * and 0x29 (Power Control Register)
+ *
+ * |----------------------------------|
+ * | Power Control Register |
+ * | |
+ * | Description omitted, |
+ * | since it has no analog in ESDHCI |
+ * | |
+ * |----------------------------------|
+ *
+ * Since offsets 0x2A and 0x2B should be compatible between
+ * both IP specs we only need to reconcile least 16-bit of the
+ * word we've been given.
+ */
+
+ /*
+ * First, save bits 7 6 and 0 since they are identical
+ */
+ hostctl = value & (SDHC_CTRL_LED |
+ SDHC_CTRL_CDTEST_INS |
+ SDHC_CTRL_CDTEST_EN);
+ /*
+ * Second, split "Data Transfer Width" from bits 2 and 1 in to
+ * bits 5 and 1
+ */
+ if (value & ESDHC_CTRL_8BITBUS) {
+ hostctl |= SDHC_CTRL_8BITBUS;
+ }
+
+ if (value & ESDHC_CTRL_4BITBUS) {
+ hostctl |= ESDHC_CTRL_4BITBUS;
+ }
+
+ /*
+ * Third, move DMA select from bits 9 and 8 to bits 4 and 3
+ */
+ hostctl |= SDHC_DMA_TYPE(value >> (8 - 3));
+
+ /*
+ * Now place the corrected value into low 16-bit of the value
+ * we are going to give standard SDHCI write function
+ *
+ * NOTE: This transformation should be the inverse of what can
+ * be found in drivers/mmc/host/sdhci-esdhc-imx.c in Linux
+ * kernel
+ */
+ value &= ~UINT16_MAX;
+ value |= hostctl;
+ value |= (uint16_t)s->pwrcon << 8;
+
+ sdhci_write(opaque, offset, value, size);
+ break;
+
+ case ESDHC_MIX_CTRL:
+ /*
+ * So, when SD/MMC stack in Linux tries to write to "Transfer
+ * Mode Register", ESDHC i.MX quirk code will translate it
+ * into a write to ESDHC_MIX_CTRL, so we do the opposite in
+ * order to get where we started
+ *
+ * Note that Auto CMD23 Enable bit is located in a wrong place
+ * on i.MX, but since it is not used by QEMU we do not care.
+ *
+ * We don't want to call sdhci_write(.., SDHC_TRNMOD, ...)
+ * here becuase it will result in a call to
+ * sdhci_send_command(s) which we don't want.
+ *
+ */
+ s->trnmod = value & UINT16_MAX;
+ break;
+ case SDHC_TRNMOD:
+ /*
+ * Similar to above, but this time a write to "Command
+ * Register" will be translated into a 4-byte write to
+ * "Transfer Mode register" where lower 16-bit of value would
+ * be set to zero. So what we do is fill those bits with
+ * cached value from s->trnmod and let the SDHCI
+ * infrastructure handle the rest
+ */
+ sdhci_write(opaque, offset, val | s->trnmod, size);
+ break;
+ case SDHC_BLKSIZE:
+ /*
+ * ESDHCI does not implement "Host SDMA Buffer Boundary", and
+ * Linux driver will try to zero this field out which will
+ * break the rest of SDHCI emulation.
+ *
+ * Linux defaults to maximum possible setting (512K boundary)
+ * and it seems to be the only option that i.MX IP implements,
+ * so we artificially set it to that value.
+ */
+ val |= 0x7 << 12;
+ /* FALLTHROUGH */
+ default:
+ sdhci_write(opaque, offset, val, size);
+ break;
+ }
+}
+
+
+static const MemoryRegionOps usdhc_mmio_ops = {
+ .read = usdhc_read,
+ .write = usdhc_write,
+ .valid = {
+ .min_access_size = 1,
+ .max_access_size = 4,
+ .unaligned = false
+ },
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void imx_usdhc_init(Object *obj)
+{
+ SDHCIState *s = SYSBUS_SDHCI(obj);
+
+ s->io_ops = &usdhc_mmio_ops;
+ s->quirks = SDHCI_QUIRK_NO_BUSY_IRQ;
+}
+
+static const TypeInfo imx_usdhc_info = {
+ .name = TYPE_IMX_USDHC,
+ .parent = TYPE_SYSBUS_SDHCI,
+ .instance_init = imx_usdhc_init,
+};
+
static void sdhci_register_types(void)
{
type_register_static(&sdhci_pci_info);
type_register_static(&sdhci_sysbus_info);
type_register_static(&sdhci_bus_info);
+ type_register_static(&imx_usdhc_info);
}
type_init(sdhci_register_types)
diff --git a/hw/smbios/smbios-stub.c b/hw/smbios/smbios-stub.c
index 308739410f..d3a385441a 100644
--- a/hw/smbios/smbios-stub.c
+++ b/hw/smbios/smbios-stub.c
@@ -21,8 +21,8 @@
*/
#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "qapi/qmp/qerror.h"
-#include "qmp-commands.h"
#include "hw/smbios/smbios.h"
void smbios_entry_add(QemuOpts *opts, Error **errp)
diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
index 5d11f01874..27a07e96f4 100644
--- a/hw/smbios/smbios.c
+++ b/hw/smbios/smbios.c
@@ -19,6 +19,7 @@
#include "qapi/error.h"
#include "qemu/config-file.h"
#include "qemu/error-report.h"
+#include "qemu/option.h"
#include "sysemu/sysemu.h"
#include "qemu/uuid.h"
#include "sysemu/cpus.h"
diff --git a/hw/sparc64/niagara.c b/hw/sparc64/niagara.c
index 996ce2ada0..1874477ef6 100644
--- a/hw/sparc64/niagara.c
+++ b/hw/sparc64/niagara.c
@@ -23,7 +23,6 @@
*/
#include "qemu/osdep.h"
-#include "qapi/error.h"
#include "qemu-common.h"
#include "cpu.h"
#include "hw/hw.h"
diff --git a/hw/sparc64/sun4u_iommu.c b/hw/sparc64/sun4u_iommu.c
index 4cf8e69be9..eb3aaa87e6 100644
--- a/hw/sparc64/sun4u_iommu.c
+++ b/hw/sparc64/sun4u_iommu.c
@@ -28,7 +28,6 @@
#include "hw/sysbus.h"
#include "hw/sparc/sun4u_iommu.h"
#include "exec/address-spaces.h"
-#include "qapi/error.h"
#include "qemu/log.h"
#include "trace.h"
diff --git a/hw/ssi/stm32f2xx_spi.c b/hw/ssi/stm32f2xx_spi.c
index 69514da9fb..930c616de3 100644
--- a/hw/ssi/stm32f2xx_spi.c
+++ b/hw/ssi/stm32f2xx_spi.c
@@ -23,7 +23,6 @@
*/
#include "qemu/osdep.h"
-#include "qapi/error.h"
#include "qemu/log.h"
#include "hw/ssi/stm32f2xx_spi.h"
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
index 4b9b54bf2e..65e4ee6bcf 100644
--- a/hw/timer/imx_gpt.c
+++ b/hw/timer/imx_gpt.c
@@ -113,6 +113,17 @@ static const IMXClk imx6_gpt_clocks[] = {
CLK_HIGH, /* 111 reference clock */
};
+static const IMXClk imx7_gpt_clocks[] = {
+ CLK_NONE, /* 000 No clock source */
+ CLK_IPG, /* 001 ipg_clk, 532MHz*/
+ CLK_IPG_HIGH, /* 010 ipg_clk_highfreq */
+ CLK_EXT, /* 011 External clock */
+ CLK_32k, /* 100 ipg_clk_32k */
+ CLK_HIGH, /* 101 reference clock */
+ CLK_NONE, /* 110 not defined */
+ CLK_NONE, /* 111 not defined */
+};
+
static void imx_gpt_set_freq(IMXGPTState *s)
{
uint32_t clksrc = extract32(s->cr, GPT_CR_CLKSRC_SHIFT, 3);
@@ -512,6 +523,13 @@ static void imx6_gpt_init(Object *obj)
s->clocks = imx6_gpt_clocks;
}
+static void imx7_gpt_init(Object *obj)
+{
+ IMXGPTState *s = IMX_GPT(obj);
+
+ s->clocks = imx7_gpt_clocks;
+}
+
static const TypeInfo imx25_gpt_info = {
.name = TYPE_IMX25_GPT,
.parent = TYPE_SYS_BUS_DEVICE,
@@ -532,11 +550,18 @@ static const TypeInfo imx6_gpt_info = {
.instance_init = imx6_gpt_init,
};
+static const TypeInfo imx7_gpt_info = {
+ .name = TYPE_IMX7_GPT,
+ .parent = TYPE_IMX25_GPT,
+ .instance_init = imx7_gpt_init,
+};
+
static void imx_gpt_register_types(void)
{
type_register_static(&imx25_gpt_info);
type_register_static(&imx31_gpt_info);
type_register_static(&imx6_gpt_info);
+ type_register_static(&imx7_gpt_info);
}
type_init(imx_gpt_register_types)
diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c
index 844aad540e..742c576443 100644
--- a/hw/timer/m48t59.c
+++ b/hw/timer/m48t59.c
@@ -25,7 +25,6 @@
#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/timer/m48t59.h"
-#include "qapi/error.h"
#include "qemu/timer.h"
#include "sysemu/sysemu.h"
#include "hw/sysbus.h"
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index 35a05a64cc..9d93a16e0f 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -21,6 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+
#include "qemu/osdep.h"
#include "qemu/cutils.h"
#include "qemu/bcd.h"
@@ -29,6 +30,7 @@
#include "sysemu/sysemu.h"
#include "sysemu/replay.h"
#include "hw/timer/mc146818rtc.h"
+#include "qapi/error.h"
#include "qapi/visitor.h"
#include "qapi-event.h"
#include "qmp-commands.h"
diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c
index 710a9ec718..b787aee13b 100644
--- a/hw/tpm/tpm_emulator.c
+++ b/hw/tpm/tpm_emulator.c
@@ -40,11 +40,6 @@
#include "qapi/clone-visitor.h"
#include "chardev/char-fe.h"
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdio.h>
-
#define DEBUG_TPM 0
#define DPRINTF(fmt, ...) do { \
diff --git a/hw/tpm/tpm_int.h b/hw/tpm/tpm_int.h
index abbca5191a..a4c77fbd7e 100644
--- a/hw/tpm/tpm_int.h
+++ b/hw/tpm/tpm_int.h
@@ -12,8 +12,6 @@
#ifndef TPM_TPM_INT_H
#define TPM_TPM_INT_H
-#include "qemu/osdep.h"
-
#define TPM_STANDARD_CMDLINE_OPTS \
{ \
.name = "type", \
diff --git a/hw/tpm/tpm_ioctl.h b/hw/tpm/tpm_ioctl.h
index 54c8d345ad..59a0b0595d 100644
--- a/hw/tpm/tpm_ioctl.h
+++ b/hw/tpm/tpm_ioctl.h
@@ -8,9 +8,7 @@
#ifndef _TPM_IOCTL_H_
#define _TPM_IOCTL_H_
-#include <stdint.h>
#include <sys/uio.h>
-#include <sys/types.h>
#include <sys/ioctl.h>
/*
diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs
index fbcd498c59..41be700812 100644
--- a/hw/usb/Makefile.objs
+++ b/hw/usb/Makefile.objs
@@ -12,6 +12,7 @@ common-obj-$(CONFIG_USB_XHCI_NEC) += hcd-xhci-nec.o
common-obj-$(CONFIG_USB_MUSB) += hcd-musb.o
obj-$(CONFIG_TUSB6010) += tusb6010.o
+obj-$(CONFIG_IMX) += chipidea.o
# emulated usb devices
common-obj-$(CONFIG_USB) += dev-hub.o
diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c
index 085ed2c667..b7dd3602dc 100644
--- a/hw/usb/ccid-card-passthru.c
+++ b/hw/usb/ccid-card-passthru.c
@@ -9,7 +9,6 @@
*/
#include "qemu/osdep.h"
-#include "qapi/error.h"
#include <cacard/vscard_common.h>
#include "chardev/char-fe.h"
#include "qemu/error-report.h"
diff --git a/hw/usb/chipidea.c b/hw/usb/chipidea.c
new file mode 100644
index 0000000000..60d67f88b8
--- /dev/null
+++ b/hw/usb/chipidea.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2018, Impinj, Inc.
+ *
+ * Chipidea USB block emulation code
+ *
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.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 "hw/usb/hcd-ehci.h"
+#include "hw/usb/chipidea.h"
+#include "qemu/log.h"
+
+enum {
+ CHIPIDEA_USBx_DCIVERSION = 0x000,
+ CHIPIDEA_USBx_DCCPARAMS = 0x004,
+ CHIPIDEA_USBx_DCCPARAMS_HC = BIT(8),
+};
+
+static uint64_t chipidea_read(void *opaque, hwaddr offset,
+ unsigned size)
+{
+ return 0;
+}
+
+static void chipidea_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+}
+
+static const struct MemoryRegionOps chipidea_ops = {
+ .read = chipidea_read,
+ .write = chipidea_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ /*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the
+ * real device but in practice there is no reason for a guest
+ * to access this device unaligned.
+ */
+ .min_access_size = 4,
+ .max_access_size = 4,
+ .unaligned = false,
+ },
+};
+
+static uint64_t chipidea_dc_read(void *opaque, hwaddr offset,
+ unsigned size)
+{
+ switch (offset) {
+ case CHIPIDEA_USBx_DCIVERSION:
+ return 0x1;
+ case CHIPIDEA_USBx_DCCPARAMS:
+ /*
+ * Real hardware (at least i.MX7) will also report the
+ * controller as "Device Capable" (and 8 supported endpoints),
+ * but there doesn't seem to be much point in doing so, since
+ * we don't emulate that part.
+ */
+ return CHIPIDEA_USBx_DCCPARAMS_HC;
+ }
+
+ return 0;
+}
+
+static void chipidea_dc_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+}
+
+static const struct MemoryRegionOps chipidea_dc_ops = {
+ .read = chipidea_dc_read,
+ .write = chipidea_dc_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ /*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the real
+ * device but in practice there is no reason for a guest to access
+ * this device unaligned.
+ */
+ .min_access_size = 4,
+ .max_access_size = 4,
+ .unaligned = false,
+ },
+};
+
+static void chipidea_init(Object *obj)
+{
+ EHCIState *ehci = &SYS_BUS_EHCI(obj)->ehci;
+ ChipideaState *ci = CHIPIDEA(obj);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ci->iomem); i++) {
+ const struct {
+ const char *name;
+ hwaddr offset;
+ uint64_t size;
+ const struct MemoryRegionOps *ops;
+ } regions[ARRAY_SIZE(ci->iomem)] = {
+ /*
+ * Registers located between offsets 0x000 and 0xFC
+ */
+ {
+ .name = TYPE_CHIPIDEA ".misc",
+ .offset = 0x000,
+ .size = 0x100,
+ .ops = &chipidea_ops,
+ },
+ /*
+ * Registers located between offsets 0x1A4 and 0x1DC
+ */
+ {
+ .name = TYPE_CHIPIDEA ".endpoints",
+ .offset = 0x1A4,
+ .size = 0x1DC - 0x1A4 + 4,
+ .ops = &chipidea_ops,
+ },
+ /*
+ * USB_x_DCIVERSION and USB_x_DCCPARAMS
+ */
+ {
+ .name = TYPE_CHIPIDEA ".dc",
+ .offset = 0x120,
+ .size = 8,
+ .ops = &chipidea_dc_ops,
+ },
+ };
+
+ memory_region_init_io(&ci->iomem[i],
+ obj,
+ regions[i].ops,
+ ci,
+ regions[i].name,
+ regions[i].size);
+
+ memory_region_add_subregion(&ehci->mem,
+ regions[i].offset,
+ &ci->iomem[i]);
+ }
+}
+
+static void chipidea_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusEHCIClass *sec = SYS_BUS_EHCI_CLASS(klass);
+
+ /*
+ * Offsets used were taken from i.MX7Dual Applications Processor
+ * Reference Manual, Rev 0.1, p. 3177, Table 11-59
+ */
+ sec->capsbase = 0x100;
+ sec->opregbase = 0x140;
+ sec->portnr = 1;
+
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
+ dc->desc = "Chipidea USB Module";
+}
+
+static const TypeInfo chipidea_info = {
+ .name = TYPE_CHIPIDEA,
+ .parent = TYPE_SYS_BUS_EHCI,
+ .instance_size = sizeof(ChipideaState),
+ .instance_init = chipidea_init,
+ .class_init = chipidea_class_init,
+};
+
+static void chipidea_register_type(void)
+{
+ type_register_static(&chipidea_info);
+}
+type_init(chipidea_register_type)
diff --git a/hw/usb/xen-usb.c b/hw/usb/xen-usb.c
index 584a6f2442..3beeb0d170 100644
--- a/hw/usb/xen-usb.c
+++ b/hw/usb/xen-usb.c
@@ -23,13 +23,13 @@
#include <libusb.h>
#include <sys/user.h>
-#include "qemu-common.h"
#include "qemu/config-file.h"
+#include "qemu/option.h"
#include "hw/sysbus.h"
#include "hw/usb.h"
#include "hw/xen/xen_backend.h"
#include "monitor/qdev.h"
-#include "qapi/qmp/qbool.h"
+#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qstring.h"
#include "hw/xen/io/ring.h"
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index b33c5e8a03..033cc8dea1 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -26,6 +26,7 @@
#include "hw/pci/msix.h"
#include "hw/pci/pci_bridge.h"
#include "qemu/error-report.h"
+#include "qemu/option.h"
#include "qemu/range.h"
#include "sysemu/kvm.h"
#include "sysemu/sysemu.h"
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index 179c8f5768..48224493a0 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -23,6 +23,7 @@
#include "hw/virtio/virtio-balloon.h"
#include "sysemu/kvm.h"
#include "exec/address-spaces.h"
+#include "qapi/error.h"
#include "qapi/visitor.h"
#include "qapi-event.h"
#include "trace.h"
diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c
index 670114ecfe..98a5dd6689 100644
--- a/hw/watchdog/watchdog.c
+++ b/hw/watchdog/watchdog.c
@@ -23,7 +23,7 @@
#include "qemu/option.h"
#include "qemu/config-file.h"
#include "qemu/queue.h"
-#include "qapi/qmp/types.h"
+#include "qapi/error.h"
#include "sysemu/sysemu.h"
#include "sysemu/watchdog.h"
#include "qapi-event.h"
diff --git a/hw/xen/xen-common.c b/hw/xen/xen-common.c
index afa1e3f404..83099dd1b1 100644
--- a/hw/xen/xen-common.c
+++ b/hw/xen/xen-common.c
@@ -11,7 +11,6 @@
#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "hw/xen/xen_backend.h"
-#include "qmp-commands.h"
#include "chardev/char.h"
#include "sysemu/accel.h"
#include "migration/misc.h"
diff --git a/hw/xen/xen_devconfig.c b/hw/xen/xen_devconfig.c
index a80e78c0dc..fac9d3fcdc 100644
--- a/hw/xen/xen_devconfig.c
+++ b/hw/xen/xen_devconfig.c
@@ -1,5 +1,6 @@
#include "qemu/osdep.h"
#include "hw/xen/xen_backend.h"
+#include "qemu/option.h"
#include "sysemu/block-backend.h"
#include "sysemu/blockdev.h"
diff --git a/hw/xtensa/xtensa_memory.h b/hw/xtensa/xtensa_memory.h
index cab4d172d4..e9aa08749d 100644
--- a/hw/xtensa/xtensa_memory.h
+++ b/hw/xtensa/xtensa_memory.h
@@ -28,7 +28,6 @@
#ifndef _XTENSA_MEMORY_H
#define _XTENSA_MEMORY_H
-#include "qemu/osdep.h"
#include "qemu-common.h"
#include "cpu.h"
#include "exec/memory.h"
diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
index 76ea970215..70686a2eb1 100644
--- a/hw/xtensa/xtfpga.c
+++ b/hw/xtensa/xtfpga.c
@@ -27,7 +27,6 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
-#include "qemu-common.h"
#include "cpu.h"
#include "sysemu/sysemu.h"
#include "hw/boards.h"
@@ -43,6 +42,7 @@
#include "chardev/char.h"
#include "sysemu/device_tree.h"
#include "qemu/error-report.h"
+#include "qemu/option.h"
#include "bootparam.h"
#include "xtensa_memory.h"