aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS4
-rw-r--r--accel/kvm/kvm-accel-ops.c12
-rw-r--r--accel/meson.build12
-rw-r--r--accel/qtest/qtest.c1
-rw-r--r--accel/stubs/hax-stub.c2
-rw-r--r--accel/stubs/kvm-stub.c5
-rw-r--r--accel/stubs/meson.build11
-rw-r--r--accel/tcg/cpu-exec.c4
-rw-r--r--accel/tcg/tcg-accel-ops-icount.c1
-rw-r--r--accel/tcg/tcg-accel-ops-mttcg.c1
-rw-r--r--accel/tcg/tcg-accel-ops-rr.c1
-rw-r--r--accel/tcg/tcg-accel-ops.c1
-rw-r--r--block/blkverify.c1
-rw-r--r--block/block-copy.c1
-rw-r--r--block/commit.c1
-rw-r--r--block/crypto.c1
-rw-r--r--block/dmg.c1
-rw-r--r--block/export/fuse.c1
-rw-r--r--block/file-posix.c1
-rw-r--r--block/io.c1
-rw-r--r--block/mirror.c1
-rw-r--r--block/nvme.c1
-rw-r--r--block/parallels-ext.c1
-rw-r--r--block/parallels.c1
-rw-r--r--block/qcow.c1
-rw-r--r--block/qcow2-cache.c1
-rw-r--r--block/qcow2-cluster.c1
-rw-r--r--block/qcow2-refcount.c1
-rw-r--r--block/qcow2-snapshot.c1
-rw-r--r--block/qcow2.c1
-rw-r--r--block/qed-l2-cache.c1
-rw-r--r--block/qed-table.c1
-rw-r--r--block/qed.c1
-rw-r--r--block/quorum.c1
-rw-r--r--block/raw-format.c1
-rw-r--r--block/vdi.c1
-rw-r--r--block/vhdx-log.c1
-rw-r--r--block/vhdx.c1
-rw-r--r--block/vmdk.c1
-rw-r--r--block/vpc.c1
-rw-r--r--block/win32-aio.c1
-rwxr-xr-xconfigure4
-rw-r--r--cpu.c8
-rw-r--r--docs/about/deprecated.rst8
-rw-r--r--docs/interop/vhost-user.rst20
-rw-r--r--docs/pcie_sriov.txt115
-rw-r--r--docs/specs/acpi_erst.rst200
-rw-r--r--docs/specs/index.rst1
-rw-r--r--docs/specs/pci-ids.txt1
-rw-r--r--fsdev/file-op-9p.h9
-rw-r--r--fsdev/meson.build1
-rw-r--r--fsdev/p9array.h38
-rw-r--r--hw/9pfs/9p-local.c27
-rw-r--r--hw/9pfs/9p-proxy.c38
-rw-r--r--hw/9pfs/9p-synth.c6
-rw-r--r--hw/9pfs/9p-util-darwin.c97
-rw-r--r--hw/9pfs/9p-util-linux.c (renamed from hw/9pfs/9p-util.c)8
-rw-r--r--hw/9pfs/9p-util.h78
-rw-r--r--hw/9pfs/9p.c104
-rw-r--r--hw/9pfs/9p.h30
-rw-r--r--hw/9pfs/codir.c34
-rw-r--r--hw/9pfs/coth.h4
-rw-r--r--hw/9pfs/meson.build3
-rw-r--r--hw/acpi/aml-build.c8
-rw-r--r--hw/acpi/erst.c5
-rw-r--r--hw/acpi/pcihp.c12
-rw-r--r--hw/arm/virt.c7
-rw-r--r--hw/audio/cs4231a.c2
-rw-r--r--hw/audio/gus.c2
-rw-r--r--hw/audio/sb16.c2
-rw-r--r--hw/block/dataplane/xen-block.c1
-rw-r--r--hw/block/fdc-isa.c2
-rw-r--r--hw/block/fdc.c1
-rw-r--r--hw/char/parallel.c2
-rw-r--r--hw/char/serial-isa.c2
-rw-r--r--hw/i386/acpi-build.c8
-rw-r--r--hw/i386/acpi-microvm.c6
-rw-r--r--hw/i386/intel_iommu.c14
-rw-r--r--hw/i386/intel_iommu_internal.h1
-rw-r--r--hw/i386/pc.c30
-rw-r--r--hw/i386/pc_piix.c1
-rw-r--r--hw/i386/x86.c16
-rw-r--r--hw/ide/core.c1
-rw-r--r--hw/ide/isa.c2
-rw-r--r--hw/input/pckbd.c26
-rw-r--r--hw/intc/arm_gicv3.c8
-rw-r--r--hw/intc/arm_gicv3_cpuif.c3
-rw-r--r--hw/intc/arm_gicv3_dist.c4
-rw-r--r--hw/intc/arm_gicv3_its.c69
-rw-r--r--hw/intc/trace-events21
-rw-r--r--hw/ipmi/isa_ipmi_bt.c2
-rw-r--r--hw/ipmi/isa_ipmi_kcs.c2
-rw-r--r--hw/isa/isa-bus.c37
-rw-r--r--hw/isa/piix4.c56
-rw-r--r--hw/mips/gt64xxx_pci.c80
-rw-r--r--hw/mips/malta.c7
-rw-r--r--hw/misc/pvpanic-isa.c4
-rw-r--r--hw/misc/pvpanic-pci.c4
-rw-r--r--hw/misc/pvpanic.c5
-rw-r--r--hw/net/ne2000-isa.c2
-rw-r--r--hw/net/virtio-net.c13
-rw-r--r--hw/pci-bridge/pci_expander_bridge.c6
-rw-r--r--hw/pci-bridge/xio3130_downstream.c5
-rw-r--r--hw/pci-bridge/xio3130_upstream.c2
-rw-r--r--hw/pci/meson.build1
-rw-r--r--hw/pci/pci.c104
-rw-r--r--hw/pci/pcie.c16
-rw-r--r--hw/pci/pcie_sriov.c302
-rw-r--r--hw/pci/trace-events5
-rw-r--r--hw/ppc/spapr.c1
-rw-r--r--hw/ppc/spapr_softmmu.c1
-rw-r--r--hw/rtc/m48t59-isa.c9
-rw-r--r--hw/rtc/mc146818rtc.c13
-rw-r--r--hw/scsi/scsi-disk.c1
-rw-r--r--hw/smbios/smbios.c80
-rw-r--r--hw/tpm/tpm_ppi.c2
-rw-r--r--hw/tpm/tpm_tis_isa.c2
-rw-r--r--hw/virtio/trace-events4
-rw-r--r--hw/virtio/vhost-user-i2c.c11
-rw-r--r--hw/virtio/vhost-user.c61
-rw-r--r--hw/virtio/vhost-vdpa.c21
-rw-r--r--hw/virtio/vhost-vsock-common.c10
-rw-r--r--hw/virtio/vhost.c6
-rw-r--r--hw/virtio/virtio-bus.c12
-rw-r--r--hw/virtio/virtio-iommu.c99
-rw-r--r--include/exec/cpu-all.h4
-rw-r--r--include/exec/cpu-common.h39
-rw-r--r--include/exec/cpu_ldst.h1
-rw-r--r--include/exec/exec-all.h26
-rw-r--r--include/exec/gdbstub.h25
-rw-r--r--include/exec/poison.h2
-rw-r--r--include/hw/acpi/acpi-defs.h1
-rw-r--r--include/hw/arm/virt.h1
-rw-r--r--include/hw/core/cpu.h33
-rw-r--r--include/hw/i386/intel_iommu.h1
-rw-r--r--include/hw/i386/pc.h2
-rw-r--r--include/hw/i386/x86.h2
-rw-r--r--include/hw/input/i8042.h15
-rw-r--r--include/hw/isa/isa.h3
-rw-r--r--include/hw/mips/mips.h3
-rw-r--r--include/hw/misc/pvpanic.h8
-rw-r--r--include/hw/pci-bridge/xio3130_downstream.h15
-rw-r--r--include/hw/pci/pci.h12
-rw-r--r--include/hw/pci/pci_regs.h1
-rw-r--r--include/hw/pci/pcie.h7
-rw-r--r--include/hw/pci/pcie_sriov.h77
-rw-r--r--include/hw/rtc/mc146818rtc.h1
-rw-r--r--include/hw/southbridge/piix.h2
-rw-r--r--include/hw/virtio/vhost-user-i2c.h3
-rw-r--r--include/hw/virtio/vhost-user.h3
-rw-r--r--include/hw/virtio/virtio-iommu.h1
-rw-r--r--include/qemu-common.h2
-rw-r--r--include/qemu/event_notifier.h1
-rw-r--r--include/qemu/memalign.h61
-rw-r--r--include/qemu/osdep.h31
-rw-r--r--include/qemu/typedefs.h4
-rw-r--r--include/qemu/xattr.h4
-rw-r--r--include/standard-headers/linux/pvpanic.h9
-rw-r--r--include/sysemu/accel-ops.h3
-rw-r--r--include/sysemu/arch_init.h2
-rw-r--r--include/sysemu/hax.h18
-rw-r--r--include/sysemu/hw_accel.h5
-rw-r--r--include/sysemu/kvm.h6
-rw-r--r--include/sysemu/memory_mapping.h5
-rw-r--r--meson.build26
-rw-r--r--nbd/server.c1
-rw-r--r--net/l2tpv3.c2
-rw-r--r--pc-bios/bios-256k.binbin262144 -> 262144 bytes
-rw-r--r--pc-bios/bios-microvm.binbin131072 -> 131072 bytes
-rw-r--r--pc-bios/bios.binbin131072 -> 131072 bytes
-rw-r--r--pc-bios/vgabios-ati.binbin39936 -> 39936 bytes
-rw-r--r--pc-bios/vgabios-bochs-display.binbin28672 -> 28672 bytes
-rw-r--r--pc-bios/vgabios-cirrus.binbin39424 -> 39424 bytes
-rw-r--r--pc-bios/vgabios-qxl.binbin39424 -> 39424 bytes
-rw-r--r--pc-bios/vgabios-ramfb.binbin28672 -> 28672 bytes
-rw-r--r--pc-bios/vgabios-stdvga.binbin39424 -> 39424 bytes
-rw-r--r--pc-bios/vgabios-virtio.binbin39424 -> 39424 bytes
-rw-r--r--pc-bios/vgabios-vmware.binbin39424 -> 39424 bytes
-rw-r--r--pc-bios/vgabios.binbin38912 -> 38912 bytes
-rw-r--r--plugins/loader.c1
-rw-r--r--python/qemu/aqmp/legacy.py7
-rw-r--r--python/qemu/aqmp/protocol.py381
-rw-r--r--python/tests/protocol.py45
-rw-r--r--qemu-img.c1
-rw-r--r--qemu-io-cmds.c1
-rw-r--r--qemu-options.hx3
-rw-r--r--qom/object.c7
m---------roms/seabios0
-rwxr-xr-xscripts/qmp/qmp-shell-wrap2
-rwxr-xr-xscripts/update-linux-headers.sh3
-rw-r--r--softmmu/arch_init.c9
-rw-r--r--softmmu/cpu-timers.c1
-rw-r--r--softmmu/cpus.c23
-rw-r--r--softmmu/globals.c2
-rw-r--r--softmmu/memory_mapping.c1
-rw-r--r--softmmu/meson.build24
-rw-r--r--softmmu/physmem.c8
-rw-r--r--softmmu/qdev-monitor.c7
-rw-r--r--softmmu/vl.c5
-rw-r--r--target/alpha/cpu-qom.h3
-rw-r--r--target/alpha/cpu.h11
-rw-r--r--target/alpha/translate.c1
-rw-r--r--target/arm/cpu-qom.h3
-rw-r--r--target/arm/cpu.c6
-rw-r--r--target/arm/cpu.h12
-rw-r--r--target/arm/cpu64.c24
-rw-r--r--target/arm/hvf_arm.h2
-rw-r--r--target/arm/translate-neon.c13
-rw-r--r--target/avr/cpu-qom.h3
-rw-r--r--target/avr/cpu.h13
-rw-r--r--target/cris/cpu-qom.h3
-rw-r--r--target/cris/cpu.h7
-rw-r--r--target/hexagon/cpu.h23
-rw-r--r--target/hppa/cpu-qom.h3
-rw-r--r--target/hppa/cpu.h12
-rw-r--r--target/i386/cpu-qom.h3
-rw-r--r--target/i386/cpu.h7
-rw-r--r--target/i386/hax/hax-all.c11
-rw-r--r--target/i386/hvf/hvf.c1
-rw-r--r--target/i386/hvf/x86_emu.c110
-rw-r--r--target/i386/hvf/x86_emu.h22
-rw-r--r--target/i386/kvm/kvm.c1
-rw-r--r--target/i386/nvmm/nvmm-all.c14
-rw-r--r--target/i386/tcg/sysemu/excp_helper.c1
-rw-r--r--target/i386/tcg/sysemu/misc_helper.c1
-rw-r--r--target/i386/whpx/whpx-accel-ops.c6
-rw-r--r--target/i386/whpx/whpx-all.c18
-rw-r--r--target/m68k/cpu-qom.h3
-rw-r--r--target/m68k/cpu.h7
-rw-r--r--target/microblaze/cpu-qom.h3
-rw-r--r--target/microblaze/cpu.h9
-rw-r--r--target/microblaze/mmu.h2
-rw-r--r--target/mips/cpu-qom.h3
-rw-r--r--target/mips/cpu.c11
-rw-r--r--target/mips/cpu.h19
-rw-r--r--target/mips/internal.h24
-rw-r--r--target/nios2/cpu.h9
-rw-r--r--target/nios2/mmu.h2
-rw-r--r--target/openrisc/cpu.h17
-rw-r--r--target/ppc/cpu-qom.h5
-rw-r--r--target/ppc/cpu.h7
-rw-r--r--target/riscv/cpu.h11
-rw-r--r--target/riscv/csr.c1
-rw-r--r--target/riscv/pmp.h2
-rw-r--r--target/rx/cpu-qom.h5
-rw-r--r--target/rx/cpu.h6
-rw-r--r--target/s390x/cpu-qom.h7
-rw-r--r--target/s390x/cpu.h7
-rw-r--r--target/sh4/cpu-qom.h3
-rw-r--r--target/sh4/cpu.h7
-rw-r--r--target/sparc/cpu-qom.h3
-rw-r--r--target/sparc/cpu.h9
-rw-r--r--target/tricore/cpu-qom.h3
-rw-r--r--target/tricore/cpu.h10
-rw-r--r--target/xtensa/cpu-qom.h3
-rw-r--r--target/xtensa/cpu.h13
-rw-r--r--tcg/region.c1
-rw-r--r--tests/avocado/avocado_qemu/__init__.py2
-rw-r--r--tests/avocado/boot_linux.py2
-rw-r--r--tests/avocado/linux_ssh_mips_malta.py3
-rw-r--r--tests/bench/atomic_add-bench.c1
-rw-r--r--tests/bench/qht-bench.c1
-rw-r--r--tests/data/acpi/q35/FACPbin244 -> 244 bytes
-rw-r--r--tests/data/acpi/q35/FACP.nosmmbin244 -> 244 bytes
-rw-r--r--tests/data/acpi/q35/FACP.slicbin244 -> 244 bytes
-rw-r--r--tests/data/acpi/q35/FACP.xapicbin244 -> 244 bytes
-rw-r--r--tests/qemu-iotests/172.out26
-rw-r--r--tests/qtest/virtio-9p-test.c2
-rw-r--r--tests/qtest/virtio-iommu-test.c2
-rw-r--r--tests/tcg/s390x/exrl-trt.c8
-rw-r--r--tests/tcg/s390x/exrl-trtr.c8
-rw-r--r--tests/tcg/s390x/mie3-mvcrl.c10
-rw-r--r--tests/tcg/s390x/mie3-sel.c35
-rw-r--r--tests/tcg/s390x/mvc.c4
-rw-r--r--tests/tcg/s390x/mvo.c4
-rw-r--r--tests/tcg/s390x/pack.c2
-rw-r--r--tests/unit/ptimer-test-stubs.c1
-rwxr-xr-xtests/vm/haiku.x86_648
-rw-r--r--ui/cocoa.m112
-rw-r--r--util/atomic64.c1
-rw-r--r--util/event_notifier-posix.c5
-rw-r--r--util/memalign.c92
-rw-r--r--util/meson.build1
-rw-r--r--util/osdep.c21
-rw-r--r--util/oslib-posix.c46
-rw-r--r--util/oslib-win32.c35
-rw-r--r--util/qht.c1
287 files changed, 2822 insertions, 1316 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 4f0cc1e448..38d1ac8803 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1819,7 +1819,6 @@ F: docs/specs/acpi_hw_reduced_hotplug.rst
ACPI/VIOT
M: Jean-Philippe Brucker <jean-philippe@linaro.org>
-R: Ani Sinha <ani@anisinha.ca>
S: Supported
F: hw/acpi/viot.c
F: hw/acpi/viot.h
@@ -3611,7 +3610,8 @@ FreeBSD Hosted Continuous Integration
M: Ed Maste <emaste@freebsd.org>
M: Li-Wen Hsu <lwhsu@freebsd.org>
S: Maintained
-F: .cirrus.yml
+F: .gitlab-ci.d/cirrus/freebsd*
+F: tests/vm/freebsd
W: https://cirrus-ci.com/github/qemu/qemu
Windows Hosted Continuous Integration
diff --git a/accel/kvm/kvm-accel-ops.c b/accel/kvm/kvm-accel-ops.c
index 7516c67a3f..c4244a23c6 100644
--- a/accel/kvm/kvm-accel-ops.c
+++ b/accel/kvm/kvm-accel-ops.c
@@ -74,11 +74,23 @@ static void kvm_start_vcpu_thread(CPUState *cpu)
cpu, QEMU_THREAD_JOINABLE);
}
+static bool kvm_vcpu_thread_is_idle(CPUState *cpu)
+{
+ return !kvm_halt_in_kernel();
+}
+
+static bool kvm_cpus_are_resettable(void)
+{
+ return !kvm_enabled() || kvm_cpu_check_are_resettable();
+}
+
static void kvm_accel_ops_class_init(ObjectClass *oc, void *data)
{
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
ops->create_vcpu_thread = kvm_start_vcpu_thread;
+ ops->cpu_thread_is_idle = kvm_vcpu_thread_is_idle;
+ ops->cpus_are_resettable = kvm_cpus_are_resettable;
ops->synchronize_post_reset = kvm_cpu_synchronize_post_reset;
ops->synchronize_post_init = kvm_cpu_synchronize_post_init;
ops->synchronize_state = kvm_cpu_synchronize_state;
diff --git a/accel/meson.build b/accel/meson.build
index dfd808d2c8..b9a963cf80 100644
--- a/accel/meson.build
+++ b/accel/meson.build
@@ -2,12 +2,14 @@ specific_ss.add(files('accel-common.c'))
softmmu_ss.add(files('accel-softmmu.c'))
user_ss.add(files('accel-user.c'))
-subdir('hvf')
-subdir('qtest')
-subdir('kvm')
subdir('tcg')
-subdir('xen')
-subdir('stubs')
+if have_system
+ subdir('hvf')
+ subdir('qtest')
+ subdir('kvm')
+ subdir('xen')
+ subdir('stubs')
+endif
dummy_ss = ss.source_set()
dummy_ss.add(files(
diff --git a/accel/qtest/qtest.c b/accel/qtest/qtest.c
index 7e6b8110d5..f6056ac836 100644
--- a/accel/qtest/qtest.c
+++ b/accel/qtest/qtest.c
@@ -20,7 +20,6 @@
#include "qemu/accel.h"
#include "sysemu/qtest.h"
#include "sysemu/cpus.h"
-#include "sysemu/cpu-timers.h"
#include "qemu/guest-random.h"
#include "qemu/main-loop.h"
#include "hw/core/cpu.h"
diff --git a/accel/stubs/hax-stub.c b/accel/stubs/hax-stub.c
index 49077f88e3..2fe31aaa9a 100644
--- a/accel/stubs/hax-stub.c
+++ b/accel/stubs/hax-stub.c
@@ -16,6 +16,8 @@
#include "qemu/osdep.h"
#include "sysemu/hax.h"
+bool hax_allowed;
+
int hax_sync_vcpus(void)
{
return 0;
diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c
index 5319573e00..7e0fb884b9 100644
--- a/accel/stubs/kvm-stub.c
+++ b/accel/stubs/kvm-stub.c
@@ -12,10 +12,7 @@
#include "qemu/osdep.h"
#include "sysemu/kvm.h"
-
-#ifndef CONFIG_USER_ONLY
#include "hw/pci/msi.h"
-#endif
KVMState *kvm_state;
bool kvm_kernel_irqchip;
@@ -80,7 +77,6 @@ int kvm_on_sigbus(int code, void *addr)
return 1;
}
-#ifndef CONFIG_USER_ONLY
int kvm_irqchip_add_msi_route(KVMState *s, int vector, PCIDevice *dev)
{
return -ENOSYS;
@@ -152,4 +148,3 @@ bool kvm_dirty_ring_enabled(void)
{
return false;
}
-#endif
diff --git a/accel/stubs/meson.build b/accel/stubs/meson.build
index 12dd1539af..0249b9258f 100644
--- a/accel/stubs/meson.build
+++ b/accel/stubs/meson.build
@@ -1,4 +1,7 @@
-specific_ss.add(when: 'CONFIG_HAX', if_false: files('hax-stub.c'))
-specific_ss.add(when: 'CONFIG_XEN', if_false: files('xen-stub.c'))
-specific_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c'))
-specific_ss.add(when: 'CONFIG_TCG', if_false: files('tcg-stub.c'))
+sysemu_stubs_ss = ss.source_set()
+sysemu_stubs_ss.add(when: 'CONFIG_HAX', if_false: files('hax-stub.c'))
+sysemu_stubs_ss.add(when: 'CONFIG_XEN', if_false: files('xen-stub.c'))
+sysemu_stubs_ss.add(when: 'CONFIG_KVM', if_false: files('kvm-stub.c'))
+sysemu_stubs_ss.add(when: 'CONFIG_TCG', if_false: files('tcg-stub.c'))
+
+specific_ss.add_all(when: ['CONFIG_SOFTMMU'], if_true: sysemu_stubs_ss)
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index c68270f794..c997c2e8e0 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -422,7 +422,7 @@ static void cpu_exec_exit(CPUState *cpu)
void cpu_exec_step_atomic(CPUState *cpu)
{
- CPUArchState *env = (CPUArchState *)cpu->env_ptr;
+ CPUArchState *env = cpu->env_ptr;
TranslationBlock *tb;
target_ulong cs_base, pc;
uint32_t flags, cflags;
@@ -532,7 +532,7 @@ TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
struct tb_desc desc;
uint32_t h;
- desc.env = (CPUArchState *)cpu->env_ptr;
+ desc.env = cpu->env_ptr;
desc.cs_base = cs_base;
desc.flags = flags;
desc.cflags = cflags;
diff --git a/accel/tcg/tcg-accel-ops-icount.c b/accel/tcg/tcg-accel-ops-icount.c
index ea42d1d51b..bdaf2c943b 100644
--- a/accel/tcg/tcg-accel-ops-icount.c
+++ b/accel/tcg/tcg-accel-ops-icount.c
@@ -27,6 +27,7 @@
#include "qemu-common.h"
#include "sysemu/tcg.h"
#include "sysemu/replay.h"
+#include "sysemu/cpu-timers.h"
#include "qemu/main-loop.h"
#include "qemu/guest-random.h"
#include "exec/exec-all.h"
diff --git a/accel/tcg/tcg-accel-ops-mttcg.c b/accel/tcg/tcg-accel-ops-mttcg.c
index 29632bd4c0..dc421c8fd7 100644
--- a/accel/tcg/tcg-accel-ops-mttcg.c
+++ b/accel/tcg/tcg-accel-ops-mttcg.c
@@ -27,6 +27,7 @@
#include "qemu-common.h"
#include "sysemu/tcg.h"
#include "sysemu/replay.h"
+#include "sysemu/cpu-timers.h"
#include "qemu/main-loop.h"
#include "qemu/notify.h"
#include "qemu/guest-random.h"
diff --git a/accel/tcg/tcg-accel-ops-rr.c b/accel/tcg/tcg-accel-ops-rr.c
index bf59f53dbc..a805fb6bdd 100644
--- a/accel/tcg/tcg-accel-ops-rr.c
+++ b/accel/tcg/tcg-accel-ops-rr.c
@@ -27,6 +27,7 @@
#include "qemu-common.h"
#include "sysemu/tcg.h"
#include "sysemu/replay.h"
+#include "sysemu/cpu-timers.h"
#include "qemu/main-loop.h"
#include "qemu/notify.h"
#include "qemu/guest-random.h"
diff --git a/accel/tcg/tcg-accel-ops.c b/accel/tcg/tcg-accel-ops.c
index 1a8e8390bd..ea7dcad674 100644
--- a/accel/tcg/tcg-accel-ops.c
+++ b/accel/tcg/tcg-accel-ops.c
@@ -29,6 +29,7 @@
#include "qemu-common.h"
#include "sysemu/tcg.h"
#include "sysemu/replay.h"
+#include "sysemu/cpu-timers.h"
#include "qemu/main-loop.h"
#include "qemu/guest-random.h"
#include "exec/exec-all.h"
diff --git a/block/blkverify.c b/block/blkverify.c
index d1facf5ba9..53ba1c9195 100644
--- a/block/blkverify.c
+++ b/block/blkverify.c
@@ -16,6 +16,7 @@
#include "qemu/cutils.h"
#include "qemu/module.h"
#include "qemu/option.h"
+#include "qemu/memalign.h"
typedef struct {
BdrvChild *test_file;
diff --git a/block/block-copy.c b/block/block-copy.c
index ef948dccec..ec46775ea5 100644
--- a/block/block-copy.c
+++ b/block/block-copy.c
@@ -23,6 +23,7 @@
#include "qemu/coroutine.h"
#include "block/aio_task.h"
#include "qemu/error-report.h"
+#include "qemu/memalign.h"
#define BLOCK_COPY_MAX_COPY_RANGE (16 * MiB)
#define BLOCK_COPY_MAX_BUFFER (1 * MiB)
diff --git a/block/commit.c b/block/commit.c
index c76899f640..851d1c557a 100644
--- a/block/commit.c
+++ b/block/commit.c
@@ -20,6 +20,7 @@
#include "qapi/error.h"
#include "qapi/qmp/qerror.h"
#include "qemu/ratelimit.h"
+#include "qemu/memalign.h"
#include "sysemu/block-backend.h"
enum {
diff --git a/block/crypto.c b/block/crypto.c
index 9d5fecbef8..1ba82984ef 100644
--- a/block/crypto.c
+++ b/block/crypto.c
@@ -31,6 +31,7 @@
#include "qemu/module.h"
#include "qemu/option.h"
#include "qemu/cutils.h"
+#include "qemu/memalign.h"
#include "crypto.h"
typedef struct BlockCrypto BlockCrypto;
diff --git a/block/dmg.c b/block/dmg.c
index 447901fbb8..c626587f9c 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -27,6 +27,7 @@
#include "qemu/bswap.h"
#include "qemu/error-report.h"
#include "qemu/module.h"
+#include "qemu/memalign.h"
#include "dmg.h"
int (*dmg_uncompress_bz2)(char *next_in, unsigned int avail_in,
diff --git a/block/export/fuse.c b/block/export/fuse.c
index 5029e70f84..e80b24a867 100644
--- a/block/export/fuse.c
+++ b/block/export/fuse.c
@@ -19,6 +19,7 @@
#define FUSE_USE_VERSION 31
#include "qemu/osdep.h"
+#include "qemu/memalign.h"
#include "block/aio.h"
#include "block/block.h"
#include "block/export.h"
diff --git a/block/file-posix.c b/block/file-posix.c
index 1f1756e192..c000a61db2 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -31,6 +31,7 @@
#include "qemu/module.h"
#include "qemu/option.h"
#include "qemu/units.h"
+#include "qemu/memalign.h"
#include "trace.h"
#include "block/thread-pool.h"
#include "qemu/iov.h"
diff --git a/block/io.c b/block/io.c
index f0c8da6b9f..3280144a17 100644
--- a/block/io.c
+++ b/block/io.c
@@ -32,6 +32,7 @@
#include "block/coroutines.h"
#include "block/write-threshold.h"
#include "qemu/cutils.h"
+#include "qemu/memalign.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "qemu/main-loop.h"
diff --git a/block/mirror.c b/block/mirror.c
index ce6bc58d1f..d8ecb9efa2 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -23,6 +23,7 @@
#include "qapi/qmp/qerror.h"
#include "qemu/ratelimit.h"
#include "qemu/bitmap.h"
+#include "qemu/memalign.h"
#define MAX_IN_FLIGHT 16
#define MAX_IO_BYTES (1 << 20) /* 1 Mb */
diff --git a/block/nvme.c b/block/nvme.c
index dd20de3865..552029931d 100644
--- a/block/nvme.c
+++ b/block/nvme.c
@@ -21,6 +21,7 @@
#include "qemu/module.h"
#include "qemu/cutils.h"
#include "qemu/option.h"
+#include "qemu/memalign.h"
#include "qemu/vfio-helpers.h"
#include "block/block_int.h"
#include "sysemu/replay.h"
diff --git a/block/parallels-ext.c b/block/parallels-ext.c
index e0dd0975c6..cb22a427d7 100644
--- a/block/parallels-ext.c
+++ b/block/parallels-ext.c
@@ -29,6 +29,7 @@
#include "parallels.h"
#include "crypto/hash.h"
#include "qemu/uuid.h"
+#include "qemu/memalign.h"
#define PARALLELS_FORMAT_EXTENSION_MAGIC 0xAB234CEF23DCEA87ULL
diff --git a/block/parallels.c b/block/parallels.c
index e58c828422..cd23e02d06 100644
--- a/block/parallels.c
+++ b/block/parallels.c
@@ -41,6 +41,7 @@
#include "qapi/qapi-visit-block-core.h"
#include "qemu/bswap.h"
#include "qemu/bitmap.h"
+#include "qemu/memalign.h"
#include "migration/blocker.h"
#include "parallels.h"
diff --git a/block/qcow.c b/block/qcow.c
index c39940f33e..4fba1b9e36 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -32,6 +32,7 @@
#include "qemu/option.h"
#include "qemu/bswap.h"
#include "qemu/cutils.h"
+#include "qemu/memalign.h"
#include <zlib.h>
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qstring.h"
diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
index 7444b9c4ab..8a0105911f 100644
--- a/block/qcow2-cache.c
+++ b/block/qcow2-cache.c
@@ -23,6 +23,7 @@
*/
#include "qemu/osdep.h"
+#include "qemu/memalign.h"
#include "qcow2.h"
#include "trace.h"
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 21884a1ab9..20a16ba6ee 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -28,6 +28,7 @@
#include "qapi/error.h"
#include "qcow2.h"
#include "qemu/bswap.h"
+#include "qemu/memalign.h"
#include "trace.h"
int qcow2_shrink_l1_table(BlockDriverState *bs, uint64_t exact_size)
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 4614572252..94033972be 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -28,6 +28,7 @@
#include "qemu/range.h"
#include "qemu/bswap.h"
#include "qemu/cutils.h"
+#include "qemu/memalign.h"
#include "trace.h"
static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size,
diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
index 71ddb08c21..075269a023 100644
--- a/block/qcow2-snapshot.c
+++ b/block/qcow2-snapshot.c
@@ -29,6 +29,7 @@
#include "qemu/bswap.h"
#include "qemu/error-report.h"
#include "qemu/cutils.h"
+#include "qemu/memalign.h"
static void qcow2_free_single_snapshot(BlockDriverState *bs, int i)
{
diff --git a/block/qcow2.c b/block/qcow2.c
index c8115e1cba..b5c47931ef 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -38,6 +38,7 @@
#include "qemu/option_int.h"
#include "qemu/cutils.h"
#include "qemu/bswap.h"
+#include "qemu/memalign.h"
#include "qapi/qobject-input-visitor.h"
#include "qapi/qapi-visit-block-core.h"
#include "crypto.h"
diff --git a/block/qed-l2-cache.c b/block/qed-l2-cache.c
index b548362398..caf2c024c2 100644
--- a/block/qed-l2-cache.c
+++ b/block/qed-l2-cache.c
@@ -51,6 +51,7 @@
*/
#include "qemu/osdep.h"
+#include "qemu/memalign.h"
#include "trace.h"
#include "qed.h"
diff --git a/block/qed-table.c b/block/qed-table.c
index 405d446cbe..1cc844b1a5 100644
--- a/block/qed-table.c
+++ b/block/qed-table.c
@@ -17,6 +17,7 @@
#include "qemu/sockets.h" /* for EINPROGRESS on Windows */
#include "qed.h"
#include "qemu/bswap.h"
+#include "qemu/memalign.h"
/* Called with table_lock held. */
static int coroutine_fn qed_read_table(BDRVQEDState *s, uint64_t offset,
diff --git a/block/qed.c b/block/qed.c
index 558d3646c4..f34d9a3ac1 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -20,6 +20,7 @@
#include "qemu/main-loop.h"
#include "qemu/module.h"
#include "qemu/option.h"
+#include "qemu/memalign.h"
#include "trace.h"
#include "qed.h"
#include "sysemu/block-backend.h"
diff --git a/block/quorum.c b/block/quorum.c
index c28dda7baa..f33f30d36b 100644
--- a/block/quorum.c
+++ b/block/quorum.c
@@ -17,6 +17,7 @@
#include "qemu/cutils.h"
#include "qemu/module.h"
#include "qemu/option.h"
+#include "qemu/memalign.h"
#include "block/block_int.h"
#include "block/coroutines.h"
#include "block/qdict.h"
diff --git a/block/raw-format.c b/block/raw-format.c
index bda757fd19..69fd650eaf 100644
--- a/block/raw-format.c
+++ b/block/raw-format.c
@@ -31,6 +31,7 @@
#include "qapi/error.h"
#include "qemu/module.h"
#include "qemu/option.h"
+#include "qemu/memalign.h"
typedef struct BDRVRawState {
uint64_t offset;
diff --git a/block/vdi.c b/block/vdi.c
index bdc58d726e..cca3a3a356 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -64,6 +64,7 @@
#include "qemu/coroutine.h"
#include "qemu/cutils.h"
#include "qemu/uuid.h"
+#include "qemu/memalign.h"
/* Code configuration options. */
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
index 7672161d95..ff0d4e0da0 100644
--- a/block/vhdx-log.c
+++ b/block/vhdx-log.c
@@ -23,6 +23,7 @@
#include "block/block_int.h"
#include "qemu/error-report.h"
#include "qemu/bswap.h"
+#include "qemu/memalign.h"
#include "vhdx.h"
diff --git a/block/vhdx.c b/block/vhdx.c
index 356ec4c455..410c6f9610 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -25,6 +25,7 @@
#include "qemu/crc32c.h"
#include "qemu/bswap.h"
#include "qemu/error-report.h"
+#include "qemu/memalign.h"
#include "vhdx.h"
#include "migration/blocker.h"
#include "qemu/uuid.h"
diff --git a/block/vmdk.c b/block/vmdk.c
index 0dfab6e941..37c0946066 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -33,6 +33,7 @@
#include "qemu/module.h"
#include "qemu/option.h"
#include "qemu/bswap.h"
+#include "qemu/memalign.h"
#include "migration/blocker.h"
#include "qemu/cutils.h"
#include <zlib.h>
diff --git a/block/vpc.c b/block/vpc.c
index 297a26262a..4d8f16e199 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -33,6 +33,7 @@
#include "migration/blocker.h"
#include "qemu/bswap.h"
#include "qemu/uuid.h"
+#include "qemu/memalign.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qobject-input-visitor.h"
#include "qapi/qapi-visit-block-core.h"
diff --git a/block/win32-aio.c b/block/win32-aio.c
index c57e10c997..aadc7b1bc3 100644
--- a/block/win32-aio.c
+++ b/block/win32-aio.c
@@ -29,6 +29,7 @@
#include "block/raw-aio.h"
#include "qemu/event_notifier.h"
#include "qemu/iov.h"
+#include "qemu/memalign.h"
#include <windows.h>
#include <winioctl.h>
diff --git a/configure b/configure
index 81618708e4..886000346a 100755
--- a/configure
+++ b/configure
@@ -1659,8 +1659,8 @@ fi
# vhost interdependencies and host support
# vhost backends
-if test "$vhost_user" = "yes" && test "$linux" != "yes"; then
- error_exit "vhost-user is only available on Linux"
+if test "$vhost_user" = "yes" && test "$mingw32" = "yes"; then
+ error_exit "vhost-user is not available on Windows"
fi
test "$vhost_vdpa" = "" && vhost_vdpa=$linux
if test "$vhost_vdpa" = "yes" && test "$linux" != "yes"; then
diff --git a/cpu.c b/cpu.c
index 3ea38aea70..d564886149 100644
--- a/cpu.c
+++ b/cpu.c
@@ -35,10 +35,12 @@
#include "sysemu/tcg.h"
#include "sysemu/kvm.h"
#include "sysemu/replay.h"
+#include "exec/exec-all.h"
#include "exec/translate-all.h"
#include "exec/log.h"
#include "hw/core/accel-cpu.h"
#include "trace/trace-root.h"
+#include "qemu/accel.h"
uintptr_t qemu_host_page_size;
intptr_t qemu_host_page_mask;
@@ -415,11 +417,11 @@ void cpu_abort(CPUState *cpu, const char *fmt, ...)
/* physical memory access (slow version, mainly for debug) */
#if defined(CONFIG_USER_ONLY)
-int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
- void *ptr, target_ulong len, bool is_write)
+int cpu_memory_rw_debug(CPUState *cpu, vaddr addr,
+ void *ptr, size_t len, bool is_write)
{
int flags;
- target_ulong l, page;
+ vaddr l, page;
void * p;
uint8_t *buf = ptr;
diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index 85773db631..cf02ef6821 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -324,6 +324,14 @@ machine is hardly emulated at all (e.g. neither the LCD nor the USB part had
been implemented), so there is not much value added by this board. Use the
``ref405ep`` machine instead.
+``pc-i440fx-1.4`` up to ``pc-i440fx-1.7`` (since 7.0)
+'''''''''''''''''''''''''''''''''''''''''''''''''''''
+
+These old machine types are quite neglected nowadays and thus might have
+various pitfalls with regards to live migration. Use a newer machine type
+instead.
+
+
Backend options
---------------
diff --git a/docs/interop/vhost-user.rst b/docs/interop/vhost-user.rst
index edc3ad84a3..4dbc84fd00 100644
--- a/docs/interop/vhost-user.rst
+++ b/docs/interop/vhost-user.rst
@@ -38,6 +38,26 @@ conventions <backend_conventions>`.
*Master* and *slave* can be either a client (i.e. connecting) or
server (listening) in the socket communication.
+Support for platforms other than Linux
+--------------------------------------
+
+While vhost-user was initially developed targeting Linux, nowadays it
+is supported on any platform that provides the following features:
+
+- A way for requesting shared memory represented by a file descriptor
+ so it can be passed over a UNIX domain socket and then mapped by the
+ other process.
+
+- AF_UNIX sockets with SCM_RIGHTS, so QEMU and the other process can
+ exchange messages through it, including ancillary data when needed.
+
+- Either eventfd or pipe/pipe2. On platforms where eventfd is not
+ available, QEMU will automatically fall back to pipe2 or, as a last
+ resort, pipe. Each file descriptor will be used for receiving or
+ sending events by reading or writing (respectively) an 8-byte value
+ to the corresponding it. The 8-value itself has no meaning and
+ should not be interpreted.
+
Message Specification
=====================
diff --git a/docs/pcie_sriov.txt b/docs/pcie_sriov.txt
new file mode 100644
index 0000000000..f5e891e1d4
--- /dev/null
+++ b/docs/pcie_sriov.txt
@@ -0,0 +1,115 @@
+PCI SR/IOV EMULATION SUPPORT
+============================
+
+Description
+===========
+SR/IOV (Single Root I/O Virtualization) is an optional extended capability
+of a PCI Express device. It allows a single physical function (PF) to appear as multiple
+virtual functions (VFs) for the main purpose of eliminating software
+overhead in I/O from virtual machines.
+
+Qemu now implements the basic common functionality to enable an emulated device
+to support SR/IOV. Yet no fully implemented devices exists in Qemu, but a
+proof-of-concept hack of the Intel igb can be found here:
+
+git://github.com/knuto/qemu.git sriov_patches_v5
+
+Implementation
+==============
+Implementing emulation of an SR/IOV capable device typically consists of
+implementing support for two types of device classes; the "normal" physical device
+(PF) and the virtual device (VF). From Qemu's perspective, the VFs are just
+like other devices, except that some of their properties are derived from
+the PF.
+
+A virtual function is different from a physical function in that the BAR
+space for all VFs are defined by the BAR registers in the PFs SR/IOV
+capability. All VFs have the same BARs and BAR sizes.
+
+Accesses to these virtual BARs then is computed as
+
+ <VF BAR start> + <VF number> * <BAR sz> + <offset>
+
+From our emulation perspective this means that there is a separate call for
+setting up a BAR for a VF.
+
+1) To enable SR/IOV support in the PF, it must be a PCI Express device so
+ you would need to add a PCI Express capability in the normal PCI
+ capability list. You might also want to add an ARI (Alternative
+ Routing-ID Interpretation) capability to indicate that your device
+ supports functions beyond it's "own" function space (0-7),
+ which is necessary to support more than 7 functions, or
+ if functions extends beyond offset 7 because they are placed at an
+ offset > 1 or have stride > 1.
+
+ ...
+ #include "hw/pci/pcie.h"
+ #include "hw/pci/pcie_sriov.h"
+
+ pci_your_pf_dev_realize( ... )
+ {
+ ...
+ int ret = pcie_endpoint_cap_init(d, 0x70);
+ ...
+ pcie_ari_init(d, 0x100, 1);
+ ...
+
+ /* Add and initialize the SR/IOV capability */
+ pcie_sriov_pf_init(d, 0x200, "your_virtual_dev",
+ vf_devid, initial_vfs, total_vfs,
+ fun_offset, stride);
+
+ /* Set up individual VF BARs (parameters as for normal BARs) */
+ pcie_sriov_pf_init_vf_bar( ... )
+ ...
+ }
+
+ For cleanup, you simply call:
+
+ pcie_sriov_pf_exit(device);
+
+ which will delete all the virtual functions and associated resources.
+
+2) Similarly in the implementation of the virtual function, you need to
+ make it a PCI Express device and add a similar set of capabilities
+ except for the SR/IOV capability. Then you need to set up the VF BARs as
+ subregions of the PFs SR/IOV VF BARs by calling
+ pcie_sriov_vf_register_bar() instead of the normal pci_register_bar() call:
+
+ pci_your_vf_dev_realize( ... )
+ {
+ ...
+ int ret = pcie_endpoint_cap_init(d, 0x60);
+ ...
+ pcie_ari_init(d, 0x100, 1);
+ ...
+ memory_region_init(mr, ... )
+ pcie_sriov_vf_register_bar(d, bar_nr, mr);
+ ...
+ }
+
+Testing on Linux guest
+======================
+The easiest is if your device driver supports sysfs based SR/IOV
+enabling. Support for this was added in kernel v.3.8, so not all drivers
+support it yet.
+
+To enable 4 VFs for a device at 01:00.0:
+
+ modprobe yourdriver
+ echo 4 > /sys/bus/pci/devices/0000:01:00.0/sriov_numvfs
+
+You should now see 4 VFs with lspci.
+To turn SR/IOV off again - the standard requires you to turn it off before you can enable
+another VF count, and the emulation enforces this:
+
+ echo 0 > /sys/bus/pci/devices/0000:01:00.0/sriov_numvfs
+
+Older drivers typically provide a max_vfs module parameter
+to enable it at load time:
+
+ modprobe yourdriver max_vfs=4
+
+To disable the VFs again then, you simply have to unload the driver:
+
+ rmmod yourdriver
diff --git a/docs/specs/acpi_erst.rst b/docs/specs/acpi_erst.rst
new file mode 100644
index 0000000000..a8a9d22d25
--- /dev/null
+++ b/docs/specs/acpi_erst.rst
@@ -0,0 +1,200 @@
+ACPI ERST DEVICE
+================
+
+The ACPI ERST device is utilized to support the ACPI Error Record
+Serialization Table, ERST, functionality. This feature is designed for
+storing error records in persistent storage for future reference
+and/or debugging.
+
+The ACPI specification[1], in Chapter "ACPI Platform Error Interfaces
+(APEI)", and specifically subsection "Error Serialization", outlines a
+method for storing error records into persistent storage.
+
+The format of error records is described in the UEFI specification[2],
+in Appendix N "Common Platform Error Record".
+
+While the ACPI specification allows for an NVRAM "mode" (see
+GET_ERROR_LOG_ADDRESS_RANGE_ATTRIBUTES) where non-volatile RAM is
+directly exposed for direct access by the OS/guest, this device
+implements the non-NVRAM "mode". This non-NVRAM "mode" is what is
+implemented by most BIOS (since flash memory requires programming
+operations in order to update its contents). Furthermore, as of the
+time of this writing, Linux only supports the non-NVRAM "mode".
+
+
+Background/Motivation
+---------------------
+
+Linux uses the persistent storage filesystem, pstore, to record
+information (eg. dmesg tail) upon panics and shutdowns. Pstore is
+independent of, and runs before, kdump. In certain scenarios (ie.
+hosts/guests with root filesystems on NFS/iSCSI where networking
+software and/or hardware fails, and thus kdump fails), pstore may
+contain information available for post-mortem debugging.
+
+Two common storage backends for the pstore filesystem are ACPI ERST
+and UEFI. Most BIOS implement ACPI ERST. UEFI is not utilized in all
+guests. With QEMU supporting ACPI ERST, it becomes a viable pstore
+storage backend for virtual machines (as it is now for bare metal
+machines).
+
+Enabling support for ACPI ERST facilitates a consistent method to
+capture kernel panic information in a wide range of guests: from
+resource-constrained microvms to very large guests, and in particular,
+in direct-boot environments (which would lack UEFI run-time services).
+
+Note that Microsoft Windows also utilizes the ACPI ERST for certain
+crash information, if available[3].
+
+
+Configuration|Usage
+-------------------
+
+To use ACPI ERST, a memory-backend-file object and acpi-erst device
+can be created, for example:
+
+ qemu ...
+ -object memory-backend-file,id=erstnvram,mem-path=acpi-erst.backing,size=0x10000,share=on \
+ -device acpi-erst,memdev=erstnvram
+
+For proper operation, the ACPI ERST device needs a memory-backend-file
+object with the following parameters:
+
+ - id: The id of the memory-backend-file object is used to associate
+ this memory with the acpi-erst device.
+ - size: The size of the ACPI ERST backing storage. This parameter is
+ required.
+ - mem-path: The location of the ACPI ERST backing storage file. This
+ parameter is also required.
+ - share: The share=on parameter is required so that updates to the
+ ERST backing store are written to the file.
+
+and ERST device:
+
+ - memdev: Is the object id of the memory-backend-file.
+ - record_size: Specifies the size of the records (or slots) in the
+ backend storage. Must be a power of two value greater than or
+ equal to 4096 (PAGE_SIZE).
+
+
+PCI Interface
+-------------
+
+The ERST device is a PCI device with two BARs, one for accessing the
+programming registers, and the other for accessing the record exchange
+buffer.
+
+BAR0 contains the programming interface consisting of ACTION and VALUE
+64-bit registers. All ERST actions/operations/side effects happen on
+the write to the ACTION, by design. Any data needed by the action must
+be placed into VALUE prior to writing ACTION. Reading the VALUE
+simply returns the register contents, which can be updated by a
+previous ACTION.
+
+BAR1 contains the 8KiB record exchange buffer, which is the
+implemented maximum record size.
+
+
+Backend Storage Format
+----------------------
+
+The backend storage is divided into fixed size "slots", 8KiB in
+length, with each slot storing a single record. Not all slots need to
+be occupied, and they need not be occupied in a contiguous fashion.
+The ability to clear/erase specific records allows for the formation
+of unoccupied slots.
+
+Slot 0 contains a backend storage header that identifies the contents
+as ERST and also facilitates efficient access to the records.
+Depending upon the size of the backend storage, additional slots will
+be designated to be a part of the slot 0 header. For example, at 8KiB,
+the slot 0 header can accomodate 1021 records. Thus a storage size
+of 8MiB (8KiB * 1024) requires an additional slot for use by the
+header. In this scenario, slot 0 and slot 1 form the backend storage
+header, and records can be stored starting at slot 2.
+
+Below is an example layout of the backend storage format (for storage
+size less than 8MiB). The size of the storage is a multiple of 8KiB,
+and contains N number of slots to store records. The example below
+shows two records (in CPER format) in the backend storage, while the
+remaining slots are empty/available.
+
+::
+
+ Slot Record
+ <------------------ 8KiB -------------------->
+ +--------------------------------------------+
+ 0 | storage header |
+ +--------------------------------------------+
+ 1 | empty/available |
+ +--------------------------------------------+
+ 2 | CPER |
+ +--------------------------------------------+
+ 3 | CPER |
+ +--------------------------------------------+
+ ... | |
+ +--------------------------------------------+
+ N | empty/available |
+ +--------------------------------------------+
+
+The storage header consists of some basic information and an array
+of CPER record_id's to efficiently access records in the backend
+storage.
+
+All fields in the header are stored in little endian format.
+
+::
+
+ +--------------------------------------------+
+ | magic | 0x0000
+ +--------------------------------------------+
+ | record_offset | record_size | 0x0008
+ +--------------------------------------------+
+ | record_count | reserved | version | 0x0010
+ +--------------------------------------------+
+ | record_id[0] | 0x0018
+ +--------------------------------------------+
+ | record_id[1] | 0x0020
+ +--------------------------------------------+
+ | record_id[...] |
+ +--------------------------------------------+
+ | record_id[N] | 0x1FF8
+ +--------------------------------------------+
+
+The 'magic' field contains the value 0x524F545354535245.
+
+The 'record_size' field contains the value 0x2000, 8KiB.
+
+The 'record_offset' field points to the first record_id in the array,
+0x0018.
+
+The 'version' field contains 0x0100, the first version.
+
+The 'record_count' field contains the number of valid records in the
+backend storage.
+
+The 'record_id' array fields are the 64-bit record identifiers of the
+CPER record in the corresponding slot. Stated differently, the
+location of a CPER record_id in the record_id[] array provides the
+slot index for the corresponding record in the backend storage.
+
+Note that, for example, with a backend storage less than 8MiB, slot 0
+contains the header, so the record_id[0] will never contain a valid
+CPER record_id. Instead slot 1 is the first available slot and thus
+record_id_[1] may contain a CPER.
+
+A 'record_id' of all 0s or all 1s indicates an invalid record (ie. the
+slot is available).
+
+
+References
+----------
+
+[1] "Advanced Configuration and Power Interface Specification",
+ version 4.0, June 2009.
+
+[2] "Unified Extensible Firmware Interface Specification",
+ version 2.1, October 2008.
+
+[3] "Windows Hardware Error Architecture", specfically
+ "Error Record Persistence Mechanism".
diff --git a/docs/specs/index.rst b/docs/specs/index.rst
index 2a35700fb3..e10684bf53 100644
--- a/docs/specs/index.rst
+++ b/docs/specs/index.rst
@@ -18,4 +18,5 @@ guest hardware that is specific to QEMU.
acpi_mem_hotplug
acpi_pci_hotplug
acpi_nvdimm
+ acpi_erst
sev-guest-firmware
diff --git a/docs/specs/pci-ids.txt b/docs/specs/pci-ids.txt
index 5e407a6f32..dd6859d039 100644
--- a/docs/specs/pci-ids.txt
+++ b/docs/specs/pci-ids.txt
@@ -65,6 +65,7 @@ PCI devices (other than virtio):
1b36:000f mdpy (mdev sample device), linux/samples/vfio-mdev/mdpy.c
1b36:0010 PCIe NVMe device (-device nvme)
1b36:0011 PCI PVPanic device (-device pvpanic-pci)
+1b36:0012 PCI ACPI ERST device (-device acpi-erst)
All these devices are documented in docs/specs.
diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index 8fd89f0447..4997677460 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -16,10 +16,17 @@
#include <dirent.h>
#include <utime.h>
-#include <sys/vfs.h>
#include "qemu-fsdev-throttle.h"
#include "p9array.h"
+#ifdef CONFIG_LINUX
+# include <sys/vfs.h>
+#endif
+#ifdef CONFIG_DARWIN
+# include <sys/param.h>
+# include <sys/mount.h>
+#endif
+
#define SM_LOCAL_MODE_BITS 0600
#define SM_LOCAL_DIR_MODE_BITS 0700
diff --git a/fsdev/meson.build b/fsdev/meson.build
index adf57cc43e..b632b66348 100644
--- a/fsdev/meson.build
+++ b/fsdev/meson.build
@@ -7,6 +7,7 @@ fsdev_ss.add(when: ['CONFIG_FSDEV_9P'], if_true: files(
'qemu-fsdev.c',
), if_false: files('qemu-fsdev-dummy.c'))
softmmu_ss.add_all(when: 'CONFIG_LINUX', if_true: fsdev_ss)
+softmmu_ss.add_all(when: 'CONFIG_DARWIN', if_true: fsdev_ss)
if have_virtfs_proxy_helper
executable('virtfs-proxy-helper',
diff --git a/fsdev/p9array.h b/fsdev/p9array.h
index 6aa25327ca..90e83a7c7b 100644
--- a/fsdev/p9array.h
+++ b/fsdev/p9array.h
@@ -81,11 +81,11 @@
*/
/**
- * Declares an array type for the passed @a scalar_type.
+ * P9ARRAY_DECLARE_TYPE() - Declares an array type for the passed @scalar_type.
*
- * This is typically used from a shared header file.
+ * @scalar_type: type of the individual array elements
*
- * @param scalar_type - type of the individual array elements
+ * This is typically used from a shared header file.
*/
#define P9ARRAY_DECLARE_TYPE(scalar_type) \
typedef struct P9Array##scalar_type { \
@@ -97,14 +97,14 @@
void p9array_auto_free_##scalar_type(scalar_type **auto_var); \
/**
- * Defines an array type for the passed @a scalar_type and appropriate
- * @a scalar_cleanup_func.
+ * P9ARRAY_DEFINE_TYPE() - Defines an array type for the passed @scalar_type
+ * and appropriate @scalar_cleanup_func.
*
- * This is typically used from a C unit file.
+ * @scalar_type: type of the individual array elements
+ * @scalar_cleanup_func: appropriate function to free memory dynamically
+ * allocated by individual array elements before
*
- * @param scalar_type - type of the individual array elements
- * @param scalar_cleanup_func - appropriate function to free memory dynamically
- * allocated by individual array elements before
+ * This is typically used from a C unit file.
*/
#define P9ARRAY_DEFINE_TYPE(scalar_type, scalar_cleanup_func) \
void p9array_new_##scalar_type(scalar_type **auto_var, size_t len) \
@@ -132,23 +132,27 @@
} \
/**
+ * P9ARRAY_REF() - Declare a reference variable for an array.
+ *
+ * @scalar_type: type of the individual array elements
+ *
* Used to declare a reference variable (unique pointer) for an array. After
* leaving the scope of the reference variable, the associated array is
* automatically freed.
- *
- * @param scalar_type - type of the individual array elements
*/
#define P9ARRAY_REF(scalar_type) \
__attribute((__cleanup__(p9array_auto_free_##scalar_type))) scalar_type*
/**
- * Allocates a new array of passed @a scalar_type with @a len number of array
- * elements and assigns the created array to the reference variable
- * @a auto_var.
+ * P9ARRAY_NEW() - Allocate a new array.
*
- * @param scalar_type - type of the individual array elements
- * @param auto_var - destination reference variable
- * @param len - amount of array elements to be allocated immediately
+ * @scalar_type: type of the individual array elements
+ * @auto_var: destination reference variable
+ * @len: amount of array elements to be allocated immediately
+ *
+ * Allocates a new array of passed @scalar_type with @len number of array
+ * elements and assigns the created array to the reference variable
+ * @auto_var.
*/
#define P9ARRAY_NEW(scalar_type, auto_var, len) \
QEMU_BUILD_BUG_MSG( \
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index 210d9e7705..d42ce6d8b8 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -32,10 +32,12 @@
#include "qemu/error-report.h"
#include "qemu/option.h"
#include <libgen.h>
+#ifdef CONFIG_LINUX
#include <linux/fs.h>
#ifdef CONFIG_LINUX_MAGIC_H
#include <linux/magic.h>
#endif
+#endif
#include <sys/ioctl.h>
#ifndef XFS_SUPER_MAGIC
@@ -560,6 +562,15 @@ again:
if (!entry) {
return NULL;
}
+#ifdef CONFIG_DARWIN
+ int off;
+ off = telldir(fs->dir.stream);
+ /* If telldir fails, fail the entire readdir call */
+ if (off < 0) {
+ return NULL;
+ }
+ entry->d_seekoff = off;
+#endif
if (ctx->export_flags & V9FS_SM_MAPPED) {
entry->d_type = DT_UNKNOWN;
@@ -671,7 +682,7 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
if (fs_ctx->export_flags & V9FS_SM_MAPPED ||
fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
- err = mknodat(dirfd, name, fs_ctx->fmode | S_IFREG, 0);
+ err = qemu_mknodat(dirfd, name, fs_ctx->fmode | S_IFREG, 0);
if (err == -1) {
goto out;
}
@@ -686,7 +697,7 @@ static int local_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
}
} else if (fs_ctx->export_flags & V9FS_SM_PASSTHROUGH ||
fs_ctx->export_flags & V9FS_SM_NONE) {
- err = mknodat(dirfd, name, credp->fc_mode, credp->fc_rdev);
+ err = qemu_mknodat(dirfd, name, credp->fc_mode, credp->fc_rdev);
if (err == -1) {
goto out;
}
@@ -779,16 +790,20 @@ static int local_fstat(FsContext *fs_ctx, int fid_type,
mode_t tmp_mode;
dev_t tmp_dev;
- if (fgetxattr(fd, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) {
+ if (qemu_fgetxattr(fd, "user.virtfs.uid",
+ &tmp_uid, sizeof(uid_t)) > 0) {
stbuf->st_uid = le32_to_cpu(tmp_uid);
}
- if (fgetxattr(fd, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) {
+ if (qemu_fgetxattr(fd, "user.virtfs.gid",
+ &tmp_gid, sizeof(gid_t)) > 0) {
stbuf->st_gid = le32_to_cpu(tmp_gid);
}
- if (fgetxattr(fd, "user.virtfs.mode", &tmp_mode, sizeof(mode_t)) > 0) {
+ if (qemu_fgetxattr(fd, "user.virtfs.mode",
+ &tmp_mode, sizeof(mode_t)) > 0) {
stbuf->st_mode = le32_to_cpu(tmp_mode);
}
- if (fgetxattr(fd, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) {
+ if (qemu_fgetxattr(fd, "user.virtfs.rdev",
+ &tmp_dev, sizeof(dev_t)) > 0) {
stbuf->st_rdev = le64_to_cpu(tmp_dev);
}
} else if (fs_ctx->export_flags & V9FS_SM_MAPPED_FILE) {
diff --git a/hw/9pfs/9p-proxy.c b/hw/9pfs/9p-proxy.c
index 09bd9f1464..8b4b5cf7dc 100644
--- a/hw/9pfs/9p-proxy.c
+++ b/hw/9pfs/9p-proxy.c
@@ -123,10 +123,16 @@ static void prstatfs_to_statfs(struct statfs *stfs, ProxyStatFS *prstfs)
stfs->f_bavail = prstfs->f_bavail;
stfs->f_files = prstfs->f_files;
stfs->f_ffree = prstfs->f_ffree;
+#ifdef CONFIG_DARWIN
+ /* f_namelen and f_frsize do not exist on Darwin */
+ stfs->f_fsid.val[0] = prstfs->f_fsid[0] & 0xFFFFFFFFU;
+ stfs->f_fsid.val[1] = prstfs->f_fsid[1] >> 32 & 0xFFFFFFFFU;
+#else
stfs->f_fsid.__val[0] = prstfs->f_fsid[0] & 0xFFFFFFFFU;
stfs->f_fsid.__val[1] = prstfs->f_fsid[1] >> 32 & 0xFFFFFFFFU;
stfs->f_namelen = prstfs->f_namelen;
stfs->f_frsize = prstfs->f_frsize;
+#endif
}
/* Converts proxy_stat structure to VFS stat structure */
@@ -143,12 +149,24 @@ static void prstat_to_stat(struct stat *stbuf, ProxyStat *prstat)
stbuf->st_size = prstat->st_size;
stbuf->st_blksize = prstat->st_blksize;
stbuf->st_blocks = prstat->st_blocks;
+ stbuf->st_atime = prstat->st_atim_sec;
+ stbuf->st_mtime = prstat->st_mtim_sec;
+ stbuf->st_ctime = prstat->st_ctim_sec;
+#ifdef CONFIG_DARWIN
+ stbuf->st_atimespec.tv_sec = prstat->st_atim_sec;
+ stbuf->st_mtimespec.tv_sec = prstat->st_mtim_sec;
+ stbuf->st_ctimespec.tv_sec = prstat->st_ctim_sec;
+ stbuf->st_atimespec.tv_nsec = prstat->st_atim_nsec;
+ stbuf->st_mtimespec.tv_nsec = prstat->st_mtim_nsec;
+ stbuf->st_ctimespec.tv_nsec = prstat->st_ctim_nsec;
+#else
stbuf->st_atim.tv_sec = prstat->st_atim_sec;
+ stbuf->st_mtim.tv_sec = prstat->st_mtim_sec;
+ stbuf->st_ctim.tv_sec = prstat->st_ctim_sec;
stbuf->st_atim.tv_nsec = prstat->st_atim_nsec;
- stbuf->st_mtime = prstat->st_mtim_sec;
stbuf->st_mtim.tv_nsec = prstat->st_mtim_nsec;
- stbuf->st_ctime = prstat->st_ctim_sec;
stbuf->st_ctim.tv_nsec = prstat->st_ctim_nsec;
+#endif
}
/*
@@ -688,7 +706,21 @@ static off_t proxy_telldir(FsContext *ctx, V9fsFidOpenState *fs)
static struct dirent *proxy_readdir(FsContext *ctx, V9fsFidOpenState *fs)
{
- return readdir(fs->dir.stream);
+ struct dirent *entry;
+ entry = readdir(fs->dir.stream);
+#ifdef CONFIG_DARWIN
+ if (!entry) {
+ return NULL;
+ }
+ int td;
+ td = telldir(fs->dir.stream);
+ /* If telldir fails, fail the entire readdir call */
+ if (td < 0) {
+ return NULL;
+ }
+ entry->d_seekoff = td;
+#endif
+ return entry;
}
static void proxy_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
diff --git a/hw/9pfs/9p-synth.c b/hw/9pfs/9p-synth.c
index 7a7cd5c5ba..b3080e415b 100644
--- a/hw/9pfs/9p-synth.c
+++ b/hw/9pfs/9p-synth.c
@@ -234,7 +234,11 @@ static void synth_direntry(V9fsSynthNode *node,
offsetof(struct dirent, d_name) + sz);
memcpy(entry->d_name, node->name, sz);
entry->d_ino = node->attr->inode;
+#ifdef CONFIG_DARWIN
+ entry->d_seekoff = off + 1;
+#else
entry->d_off = off + 1;
+#endif
}
static struct dirent *synth_get_dentry(V9fsSynthNode *dir,
@@ -439,7 +443,9 @@ static int synth_statfs(FsContext *s, V9fsPath *fs_path,
stbuf->f_bsize = 512;
stbuf->f_blocks = 0;
stbuf->f_files = synth_node_count;
+#ifndef CONFIG_DARWIN
stbuf->f_namelen = NAME_MAX;
+#endif
return 0;
}
diff --git a/hw/9pfs/9p-util-darwin.c b/hw/9pfs/9p-util-darwin.c
new file mode 100644
index 0000000000..bec0253474
--- /dev/null
+++ b/hw/9pfs/9p-util-darwin.c
@@ -0,0 +1,97 @@
+/*
+ * 9p utilities (Darwin Implementation)
+ *
+ * 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/xattr.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+#include "9p-util.h"
+
+ssize_t fgetxattrat_nofollow(int dirfd, const char *filename, const char *name,
+ void *value, size_t size)
+{
+ int ret;
+ int fd = openat_file(dirfd, filename,
+ O_RDONLY | O_PATH_9P_UTIL | O_NOFOLLOW, 0);
+ if (fd == -1) {
+ return -1;
+ }
+ ret = fgetxattr(fd, name, value, size, 0, 0);
+ close_preserve_errno(fd);
+ return ret;
+}
+
+ssize_t flistxattrat_nofollow(int dirfd, const char *filename,
+ char *list, size_t size)
+{
+ int ret;
+ int fd = openat_file(dirfd, filename,
+ O_RDONLY | O_PATH_9P_UTIL | O_NOFOLLOW, 0);
+ if (fd == -1) {
+ return -1;
+ }
+ ret = flistxattr(fd, list, size, 0);
+ close_preserve_errno(fd);
+ return ret;
+}
+
+ssize_t fremovexattrat_nofollow(int dirfd, const char *filename,
+ const char *name)
+{
+ int ret;
+ int fd = openat_file(dirfd, filename, O_PATH_9P_UTIL | O_NOFOLLOW, 0);
+ if (fd == -1) {
+ return -1;
+ }
+ ret = fremovexattr(fd, name, 0);
+ close_preserve_errno(fd);
+ return ret;
+}
+
+int fsetxattrat_nofollow(int dirfd, const char *filename, const char *name,
+ void *value, size_t size, int flags)
+{
+ int ret;
+ int fd = openat_file(dirfd, filename, O_PATH_9P_UTIL | O_NOFOLLOW, 0);
+ if (fd == -1) {
+ return -1;
+ }
+ ret = fsetxattr(fd, name, value, size, 0, flags);
+ close_preserve_errno(fd);
+ return ret;
+}
+
+/*
+ * As long as mknodat is not available on macOS, this workaround
+ * using pthread_fchdir_np is needed.
+ *
+ * Radar filed with Apple for implementing mknodat:
+ * rdar://FB9862426 (https://openradar.appspot.com/FB9862426)
+ */
+#if defined CONFIG_PTHREAD_FCHDIR_NP
+
+int qemu_mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev)
+{
+ int preserved_errno, err;
+ if (!pthread_fchdir_np) {
+ error_report_once("pthread_fchdir_np() not available on this version of macOS");
+ return -ENOTSUP;
+ }
+ if (pthread_fchdir_np(dirfd) < 0) {
+ return -1;
+ }
+ err = mknod(filename, mode, dev);
+ preserved_errno = errno;
+ /* Stop using the thread-local cwd */
+ pthread_fchdir_np(-1);
+ if (err < 0) {
+ errno = preserved_errno;
+ }
+ return err;
+}
+
+#endif
diff --git a/hw/9pfs/9p-util.c b/hw/9pfs/9p-util-linux.c
index 3221d9b498..db451b0784 100644
--- a/hw/9pfs/9p-util.c
+++ b/hw/9pfs/9p-util-linux.c
@@ -1,5 +1,5 @@
/*
- * 9p utilities
+ * 9p utilities (Linux Implementation)
*
* Copyright IBM, Corp. 2017
*
@@ -61,4 +61,10 @@ int fsetxattrat_nofollow(int dirfd, const char *filename, const char *name,
ret = lsetxattr(proc_path, name, value, size, flags);
g_free(proc_path);
return ret;
+
+}
+
+int qemu_mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev)
+{
+ return mknodat(dirfd, filename, mode, dev);
}
diff --git a/hw/9pfs/9p-util.h b/hw/9pfs/9p-util.h
index 546f46dc7d..97e681e167 100644
--- a/hw/9pfs/9p-util.h
+++ b/hw/9pfs/9p-util.h
@@ -19,6 +19,23 @@
#define O_PATH_9P_UTIL 0
#endif
+#ifdef CONFIG_DARWIN
+#define qemu_fgetxattr(...) fgetxattr(__VA_ARGS__, 0, 0)
+#define qemu_lgetxattr(...) getxattr(__VA_ARGS__, 0, XATTR_NOFOLLOW)
+#define qemu_llistxattr(...) listxattr(__VA_ARGS__, XATTR_NOFOLLOW)
+#define qemu_lremovexattr(...) removexattr(__VA_ARGS__, XATTR_NOFOLLOW)
+static inline int qemu_lsetxattr(const char *path, const char *name,
+ const void *value, size_t size, int flags) {
+ return setxattr(path, name, value, size, 0, flags | XATTR_NOFOLLOW);
+}
+#else
+#define qemu_fgetxattr fgetxattr
+#define qemu_lgetxattr lgetxattr
+#define qemu_llistxattr llistxattr
+#define qemu_lremovexattr lremovexattr
+#define qemu_lsetxattr lsetxattr
+#endif
+
static inline void close_preserve_errno(int fd)
{
int serrno = errno;
@@ -37,10 +54,13 @@ static inline int openat_file(int dirfd, const char *name, int flags,
{
int fd, serrno, ret;
+#ifndef CONFIG_DARWIN
again:
+#endif
fd = openat(dirfd, name, flags | O_NOFOLLOW | O_NOCTTY | O_NONBLOCK,
mode);
if (fd == -1) {
+#ifndef CONFIG_DARWIN
if (errno == EPERM && (flags & O_NOATIME)) {
/*
* The client passed O_NOATIME but we lack permissions to honor it.
@@ -53,6 +73,7 @@ again:
flags &= ~O_NOATIME;
goto again;
}
+#endif
return -1;
}
@@ -78,4 +99,61 @@ ssize_t flistxattrat_nofollow(int dirfd, const char *filename,
ssize_t fremovexattrat_nofollow(int dirfd, const char *filename,
const char *name);
+/*
+ * Darwin has d_seekoff, which appears to function similarly to d_off.
+ * However, it does not appear to be supported on all file systems,
+ * so ensure it is manually injected earlier and call here when
+ * needed.
+ */
+static inline off_t qemu_dirent_off(struct dirent *dent)
+{
+#ifdef CONFIG_DARWIN
+ return dent->d_seekoff;
+#else
+ return dent->d_off;
+#endif
+}
+
+/**
+ * qemu_dirent_dup() - Duplicate directory entry @dent.
+ *
+ * @dent: original directory entry to be duplicated
+ * Return: duplicated directory entry which should be freed with g_free()
+ *
+ * It is highly recommended to use this function instead of open coding
+ * duplication of dirent objects, because the actual struct dirent
+ * size may be bigger or shorter than sizeof(struct dirent) and correct
+ * handling is platform specific (see gitlab issue #841).
+ */
+static inline struct dirent *qemu_dirent_dup(struct dirent *dent)
+{
+ size_t sz = 0;
+#if defined _DIRENT_HAVE_D_RECLEN
+ /* Avoid use of strlen() if platform supports d_reclen. */
+ sz = dent->d_reclen;
+#endif
+ /*
+ * Test sz for zero even if d_reclen is available
+ * because some drivers may set d_reclen to zero.
+ */
+ if (sz == 0) {
+ /* Fallback to the most portable way. */
+ sz = offsetof(struct dirent, d_name) +
+ strlen(dent->d_name) + 1;
+ }
+ return g_memdup(dent, sz);
+}
+
+/*
+ * As long as mknodat is not available on macOS, this workaround
+ * using pthread_fchdir_np is needed. qemu_mknodat is defined in
+ * os-posix.c. pthread_fchdir_np is weakly linked here as a guard
+ * in case it disappears in future macOS versions, because it is
+ * is a private API.
+ */
+#if defined CONFIG_DARWIN && defined CONFIG_PTHREAD_FCHDIR_NP
+int pthread_fchdir_np(int fd) __attribute__((weak_import));
+#endif
+int qemu_mknodat(int dirfd, const char *filename, mode_t mode, dev_t dev);
+
#endif
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 15b3f4d385..a6d6b3f835 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -27,12 +27,17 @@
#include "virtio-9p.h"
#include "fsdev/qemu-fsdev.h"
#include "9p-xattr.h"
+#include "9p-util.h"
#include "coth.h"
#include "trace.h"
#include "migration/blocker.h"
#include "qemu/xxhash.h"
#include <math.h>
+#ifdef CONFIG_LINUX
#include <linux/limits.h>
+#else
+#include <limits.h>
+#endif
int open_fd_hw;
int total_open_fd;
@@ -133,11 +138,20 @@ static int dotl_to_open_flags(int flags)
{ P9_DOTL_NONBLOCK, O_NONBLOCK } ,
{ P9_DOTL_DSYNC, O_DSYNC },
{ P9_DOTL_FASYNC, FASYNC },
+#ifndef CONFIG_DARWIN
+ { P9_DOTL_NOATIME, O_NOATIME },
+ /*
+ * On Darwin, we could map to F_NOCACHE, which is
+ * similar, but doesn't quite have the same
+ * semantics. However, we don't support O_DIRECT
+ * even on linux at the moment, so we just ignore
+ * it here.
+ */
{ P9_DOTL_DIRECT, O_DIRECT },
+#endif
{ P9_DOTL_LARGEFILE, O_LARGEFILE },
{ P9_DOTL_DIRECTORY, O_DIRECTORY },
{ P9_DOTL_NOFOLLOW, O_NOFOLLOW },
- { P9_DOTL_NOATIME, O_NOATIME },
{ P9_DOTL_SYNC, O_SYNC },
};
@@ -166,10 +180,12 @@ static int get_dotl_openflags(V9fsState *s, int oflags)
*/
flags = dotl_to_open_flags(oflags);
flags &= ~(O_NOCTTY | O_ASYNC | O_CREAT);
+#ifndef CONFIG_DARWIN
/*
* Ignore direct disk access hint until the server supports it.
*/
flags &= ~O_DIRECT;
+#endif
return flags;
}
@@ -612,8 +628,8 @@ static inline uint64_t mirror64bit(uint64_t value)
((uint64_t)mirror8bit((value >> 56) & 0xff));
}
-/**
- * @brief Parameter k for the Exponential Golomb algorihm to be used.
+/*
+ * Parameter k for the Exponential Golomb algorihm to be used.
*
* The smaller this value, the smaller the minimum bit count for the Exp.
* Golomb generated affixes will be (at lowest index) however for the
@@ -626,28 +642,30 @@ static inline uint64_t mirror64bit(uint64_t value)
* should be small, for a large amount of devices k might be increased
* instead. The default of k=0 should be fine for most users though.
*
- * @b IMPORTANT: In case this ever becomes a runtime parameter; the value of
+ * IMPORTANT: In case this ever becomes a runtime parameter; the value of
* k should not change as long as guest is still running! Because that would
* cause completely different inode numbers to be generated on guest.
*/
#define EXP_GOLOMB_K 0
/**
- * @brief Exponential Golomb algorithm for arbitrary k (including k=0).
+ * expGolombEncode() - Exponential Golomb algorithm for arbitrary k
+ * (including k=0).
+ *
+ * @n: natural number (or index) of the prefix to be generated
+ * (1, 2, 3, ...)
+ * @k: parameter k of Exp. Golomb algorithm to be used
+ * (see comment on EXP_GOLOMB_K macro for details about k)
+ * Return: prefix for given @n and @k
*
- * The Exponential Golomb algorithm generates @b prefixes (@b not suffixes!)
+ * The Exponential Golomb algorithm generates prefixes (NOT suffixes!)
* with growing length and with the mathematical property of being
* "prefix-free". The latter means the generated prefixes can be prepended
* in front of arbitrary numbers and the resulting concatenated numbers are
* guaranteed to be always unique.
*
* This is a minor adjustment to the original Exp. Golomb algorithm in the
- * sense that lowest allowed index (@param n) starts with 1, not with zero.
- *
- * @param n - natural number (or index) of the prefix to be generated
- * (1, 2, 3, ...)
- * @param k - parameter k of Exp. Golomb algorithm to be used
- * (see comment on EXP_GOLOMB_K macro for details about k)
+ * sense that lowest allowed index (@n) starts with 1, not with zero.
*/
static VariLenAffix expGolombEncode(uint64_t n, int k)
{
@@ -661,7 +679,9 @@ static VariLenAffix expGolombEncode(uint64_t n, int k)
}
/**
- * @brief Converts a suffix into a prefix, or a prefix into a suffix.
+ * invertAffix() - Converts a suffix into a prefix, or a prefix into a suffix.
+ * @affix: either suffix or prefix to be inverted
+ * Return: inversion of passed @affix
*
* Simply mirror all bits of the affix value, for the purpose to preserve
* respectively the mathematical "prefix-free" or "suffix-free" property
@@ -685,16 +705,16 @@ static VariLenAffix invertAffix(const VariLenAffix *affix)
}
/**
- * @brief Generates suffix numbers with "suffix-free" property.
+ * affixForIndex() - Generates suffix numbers with "suffix-free" property.
+ * @index: natural number (or index) of the suffix to be generated
+ * (1, 2, 3, ...)
+ * Return: Suffix suitable to assemble unique number.
*
* This is just a wrapper function on top of the Exp. Golomb algorithm.
*
* Since the Exp. Golomb algorithm generates prefixes, but we need suffixes,
* this function converts the Exp. Golomb prefixes into appropriate suffixes
* which are still suitable for generating unique numbers.
- *
- * @param n - natural number (or index) of the suffix to be generated
- * (1, 2, 3, ...)
*/
static VariLenAffix affixForIndex(uint64_t index)
{
@@ -794,8 +814,8 @@ static int qid_inode_prefix_hash_bits(V9fsPDU *pdu, dev_t dev)
return val->prefix_bits;
}
-/**
- * @brief Slow / full mapping host inode nr -> guest inode nr.
+/*
+ * Slow / full mapping host inode nr -> guest inode nr.
*
* This function performs a slower and much more costly remapping of an
* original file inode number on host to an appropriate different inode
@@ -807,7 +827,7 @@ static int qid_inode_prefix_hash_bits(V9fsPDU *pdu, dev_t dev)
* qid_path_suffixmap() failed. In practice this slow / full mapping is not
* expected ever to be used at all though.
*
- * @see qid_path_suffixmap() for details
+ * See qid_path_suffixmap() for details
*
*/
static int qid_path_fullmap(V9fsPDU *pdu, const struct stat *stbuf,
@@ -848,8 +868,8 @@ static int qid_path_fullmap(V9fsPDU *pdu, const struct stat *stbuf,
return 0;
}
-/**
- * @brief Quick mapping host inode nr -> guest inode nr.
+/*
+ * Quick mapping host inode nr -> guest inode nr.
*
* This function performs quick remapping of an original file inode number
* on host to an appropriate different inode number on guest. This remapping
@@ -1265,12 +1285,15 @@ static int coroutine_fn stat_to_v9stat(V9fsPDU *pdu, V9fsPath *path,
/**
- * Convert host filesystem's block size into an appropriate block size for
- * 9p client (guest OS side). The value returned suggests an "optimum" block
- * size for 9p I/O, i.e. to maximize performance.
+ * blksize_to_iounit() - Block size exposed to 9p client.
+ * Return: block size
*
* @pdu: 9p client request
* @blksize: host filesystem's block size
+ *
+ * Convert host filesystem's block size into an appropriate block size for
+ * 9p client (guest OS side). The value returned suggests an "optimum" block
+ * size for 9p I/O, i.e. to maximize performance.
*/
static int32_t blksize_to_iounit(const V9fsPDU *pdu, int32_t blksize)
{
@@ -1309,11 +1332,17 @@ static int stat_to_v9stat_dotl(V9fsPDU *pdu, const struct stat *stbuf,
v9lstat->st_blksize = stat_to_iounit(pdu, stbuf);
v9lstat->st_blocks = stbuf->st_blocks;
v9lstat->st_atime_sec = stbuf->st_atime;
- v9lstat->st_atime_nsec = stbuf->st_atim.tv_nsec;
v9lstat->st_mtime_sec = stbuf->st_mtime;
- v9lstat->st_mtime_nsec = stbuf->st_mtim.tv_nsec;
v9lstat->st_ctime_sec = stbuf->st_ctime;
+#ifdef CONFIG_DARWIN
+ v9lstat->st_atime_nsec = stbuf->st_atimespec.tv_nsec;
+ v9lstat->st_mtime_nsec = stbuf->st_mtimespec.tv_nsec;
+ v9lstat->st_ctime_nsec = stbuf->st_ctimespec.tv_nsec;
+#else
+ v9lstat->st_atime_nsec = stbuf->st_atim.tv_nsec;
+ v9lstat->st_mtime_nsec = stbuf->st_mtim.tv_nsec;
v9lstat->st_ctime_nsec = stbuf->st_ctim.tv_nsec;
+#endif
/* Currently we only support BASIC fields in stat */
v9lstat->st_result_mask = P9_STATS_BASIC;
@@ -2271,7 +2300,7 @@ static int coroutine_fn v9fs_do_readdir_with_stat(V9fsPDU *pdu,
count += len;
v9fs_stat_free(&v9stat);
v9fs_path_free(&path);
- saved_dir_pos = dent->d_off;
+ saved_dir_pos = qemu_dirent_off(dent);
}
v9fs_readdir_unlock(&fidp->fs.dir);
@@ -2376,10 +2405,11 @@ out_nofid:
}
/**
- * Returns size required in Rreaddir response for the passed dirent @p name.
+ * v9fs_readdir_response_size() - Returns size required in Rreaddir response
+ * for the passed dirent @name.
*
- * @param name - directory entry's name (i.e. file name, directory name)
- * @returns required size in bytes
+ * @name: directory entry's name (i.e. file name, directory name)
+ * Return: required size in bytes
*/
size_t v9fs_readdir_response_size(V9fsString *name)
{
@@ -2410,6 +2440,7 @@ static int coroutine_fn v9fs_do_readdir(V9fsPDU *pdu, V9fsFidState *fidp,
V9fsString name;
int len, err = 0;
int32_t count = 0;
+ off_t off;
struct dirent *dent;
struct stat *st;
struct V9fsDirEnt *entries = NULL;
@@ -2470,12 +2501,13 @@ static int coroutine_fn v9fs_do_readdir(V9fsPDU *pdu, V9fsFidState *fidp,
qid.version = 0;
}
+ off = qemu_dirent_off(dent);
v9fs_string_init(&name);
v9fs_string_sprintf(&name, "%s", dent->d_name);
/* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */
len = pdu_marshal(pdu, 11 + count, "Qqbs",
- &qid, dent->d_off,
+ &qid, off,
dent->d_type, &name);
v9fs_string_free(&name);
@@ -3515,9 +3547,15 @@ static int v9fs_fill_statfs(V9fsState *s, V9fsPDU *pdu, struct statfs *stbuf)
f_bavail = stbuf->f_bavail / bsize_factor;
f_files = stbuf->f_files;
f_ffree = stbuf->f_ffree;
+#ifdef CONFIG_DARWIN
+ fsid_val = (unsigned int)stbuf->f_fsid.val[0] |
+ (unsigned long long)stbuf->f_fsid.val[1] << 32;
+ f_namelen = NAME_MAX;
+#else
fsid_val = (unsigned int) stbuf->f_fsid.__val[0] |
(unsigned long long)stbuf->f_fsid.__val[1] << 32;
f_namelen = stbuf->f_namelen;
+#endif
return pdu_marshal(pdu, offset, "ddqqqqqqd",
f_type, f_bsize, f_blocks, f_bfree,
@@ -3919,7 +3957,7 @@ static void coroutine_fn v9fs_xattrcreate(void *opaque)
rflags |= XATTR_REPLACE;
}
- if (size > XATTR_SIZE_MAX) {
+ if (size > P9_XATTR_SIZE_MAX) {
err = -E2BIG;
goto out_nofid;
}
diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
index 1567b67841..af2635fae9 100644
--- a/hw/9pfs/9p.h
+++ b/hw/9pfs/9p.h
@@ -100,8 +100,8 @@ typedef enum P9ProtoVersion {
V9FS_PROTO_2000L = 0x02,
} P9ProtoVersion;
-/**
- * @brief Minimum message size supported by this 9pfs server.
+/*
+ * Minimum message size supported by this 9pfs server.
*
* A client establishes a session by sending a Tversion request along with a
* 'msize' parameter which suggests the server a maximum message size ever to be
@@ -231,7 +231,7 @@ static inline void v9fs_readdir_init(P9ProtoVersion proto_version, V9fsDir *dir)
}
}
-/**
+/*
* Type for 9p fs drivers' (a.k.a. 9p backends) result of readdir requests,
* which is a chained list of directory entries.
*/
@@ -289,8 +289,8 @@ typedef enum AffixType_t {
AffixType_Suffix, /* A.k.a. postfix. */
} AffixType_t;
-/**
- * @brief Unique affix of variable length.
+/*
+ * Unique affix of variable length.
*
* An affix is (currently) either a suffix or a prefix, which is either
* going to be prepended (prefix) or appended (suffix) with some other
@@ -304,7 +304,7 @@ typedef struct VariLenAffix {
AffixType_t type; /* Whether this affix is a suffix or a prefix. */
uint64_t value; /* Actual numerical value of this affix. */
/*
- * Lenght of the affix, that is how many (of the lowest) bits of @c value
+ * Lenght of the affix, that is how many (of the lowest) bits of ``value``
* must be used for appending/prepending this affix to its final resulting,
* unique number.
*/
@@ -479,4 +479,22 @@ struct V9fsTransport {
void (*push_and_notify)(V9fsPDU *pdu);
};
+#if defined(XATTR_SIZE_MAX)
+/* Linux */
+#define P9_XATTR_SIZE_MAX XATTR_SIZE_MAX
+#elif defined(CONFIG_DARWIN)
+/*
+ * Darwin doesn't seem to define a maximum xattr size in its user
+ * space header, so manually configure it across platforms as 64k.
+ *
+ * Having no limit at all can lead to QEMU crashing during large g_malloc()
+ * calls. Because QEMU does not currently support macOS guests, the below
+ * preliminary solution only works due to its being a reflection of the limit of
+ * Linux guests.
+ */
+#define P9_XATTR_SIZE_MAX 65536
+#else
+#error Missing definition for P9_XATTR_SIZE_MAX for this host system
+#endif
+
#endif
diff --git a/hw/9pfs/codir.c b/hw/9pfs/codir.c
index c0873bde16..75148bc985 100644
--- a/hw/9pfs/codir.c
+++ b/hw/9pfs/codir.c
@@ -22,6 +22,8 @@
#include "qemu/coroutine.h"
#include "qemu/main-loop.h"
#include "coth.h"
+#include "9p-xattr.h"
+#include "9p-util.h"
/*
* Intended to be called from bottom-half (e.g. background I/O thread)
@@ -166,7 +168,7 @@ static int do_readdir_many(V9fsPDU *pdu, V9fsFidState *fidp,
}
size += len;
- saved_dir_pos = dent->d_off;
+ saved_dir_pos = qemu_dirent_off(dent);
}
/* restore (last) saved position */
@@ -182,14 +184,25 @@ out:
}
/**
- * @brief Reads multiple directory entries in one rush.
+ * v9fs_co_readdir_many() - Reads multiple directory entries in one rush.
+ *
+ * @pdu: the causing 9p (T_readdir) client request
+ * @fidp: already opened directory where readdir shall be performed on
+ * @entries: output for directory entries (must not be NULL)
+ * @offset: initial position inside the directory the function shall
+ * seek to before retrieving the directory entries
+ * @maxsize: maximum result message body size (in bytes)
+ * @dostat: whether a stat() should be performed and returned for
+ * each directory entry
+ * Return: resulting response message body size (in bytes) on success,
+ * negative error code otherwise
*
* Retrieves the requested (max. amount of) directory entries from the fs
* driver. This function must only be called by the main IO thread (top half).
* Internally this function call will be dispatched to a background IO thread
* (bottom half) where it is eventually executed by the fs driver.
*
- * @discussion Acquiring multiple directory entries in one rush from the fs
+ * Acquiring multiple directory entries in one rush from the fs
* driver, instead of retrieving each directory entry individually, is very
* beneficial from performance point of view. Because for every fs driver
* request latency is added, which in practice could lead to overall
@@ -197,20 +210,9 @@ out:
* directory) if every directory entry was individually requested from fs
* driver.
*
- * @note You must @b ALWAYS call @c v9fs_free_dirents(entries) after calling
+ * NOTE: You must ALWAYS call v9fs_free_dirents(entries) after calling
* v9fs_co_readdir_many(), both on success and on error cases of this
- * function, to avoid memory leaks once @p entries are no longer needed.
- *
- * @param pdu - the causing 9p (T_readdir) client request
- * @param fidp - already opened directory where readdir shall be performed on
- * @param entries - output for directory entries (must not be NULL)
- * @param offset - initial position inside the directory the function shall
- * seek to before retrieving the directory entries
- * @param maxsize - maximum result message body size (in bytes)
- * @param dostat - whether a stat() should be performed and returned for
- * each directory entry
- * @returns resulting response message body size (in bytes) on success,
- * negative error code otherwise
+ * function, to avoid memory leaks once @entries are no longer needed.
*/
int coroutine_fn v9fs_co_readdir_many(V9fsPDU *pdu, V9fsFidState *fidp,
struct V9fsDirEnt **entries,
diff --git a/hw/9pfs/coth.h b/hw/9pfs/coth.h
index f83c7dda7b..1a1edbdc2a 100644
--- a/hw/9pfs/coth.h
+++ b/hw/9pfs/coth.h
@@ -19,7 +19,7 @@
#include "qemu/coroutine.h"
#include "9p.h"
-/**
+/*
* we want to use bottom half because we want to make sure the below
* sequence of events.
*
@@ -29,7 +29,7 @@
* we cannot swap step 1 and 2, because that would imply worker thread
* can enter coroutine while step1 is still running
*
- * @b PERFORMANCE @b CONSIDERATIONS: As a rule of thumb, keep in mind
+ * PERFORMANCE CONSIDERATIONS: As a rule of thumb, keep in mind
* that hopping between threads adds @b latency! So when handling a
* 9pfs request, avoid calling v9fs_co_run_in_worker() too often, because
* this might otherwise sum up to a significant, huge overall latency for
diff --git a/hw/9pfs/meson.build b/hw/9pfs/meson.build
index 99be5d9119..12443b6ad5 100644
--- a/hw/9pfs/meson.build
+++ b/hw/9pfs/meson.build
@@ -4,7 +4,6 @@ fs_ss.add(files(
'9p-posix-acl.c',
'9p-proxy.c',
'9p-synth.c',
- '9p-util.c',
'9p-xattr-user.c',
'9p-xattr.c',
'9p.c',
@@ -14,6 +13,8 @@ fs_ss.add(files(
'coth.c',
'coxattr.c',
))
+fs_ss.add(when: 'CONFIG_LINUX', if_true: files('9p-util-linux.c'))
+fs_ss.add(when: 'CONFIG_DARWIN', if_true: files('9p-util-darwin.c'))
fs_ss.add(when: 'CONFIG_XEN', if_true: files('xen-9p-backend.c'))
softmmu_ss.add_all(when: 'CONFIG_FSDEV_9P', if_true: fs_ss)
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 8966e16320..1773cf55f1 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -2152,7 +2152,13 @@ void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
build_append_int_noprefix(tbl, 0, 1); /* DAY_ALRM */
build_append_int_noprefix(tbl, 0, 1); /* MON_ALRM */
build_append_int_noprefix(tbl, f->rtc_century, 1); /* CENTURY */
- build_append_int_noprefix(tbl, 0, 2); /* IAPC_BOOT_ARCH */
+ /* IAPC_BOOT_ARCH */
+ if (f->rev == 1) {
+ build_append_int_noprefix(tbl, 0, 2);
+ } else {
+ /* since ACPI v2.0 */
+ build_append_int_noprefix(tbl, f->iapc_boot_arch, 2);
+ }
build_append_int_noprefix(tbl, 0, 1); /* Reserved */
build_append_int_noprefix(tbl, f->flags, 4); /* Flags */
diff --git a/hw/acpi/erst.c b/hw/acpi/erst.c
index c0a23cf467..de509c2b48 100644
--- a/hw/acpi/erst.c
+++ b/hw/acpi/erst.c
@@ -80,11 +80,6 @@
#define UEFI_CPER_RECORD_MIN_SIZE 128U
#define UEFI_CPER_RECORD_LENGTH_OFFSET 20U
#define UEFI_CPER_RECORD_ID_OFFSET 96U
-#define IS_UEFI_CPER_RECORD(ptr) \
- (((ptr)[0] == 'C') && \
- ((ptr)[1] == 'P') && \
- ((ptr)[2] == 'E') && \
- ((ptr)[3] == 'R'))
/*
* NOTE that when accessing CPER fields within a record, memcpy()
diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c
index 6befd23e16..6351bd3424 100644
--- a/hw/acpi/pcihp.c
+++ b/hw/acpi/pcihp.c
@@ -32,6 +32,7 @@
#include "hw/pci/pci_bridge.h"
#include "hw/pci/pci_host.h"
#include "hw/pci/pcie_port.h"
+#include "hw/pci-bridge/xio3130_downstream.h"
#include "hw/i386/acpi-build.h"
#include "hw/acpi/acpi.h"
#include "hw/pci/pci_bus.h"
@@ -336,6 +337,8 @@ void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
{
PCIDevice *pdev = PCI_DEVICE(dev);
int slot = PCI_SLOT(pdev->devfn);
+ PCIDevice *bridge;
+ PCIBus *bus;
int bsel;
/* Don't send event when device is enabled during qemu machine creation:
@@ -365,7 +368,14 @@ void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
return;
}
- bsel = acpi_pcihp_get_bsel(pci_get_bus(pdev));
+ bus = pci_get_bus(pdev);
+ bridge = pci_bridge_get_device(bus);
+ if (object_dynamic_cast(OBJECT(bridge), TYPE_PCIE_ROOT_PORT) ||
+ object_dynamic_cast(OBJECT(bridge), TYPE_XIO3130_DOWNSTREAM)) {
+ pcie_cap_slot_enable_power(bridge);
+ }
+
+ bsel = acpi_pcihp_get_bsel(bus);
g_assert(bsel >= 0);
s->acpi_pcihp_pci_status[bsel].up |= (1U << slot);
acpi_send_event(DEVICE(hotplug_dev), ACPI_PCI_HOTPLUG_STATUS);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 46bf7ceddf..46a42502bc 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2102,6 +2102,10 @@ static void machvirt_init(MachineState *machine)
object_property_set_bool(cpuobj, "pmu", false, NULL);
}
+ if (vmc->no_tcg_lpa2 && object_property_find(cpuobj, "lpa2")) {
+ object_property_set_bool(cpuobj, "lpa2", false, NULL);
+ }
+
if (object_property_find(cpuobj, "reset-cbar")) {
object_property_set_int(cpuobj, "reset-cbar",
vms->memmap[VIRT_CPUPERIPHS].base,
@@ -3020,8 +3024,11 @@ DEFINE_VIRT_MACHINE_AS_LATEST(7, 0)
static void virt_machine_6_2_options(MachineClass *mc)
{
+ VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
+
virt_machine_7_0_options(mc);
compat_props_add(mc->compat_props, hw_compat_6_2, hw_compat_6_2_len);
+ vmc->no_tcg_lpa2 = true;
}
DEFINE_VIRT_MACHINE(6, 2)
diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c
index 7d60ce6f0e..0723e39430 100644
--- a/hw/audio/cs4231a.c
+++ b/hw/audio/cs4231a.c
@@ -677,7 +677,7 @@ static void cs4231a_realizefn (DeviceState *dev, Error **errp)
return;
}
- isa_init_irq(d, &s->pic, s->irq);
+ s->pic = isa_get_irq(d, s->irq);
k = ISADMA_GET_CLASS(s->isa_dma);
k->register_channel(s->isa_dma, s->dma, cs_dma_read, s);
diff --git a/hw/audio/gus.c b/hw/audio/gus.c
index e8719ee117..42f010b671 100644
--- a/hw/audio/gus.c
+++ b/hw/audio/gus.c
@@ -282,7 +282,7 @@ static void gus_realizefn (DeviceState *dev, Error **errp)
s->emu.himemaddr = s->himem;
s->emu.gusdatapos = s->emu.himemaddr + 1024 * 1024 + 32;
s->emu.opaque = s;
- isa_init_irq (d, &s->pic, s->emu.gusirq);
+ s->pic = isa_get_irq(d, s->emu.gusirq);
AUD_set_active_out (s->voice, 1);
}
diff --git a/hw/audio/sb16.c b/hw/audio/sb16.c
index 60f1f75e3a..2215386ddb 100644
--- a/hw/audio/sb16.c
+++ b/hw/audio/sb16.c
@@ -1408,7 +1408,7 @@ static void sb16_realizefn (DeviceState *dev, Error **errp)
return;
}
- isa_init_irq (isadev, &s->pic, s->irq);
+ s->pic = isa_get_irq(isadev, s->irq);
s->mixer_regs[0x80] = magic_of_irq (s->irq);
s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
diff --git a/hw/block/dataplane/xen-block.c b/hw/block/dataplane/xen-block.c
index 860787580a..2785b9e849 100644
--- a/hw/block/dataplane/xen-block.c
+++ b/hw/block/dataplane/xen-block.c
@@ -21,6 +21,7 @@
#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "qemu/main-loop.h"
+#include "qemu/memalign.h"
#include "qapi/error.h"
#include "hw/xen/xen_common.h"
#include "hw/block/xen_blkif.h"
diff --git a/hw/block/fdc-isa.c b/hw/block/fdc-isa.c
index ab663dce93..fa20450747 100644
--- a/hw/block/fdc-isa.c
+++ b/hw/block/fdc-isa.c
@@ -94,7 +94,7 @@ static void isabus_fdc_realize(DeviceState *dev, Error **errp)
isa->iobase, fdc_portio_list, fdctrl,
"fdc");
- isa_init_irq(isadev, &fdctrl->irq, isa->irq);
+ fdctrl->irq = isa_get_irq(isadev, isa->irq);
fdctrl->dma_chann = isa->dma;
if (fdctrl->dma_chann != -1) {
IsaDmaClass *k;
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
index 21d18ac2e3..347875a0cd 100644
--- a/hw/block/fdc.c
+++ b/hw/block/fdc.c
@@ -32,6 +32,7 @@
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "qemu/timer.h"
+#include "qemu/memalign.h"
#include "hw/irq.h"
#include "hw/isa/isa.h"
#include "hw/qdev-properties.h"
diff --git a/hw/char/parallel.c b/hw/char/parallel.c
index b45e67bfbb..adb9bd9be3 100644
--- a/hw/char/parallel.c
+++ b/hw/char/parallel.c
@@ -553,7 +553,7 @@ static void parallel_isa_realizefn(DeviceState *dev, Error **errp)
index++;
base = isa->iobase;
- isa_init_irq(isadev, &s->irq, isa->isairq);
+ s->irq = isa_get_irq(isadev, isa->isairq);
qemu_register_reset(parallel_reset, s);
qemu_chr_fe_set_handlers(&s->chr, parallel_can_receive, NULL,
diff --git a/hw/char/serial-isa.c b/hw/char/serial-isa.c
index 1b8b303079..7a7ed239cd 100644
--- a/hw/char/serial-isa.c
+++ b/hw/char/serial-isa.c
@@ -75,7 +75,7 @@ static void serial_isa_realizefn(DeviceState *dev, Error **errp)
}
index++;
- isa_init_irq(isadev, &s->irq, isa->isairq);
+ s->irq = isa_get_irq(isadev, isa->isairq);
qdev_realize(DEVICE(s), NULL, errp);
qdev_set_legacy_instance_id(dev, isa->iobase, 3);
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index ebd47aa26f..4ad4d7286c 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -38,6 +38,7 @@
#include "hw/nvram/fw_cfg.h"
#include "hw/acpi/bios-linker-loader.h"
#include "hw/isa/isa.h"
+#include "hw/input/i8042.h"
#include "hw/block/fdc.h"
#include "hw/acpi/memory_hotplug.h"
#include "sysemu/tpm.h"
@@ -192,6 +193,13 @@ static void init_common_fadt_data(MachineState *ms, Object *o,
.address = object_property_get_uint(o, ACPI_PM_PROP_GPE0_BLK, NULL)
},
};
+
+ /*
+ * ACPI v2, Table 5-10 - Fixed ACPI Description Table Boot Architecture
+ * Flags, bit offset 1 - 8042.
+ */
+ fadt.iapc_boot_arch = iapc_boot_arch_8042();
+
*data = fadt;
}
diff --git a/hw/i386/acpi-microvm.c b/hw/i386/acpi-microvm.c
index 68ca7e7fc2..fb09185cbd 100644
--- a/hw/i386/acpi-microvm.c
+++ b/hw/i386/acpi-microvm.c
@@ -37,6 +37,7 @@
#include "hw/pci/pcie_host.h"
#include "hw/usb/xhci.h"
#include "hw/virtio/virtio-mmio.h"
+#include "hw/input/i8042.h"
#include "acpi-common.h"
#include "acpi-microvm.h"
@@ -187,6 +188,11 @@ static void acpi_build_microvm(AcpiBuildTables *tables,
.address = GED_MMIO_BASE_REGS + ACPI_GED_REG_RESET,
},
.reset_val = ACPI_GED_RESET_VALUE,
+ /*
+ * ACPI v2, Table 5-10 - Fixed ACPI Description Table Boot Architecture
+ * Flags, bit offset 1 - 8042.
+ */
+ .iapc_boot_arch = iapc_boot_arch_8042(),
};
table_offsets = g_array_new(false, true /* clear */,
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index 4c6c016388..32471a44cb 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -3030,6 +3030,13 @@ static int vtd_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu,
VTDAddressSpace *vtd_as = container_of(iommu, VTDAddressSpace, iommu);
IntelIOMMUState *s = vtd_as->iommu_state;
+ /* TODO: add support for VFIO and vhost users */
+ if (s->snoop_control) {
+ error_setg_errno(errp, -ENOTSUP,
+ "Snoop Control with vhost or VFIO is not supported");
+ return -ENOTSUP;
+ }
+
/* Update per-address-space notifier flags */
vtd_as->notifier_flags = new;
@@ -3113,6 +3120,7 @@ static Property vtd_properties[] = {
VTD_HOST_ADDRESS_WIDTH),
DEFINE_PROP_BOOL("caching-mode", IntelIOMMUState, caching_mode, FALSE),
DEFINE_PROP_BOOL("x-scalable-mode", IntelIOMMUState, scalable_mode, FALSE),
+ DEFINE_PROP_BOOL("snoop-control", IntelIOMMUState, snoop_control, false),
DEFINE_PROP_BOOL("dma-drain", IntelIOMMUState, dma_drain, true),
DEFINE_PROP_END_OF_LIST(),
};
@@ -3643,7 +3651,7 @@ static void vtd_init(IntelIOMMUState *s)
vtd_spte_rsvd_large[3] = VTD_SPTE_LPAGE_L3_RSVD_MASK(s->aw_bits,
x86_iommu->dt_supported);
- if (s->scalable_mode) {
+ if (s->scalable_mode || s->snoop_control) {
vtd_spte_rsvd[1] &= ~VTD_SPTE_SNP;
vtd_spte_rsvd_large[2] &= ~VTD_SPTE_SNP;
vtd_spte_rsvd_large[3] &= ~VTD_SPTE_SNP;
@@ -3674,6 +3682,10 @@ static void vtd_init(IntelIOMMUState *s)
s->ecap |= VTD_ECAP_SMTS | VTD_ECAP_SRS | VTD_ECAP_SLTS;
}
+ if (s->snoop_control) {
+ s->ecap |= VTD_ECAP_SC;
+ }
+
vtd_reset_caches(s);
/* Define registers with default values and bit semantics */
diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h
index a6c788049b..1ff13b40f9 100644
--- a/hw/i386/intel_iommu_internal.h
+++ b/hw/i386/intel_iommu_internal.h
@@ -188,6 +188,7 @@
#define VTD_ECAP_IR (1ULL << 3)
#define VTD_ECAP_EIM (1ULL << 4)
#define VTD_ECAP_PT (1ULL << 6)
+#define VTD_ECAP_SC (1ULL << 7)
#define VTD_ECAP_MHMV (15ULL << 20)
#define VTD_ECAP_SRS (1ULL << 31)
#define VTD_ECAP_SMTS (1ULL << 43)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index c8696ac01e..fd55fc725c 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -318,8 +318,6 @@ GlobalProperty pc_compat_2_0[] = {
{ "pci-serial-4x", "prog_if", "0" },
{ "virtio-net-pci", "guest_announce", "off" },
{ "ICH9-LPC", "memory-hotplug-support", "off" },
- { "xio3130-downstream", COMPAT_PROP_PCP, "off" },
- { "ioh3420", COMPAT_PROP_PCP, "off" },
};
const size_t pc_compat_2_0_len = G_N_ELEMENTS(pc_compat_2_0);
@@ -1014,7 +1012,8 @@ static const MemoryRegionOps ioportF0_io_ops = {
},
};
-static void pc_superio_init(ISABus *isa_bus, bool create_fdctrl, bool no_vmport)
+static void pc_superio_init(ISABus *isa_bus, bool create_fdctrl,
+ bool create_i8042, bool no_vmport)
{
int i;
DriveInfo *fd[MAX_FD];
@@ -1036,6 +1035,10 @@ static void pc_superio_init(ISABus *isa_bus, bool create_fdctrl, bool no_vmport)
}
}
+ if (!create_i8042) {
+ return;
+ }
+
i8042 = isa_create_simple(isa_bus, "i8042");
if (!no_vmport) {
isa_create_simple(isa_bus, TYPE_VMPORT);
@@ -1131,7 +1134,8 @@ void pc_basic_device_init(struct PCMachineState *pcms,
i8257_dma_init(isa_bus, 0);
/* Super I/O */
- pc_superio_init(isa_bus, create_fdctrl, pcms->vmport != ON_OFF_AUTO_ON);
+ pc_superio_init(isa_bus, create_fdctrl, pcms->i8042_enabled,
+ pcms->vmport != ON_OFF_AUTO_ON);
}
void pc_nic_init(PCMachineClass *pcmc, ISABus *isa_bus, PCIBus *pci_bus)
@@ -1512,6 +1516,20 @@ static void pc_machine_set_hpet(Object *obj, bool value, Error **errp)
pcms->hpet_enabled = value;
}
+static bool pc_machine_get_i8042(Object *obj, Error **errp)
+{
+ PCMachineState *pcms = PC_MACHINE(obj);
+
+ return pcms->i8042_enabled;
+}
+
+static void pc_machine_set_i8042(Object *obj, bool value, Error **errp)
+{
+ PCMachineState *pcms = PC_MACHINE(obj);
+
+ pcms->i8042_enabled = value;
+}
+
static bool pc_machine_get_default_bus_bypass_iommu(Object *obj, Error **errp)
{
PCMachineState *pcms = PC_MACHINE(obj);
@@ -1641,6 +1659,7 @@ static void pc_machine_initfn(Object *obj)
pcms->smbus_enabled = true;
pcms->sata_enabled = true;
pcms->pit_enabled = true;
+ pcms->i8042_enabled = true;
pcms->max_fw_size = 8 * MiB;
#ifdef CONFIG_HPET
pcms->hpet_enabled = true;
@@ -1777,6 +1796,9 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
object_class_property_set_description(oc, "hpet",
"Enable/disable high precision event timer emulation");
+ object_class_property_add_bool(oc, PC_MACHINE_I8042,
+ pc_machine_get_i8042, pc_machine_set_i8042);
+
object_class_property_add_bool(oc, "default-bus-bypass-iommu",
pc_machine_get_default_bus_bypass_iommu,
pc_machine_set_default_bus_bypass_iommu);
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 8d33cf689d..b72c03d0a6 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -757,6 +757,7 @@ static void pc_i440fx_1_7_machine_options(MachineClass *m)
m->hw_version = "1.7.0";
m->default_machine_opts = NULL;
m->option_rom_has_mr = true;
+ m->deprecation_reason = "old and unattended - use a newer version instead";
compat_props_add(m->compat_props, pc_compat_1_7, pc_compat_1_7_len);
pcmc->smbios_defaults = false;
pcmc->gigabyte_align = false;
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index b84840a1bb..4cf107baea 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -83,24 +83,11 @@ inline void init_topo_info(X86CPUTopoInfo *topo_info,
uint32_t x86_cpu_apic_id_from_index(X86MachineState *x86ms,
unsigned int cpu_index)
{
- X86MachineClass *x86mc = X86_MACHINE_GET_CLASS(x86ms);
X86CPUTopoInfo topo_info;
- uint32_t correct_id;
- static bool warned;
init_topo_info(&topo_info, x86ms);
- correct_id = x86_apicid_from_cpu_idx(&topo_info, cpu_index);
- if (x86mc->compat_apic_id_mode) {
- if (cpu_index != correct_id && !warned && !qtest_enabled()) {
- error_report("APIC IDs set in compatibility mode, "
- "CPU topology won't match the configuration");
- warned = true;
- }
- return cpu_index;
- } else {
- return correct_id;
- }
+ return x86_apicid_from_cpu_idx(&topo_info, cpu_index);
}
@@ -1330,7 +1317,6 @@ static void x86_machine_class_init(ObjectClass *oc, void *data)
mc->cpu_index_to_instance_props = x86_cpu_index_to_props;
mc->get_default_cpu_node_id = x86_get_default_cpu_node_id;
mc->possible_cpu_arch_ids = x86_possible_cpu_arch_ids;
- x86mc->compat_apic_id_mode = false;
x86mc->save_tsc_khz = true;
x86mc->fwcfg_dma_enabled = true;
nc->nmi_monitor_handler = x86_nmi;
diff --git a/hw/ide/core.c b/hw/ide/core.c
index d667d0b55e..3a5afff5d7 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -30,6 +30,7 @@
#include "qemu/main-loop.h"
#include "qemu/timer.h"
#include "qemu/hw-version.h"
+#include "qemu/memalign.h"
#include "sysemu/sysemu.h"
#include "sysemu/blockdev.h"
#include "sysemu/dma.h"
diff --git a/hw/ide/isa.c b/hw/ide/isa.c
index 24bbde24c2..8bedbd13f1 100644
--- a/hw/ide/isa.c
+++ b/hw/ide/isa.c
@@ -75,7 +75,7 @@ static void isa_ide_realizefn(DeviceState *dev, Error **errp)
ide_bus_init(&s->bus, sizeof(s->bus), dev, 0, 2);
ide_init_ioport(&s->bus, isadev, s->iobase, s->iobase2);
- isa_init_irq(isadev, &s->irq, s->isairq);
+ s->irq = isa_get_irq(isadev, s->isairq);
ide_init2(&s->bus, s->irq);
vmstate_register(VMSTATE_IF(dev), 0, &vmstate_ide_isa, s);
ide_register_restart_cb(&s->bus);
diff --git a/hw/input/pckbd.c b/hw/input/pckbd.c
index baba62f357..1773db0d25 100644
--- a/hw/input/pckbd.c
+++ b/hw/input/pckbd.c
@@ -26,6 +26,7 @@
#include "qemu/error-report.h"
#include "qemu/log.h"
#include "qemu/timer.h"
+#include "qapi/error.h"
#include "hw/isa/isa.h"
#include "migration/vmstate.h"
#include "hw/acpi/aml-build.h"
@@ -671,6 +672,8 @@ struct ISAKBDState {
KBDState kbd;
bool kbd_throttle;
MemoryRegion io[2];
+ uint8_t kbd_irq;
+ uint8_t mouse_irq;
};
void i8042_isa_mouse_fake_event(ISAKBDState *isa)
@@ -734,8 +737,20 @@ static void i8042_realizefn(DeviceState *dev, Error **errp)
ISAKBDState *isa_s = I8042(dev);
KBDState *s = &isa_s->kbd;
- isa_init_irq(isadev, &s->irq_kbd, 1);
- isa_init_irq(isadev, &s->irq_mouse, 12);
+ if (isa_s->kbd_irq >= ISA_NUM_IRQS) {
+ error_setg(errp, "Maximum value for \"kbd-irq\" is: %u",
+ ISA_NUM_IRQS - 1);
+ return;
+ }
+
+ if (isa_s->mouse_irq >= ISA_NUM_IRQS) {
+ error_setg(errp, "Maximum value for \"mouse-irq\" is: %u",
+ ISA_NUM_IRQS - 1);
+ return;
+ }
+
+ s->irq_kbd = isa_get_irq(isadev, isa_s->kbd_irq);
+ s->irq_mouse = isa_get_irq(isadev, isa_s->mouse_irq);
isa_register_ioport(isadev, isa_s->io + 0, 0x60);
isa_register_ioport(isadev, isa_s->io + 1, 0x64);
@@ -754,6 +769,7 @@ static void i8042_realizefn(DeviceState *dev, Error **errp)
static void i8042_build_aml(ISADevice *isadev, Aml *scope)
{
+ ISAKBDState *isa_s = I8042(isadev);
Aml *kbd;
Aml *mou;
Aml *crs;
@@ -761,7 +777,7 @@ static void i8042_build_aml(ISADevice *isadev, Aml *scope)
crs = aml_resource_template();
aml_append(crs, aml_io(AML_DECODE16, 0x0060, 0x0060, 0x01, 0x01));
aml_append(crs, aml_io(AML_DECODE16, 0x0064, 0x0064, 0x01, 0x01));
- aml_append(crs, aml_irq_no_flags(1));
+ aml_append(crs, aml_irq_no_flags(isa_s->kbd_irq));
kbd = aml_device("KBD");
aml_append(kbd, aml_name_decl("_HID", aml_eisaid("PNP0303")));
@@ -769,7 +785,7 @@ static void i8042_build_aml(ISADevice *isadev, Aml *scope)
aml_append(kbd, aml_name_decl("_CRS", crs));
crs = aml_resource_template();
- aml_append(crs, aml_irq_no_flags(12));
+ aml_append(crs, aml_irq_no_flags(isa_s->mouse_irq));
mou = aml_device("MOU");
aml_append(mou, aml_name_decl("_HID", aml_eisaid("PNP0F13")));
@@ -783,6 +799,8 @@ static void i8042_build_aml(ISADevice *isadev, Aml *scope)
static Property i8042_properties[] = {
DEFINE_PROP_BOOL("extended-state", ISAKBDState, kbd.extended_state, true),
DEFINE_PROP_BOOL("kbd-throttle", ISAKBDState, kbd_throttle, false),
+ DEFINE_PROP_UINT8("kbd-irq", ISAKBDState, kbd_irq, 1),
+ DEFINE_PROP_UINT8("mouse-irq", ISAKBDState, mouse_irq, 12),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
index 6d3c8ee231..0b8f79a122 100644
--- a/hw/intc/arm_gicv3.c
+++ b/hw/intc/arm_gicv3.c
@@ -369,11 +369,19 @@ static const MemoryRegionOps gic_ops[] = {
.read_with_attrs = gicv3_dist_read,
.write_with_attrs = gicv3_dist_write,
.endianness = DEVICE_NATIVE_ENDIAN,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 8,
+ .impl.min_access_size = 1,
+ .impl.max_access_size = 8,
},
{
.read_with_attrs = gicv3_redist_read,
.write_with_attrs = gicv3_redist_write,
.endianness = DEVICE_NATIVE_ENDIAN,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 8,
+ .impl.min_access_size = 1,
+ .impl.max_access_size = 8,
}
};
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index d7e03d0cab..1a3d440a54 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -612,7 +612,8 @@ static uint64_t icv_hppir_read(CPUARMState *env, const ARMCPRegInfo *ri)
}
}
- trace_gicv3_icv_hppir_read(grp, gicv3_redist_affid(cs), value);
+ trace_gicv3_icv_hppir_read(ri->crm == 8 ? 0 : 1,
+ gicv3_redist_affid(cs), value);
return value;
}
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
index 4164500ea9..28d913b211 100644
--- a/hw/intc/arm_gicv3_dist.c
+++ b/hw/intc/arm_gicv3_dist.c
@@ -838,7 +838,7 @@ MemTxResult gicv3_dist_read(void *opaque, hwaddr offset, uint64_t *data,
if (!r) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: invalid guest read at offset " TARGET_FMT_plx
- "size %u\n", __func__, offset, size);
+ " size %u\n", __func__, offset, size);
trace_gicv3_dist_badread(offset, size, attrs.secure);
/* The spec requires that reserved registers are RAZ/WI;
* so use MEMTX_ERROR returns from leaf functions as a way to
@@ -879,7 +879,7 @@ MemTxResult gicv3_dist_write(void *opaque, hwaddr offset, uint64_t data,
if (!r) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: invalid guest write at offset " TARGET_FMT_plx
- "size %u\n", __func__, offset, size);
+ " size %u\n", __func__, offset, size);
trace_gicv3_dist_badwrite(offset, data, size, attrs.secure);
/* The spec requires that reserved registers are RAZ/WI;
* so use MEMTX_ERROR returns from leaf functions as a way to
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 4f598d3c14..b96b874afd 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -161,16 +161,22 @@ static MemTxResult get_cte(GICv3ITSState *s, uint16_t icid, CTEntry *cte)
if (entry_addr == -1) {
/* No L2 table entry, i.e. no valid CTE, or a memory error */
cte->valid = false;
- return res;
+ goto out;
}
cteval = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, &res);
if (res != MEMTX_OK) {
- return res;
+ goto out;
}
cte->valid = FIELD_EX64(cteval, CTE, VALID);
cte->rdbase = FIELD_EX64(cteval, CTE, RDBASE);
- return MEMTX_OK;
+out:
+ if (res != MEMTX_OK) {
+ trace_gicv3_its_cte_read_fault(icid);
+ } else {
+ trace_gicv3_its_cte_read(icid, cte->valid, cte->rdbase);
+ }
+ return res;
}
/*
@@ -187,6 +193,10 @@ static bool update_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
uint64_t itel = 0;
uint32_t iteh = 0;
+ trace_gicv3_its_ite_write(dte->ittaddr, eventid, ite->valid,
+ ite->inttype, ite->intid, ite->icid,
+ ite->vpeid, ite->doorbell);
+
if (ite->valid) {
itel = FIELD_DP64(itel, ITE_L, VALID, 1);
itel = FIELD_DP64(itel, ITE_L, INTTYPE, ite->inttype);
@@ -221,11 +231,13 @@ static MemTxResult get_ite(GICv3ITSState *s, uint32_t eventid,
itel = address_space_ldq_le(as, iteaddr, MEMTXATTRS_UNSPECIFIED, &res);
if (res != MEMTX_OK) {
+ trace_gicv3_its_ite_read_fault(dte->ittaddr, eventid);
return res;
}
iteh = address_space_ldl_le(as, iteaddr + 8, MEMTXATTRS_UNSPECIFIED, &res);
if (res != MEMTX_OK) {
+ trace_gicv3_its_ite_read_fault(dte->ittaddr, eventid);
return res;
}
@@ -235,6 +247,9 @@ static MemTxResult get_ite(GICv3ITSState *s, uint32_t eventid,
ite->icid = FIELD_EX64(itel, ITE_L, ICID);
ite->vpeid = FIELD_EX64(itel, ITE_L, VPEID);
ite->doorbell = FIELD_EX64(iteh, ITE_H, DOORBELL);
+ trace_gicv3_its_ite_read(dte->ittaddr, eventid, ite->valid,
+ ite->inttype, ite->intid, ite->icid,
+ ite->vpeid, ite->doorbell);
return MEMTX_OK;
}
@@ -254,17 +269,23 @@ static MemTxResult get_dte(GICv3ITSState *s, uint32_t devid, DTEntry *dte)
if (entry_addr == -1) {
/* No L2 table entry, i.e. no valid DTE, or a memory error */
dte->valid = false;
- return res;
+ goto out;
}
dteval = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, &res);
if (res != MEMTX_OK) {
- return res;
+ goto out;
}
dte->valid = FIELD_EX64(dteval, DTE, VALID);
dte->size = FIELD_EX64(dteval, DTE, SIZE);
/* DTE word field stores bits [51:8] of the ITT address */
dte->ittaddr = FIELD_EX64(dteval, DTE, ITTADDR) << ITTADDR_SHIFT;
- return MEMTX_OK;
+out:
+ if (res != MEMTX_OK) {
+ trace_gicv3_its_dte_read_fault(devid);
+ } else {
+ trace_gicv3_its_dte_read(devid, dte->valid, dte->size, dte->ittaddr);
+ }
+ return res;
}
/*
@@ -366,6 +387,19 @@ static ItsCmdResult process_its_cmd(GICv3ITSState *s, const uint64_t *cmdpkt,
devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
eventid = cmdpkt[1] & EVENTID_MASK;
+ switch (cmd) {
+ case INTERRUPT:
+ trace_gicv3_its_cmd_int(devid, eventid);
+ break;
+ case CLEAR:
+ trace_gicv3_its_cmd_clear(devid, eventid);
+ break;
+ case DISCARD:
+ trace_gicv3_its_cmd_discard(devid, eventid);
+ break;
+ default:
+ g_assert_not_reached();
+ }
return do_process_its_cmd(s, devid, eventid, cmd);
}
@@ -382,15 +416,16 @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
devid = (cmdpkt[0] & DEVID_MASK) >> DEVID_SHIFT;
eventid = cmdpkt[1] & EVENTID_MASK;
+ icid = cmdpkt[2] & ICID_MASK;
if (ignore_pInt) {
pIntid = eventid;
+ trace_gicv3_its_cmd_mapi(devid, eventid, icid);
} else {
pIntid = (cmdpkt[1] & pINTID_MASK) >> pINTID_SHIFT;
+ trace_gicv3_its_cmd_mapti(devid, eventid, icid, pIntid);
}
- icid = cmdpkt[2] & ICID_MASK;
-
if (devid >= s->dt.num_entries) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: invalid command attributes: devid %d>=%d",
@@ -451,6 +486,8 @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, const CTEntry *cte)
uint64_t cteval = 0;
MemTxResult res = MEMTX_OK;
+ trace_gicv3_its_cte_write(icid, cte->valid, cte->rdbase);
+
if (cte->valid) {
/* add mapping entry to collection table */
cteval = FIELD_DP64(cteval, CTE, VALID, 1);
@@ -484,6 +521,7 @@ static ItsCmdResult process_mapc(GICv3ITSState *s, const uint64_t *cmdpkt)
} else {
cte.rdbase = 0;
}
+ trace_gicv3_its_cmd_mapc(icid, cte.rdbase, cte.valid);
if (icid >= s->ct.num_entries) {
qemu_log_mask(LOG_GUEST_ERROR, "ITS MAPC: invalid ICID 0x%d", icid);
@@ -509,6 +547,8 @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, const DTEntry *dte)
uint64_t dteval = 0;
MemTxResult res = MEMTX_OK;
+ trace_gicv3_its_dte_write(devid, dte->valid, dte->size, dte->ittaddr);
+
if (dte->valid) {
/* add mapping entry to device table */
dteval = FIELD_DP64(dteval, DTE, VALID, 1);
@@ -539,6 +579,8 @@ static ItsCmdResult process_mapd(GICv3ITSState *s, const uint64_t *cmdpkt)
dte.ittaddr = (cmdpkt[2] & ITTADDR_MASK) >> ITTADDR_SHIFT;
dte.valid = cmdpkt[2] & CMD_FIELD_VALID_MASK;
+ trace_gicv3_its_cmd_mapd(devid, dte.size, dte.ittaddr, dte.valid);
+
if (devid >= s->dt.num_entries) {
qemu_log_mask(LOG_GUEST_ERROR,
"ITS MAPD: invalid device ID field 0x%x >= 0x%x\n",
@@ -562,6 +604,8 @@ static ItsCmdResult process_movall(GICv3ITSState *s, const uint64_t *cmdpkt)
rd1 = FIELD_EX64(cmdpkt[2], MOVALL_2, RDBASE1);
rd2 = FIELD_EX64(cmdpkt[3], MOVALL_3, RDBASE2);
+ trace_gicv3_its_cmd_movall(rd1, rd2);
+
if (rd1 >= s->gicv3->num_cpu) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: RDBASE1 %" PRId64
@@ -601,6 +645,8 @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
eventid = FIELD_EX64(cmdpkt[1], MOVI_1, EVENTID);
new_icid = FIELD_EX64(cmdpkt[2], MOVI_2, ICID);
+ trace_gicv3_its_cmd_movi(devid, eventid, new_icid);
+
if (devid >= s->dt.num_entries) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: invalid command attributes: devid %d>=%d",
@@ -779,6 +825,7 @@ static void process_cmdq(GICv3ITSState *s)
* is already consistent by the time SYNC command is executed.
* Hence no further processing is required for SYNC command.
*/
+ trace_gicv3_its_cmd_sync();
break;
case GITS_CMD_MAPD:
result = process_mapd(s, cmdpkt);
@@ -803,6 +850,7 @@ static void process_cmdq(GICv3ITSState *s)
* need to trigger lpi priority re-calculation to be in
* sync with LPI config table or pending table changes.
*/
+ trace_gicv3_its_cmd_inv();
for (i = 0; i < s->gicv3->num_cpu; i++) {
gicv3_redist_update_lpi(&s->gicv3->cpu[i]);
}
@@ -814,6 +862,7 @@ static void process_cmdq(GICv3ITSState *s)
result = process_movall(s, cmdpkt);
break;
default:
+ trace_gicv3_its_cmd_unknown(cmd);
break;
}
if (result == CMD_CONTINUE) {
@@ -1264,7 +1313,7 @@ static MemTxResult gicv3_its_read(void *opaque, hwaddr offset, uint64_t *data,
if (!result) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: invalid guest read at offset " TARGET_FMT_plx
- "size %u\n", __func__, offset, size);
+ " size %u\n", __func__, offset, size);
trace_gicv3_its_badread(offset, size);
/*
* The spec requires that reserved registers are RAZ/WI;
@@ -1300,7 +1349,7 @@ static MemTxResult gicv3_its_write(void *opaque, hwaddr offset, uint64_t data,
if (!result) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: invalid guest write at offset " TARGET_FMT_plx
- "size %u\n", __func__, offset, size);
+ " size %u\n", __func__, offset, size);
trace_gicv3_its_badwrite(offset, data, size);
/*
* The spec requires that reserved registers are RAZ/WI;
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index b28cda4e08..53414aa197 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -176,6 +176,27 @@ gicv3_its_write(uint64_t offset, uint64_t data, unsigned size) "GICv3 ITS write:
gicv3_its_badwrite(uint64_t offset, uint64_t data, unsigned size) "GICv3 ITS write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u: error"
gicv3_its_translation_write(uint64_t offset, uint64_t data, unsigned size, uint32_t requester_id) "GICv3 ITS TRANSLATER write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u requester_id 0x%x"
gicv3_its_process_command(uint32_t rd_offset, uint8_t cmd) "GICv3 ITS: processing command at offset 0x%x: 0x%x"
+gicv3_its_cmd_int(uint32_t devid, uint32_t eventid) "GICv3 ITS: command INT DeviceID 0x%x EventID 0x%x"
+gicv3_its_cmd_clear(uint32_t devid, uint32_t eventid) "GICv3 ITS: command CLEAR DeviceID 0x%x EventID 0x%x"
+gicv3_its_cmd_discard(uint32_t devid, uint32_t eventid) "GICv3 ITS: command DISCARD DeviceID 0x%x EventID 0x%x"
+gicv3_its_cmd_sync(void) "GICv3 ITS: command SYNC"
+gicv3_its_cmd_mapd(uint32_t devid, uint32_t size, uint64_t ittaddr, int valid) "GICv3 ITS: command MAPD DeviceID 0x%x Size 0x%x ITT_addr 0x%" PRIx64 " V %d"
+gicv3_its_cmd_mapc(uint32_t icid, uint64_t rdbase, int valid) "GICv3 ITS: command MAPC ICID 0x%x RDbase 0x%" PRIx64 " V %d"
+gicv3_its_cmd_mapi(uint32_t devid, uint32_t eventid, uint32_t icid) "GICv3 ITS: command MAPI DeviceID 0x%x EventID 0x%x ICID 0x%x"
+gicv3_its_cmd_mapti(uint32_t devid, uint32_t eventid, uint32_t icid, uint32_t intid) "GICv3 ITS: command MAPTI DeviceID 0x%x EventID 0x%x ICID 0x%x pINTID 0x%x"
+gicv3_its_cmd_inv(void) "GICv3 ITS: command INV or INVALL"
+gicv3_its_cmd_movall(uint64_t rd1, uint64_t rd2) "GICv3 ITS: command MOVALL RDbase1 0x%" PRIx64 " RDbase2 0x%" PRIx64
+gicv3_its_cmd_movi(uint32_t devid, uint32_t eventid, uint32_t icid) "GICv3 ITS: command MOVI DeviceID 0x%x EventID 0x%x ICID 0x%x"
+gicv3_its_cmd_unknown(unsigned cmd) "GICv3 ITS: unknown command 0x%x"
+gicv3_its_cte_read(uint32_t icid, int valid, uint32_t rdbase) "GICv3 ITS: Collection Table read for ICID 0x%x: valid %d RDBase 0x%x"
+gicv3_its_cte_write(uint32_t icid, int valid, uint32_t rdbase) "GICv3 ITS: Collection Table write for ICID 0x%x: valid %d RDBase 0x%x"
+gicv3_its_cte_read_fault(uint32_t icid) "GICv3 ITS: Collection Table read for ICID 0x%x: faulted"
+gicv3_its_ite_read(uint64_t ittaddr, uint32_t eventid, int valid, int inttype, uint32_t intid, uint32_t icid, uint32_t vpeid, uint32_t doorbell) "GICv3 ITS: Interrupt Table read for ITTaddr 0x%" PRIx64 " EventID 0x%x: valid %d inttype %d intid 0x%x ICID 0x%x vPEID 0x%x doorbell 0x%x"
+gicv3_its_ite_read_fault(uint64_t ittaddr, uint32_t eventid) "GICv3 ITS: Interrupt Table read for ITTaddr 0x%" PRIx64 " EventID 0x%x: faulted"
+gicv3_its_ite_write(uint64_t ittaddr, uint32_t eventid, int valid, int inttype, uint32_t intid, uint32_t icid, uint32_t vpeid, uint32_t doorbell) "GICv3 ITS: Interrupt Table write for ITTaddr 0x%" PRIx64 " EventID 0x%x: valid %d inttype %d intid 0x%x ICID 0x%x vPEID 0x%x doorbell 0x%x"
+gicv3_its_dte_read(uint32_t devid, int valid, uint32_t size, uint64_t ittaddr) "GICv3 ITS: Device Table read for DeviceID 0x%x: valid %d size 0x%x ITTaddr 0x%" PRIx64
+gicv3_its_dte_write(uint32_t devid, int valid, uint32_t size, uint64_t ittaddr) "GICv3 ITS: Device Table write for DeviceID 0x%x: valid %d size 0x%x ITTaddr 0x%" PRIx64
+gicv3_its_dte_read_fault(uint32_t devid) "GICv3 ITS: Device Table read for DeviceID 0x%x: faulted"
# armv7m_nvic.c
nvic_recompute_state(int vectpending, int vectpending_prio, int exception_prio) "NVIC state recomputed: vectpending %d vectpending_prio %d exception_prio %d"
diff --git a/hw/ipmi/isa_ipmi_bt.c b/hw/ipmi/isa_ipmi_bt.c
index 02625eb94e..88aa734e9e 100644
--- a/hw/ipmi/isa_ipmi_bt.c
+++ b/hw/ipmi/isa_ipmi_bt.c
@@ -92,7 +92,7 @@ static void isa_ipmi_bt_realize(DeviceState *dev, Error **errp)
}
if (iib->isairq > 0) {
- isa_init_irq(isadev, &iib->irq, iib->isairq);
+ iib->irq = isa_get_irq(isadev, iib->isairq);
iib->bt.use_irq = 1;
iib->bt.raise_irq = isa_ipmi_bt_raise_irq;
iib->bt.lower_irq = isa_ipmi_bt_lower_irq;
diff --git a/hw/ipmi/isa_ipmi_kcs.c b/hw/ipmi/isa_ipmi_kcs.c
index 3b23ad08b3..afabb95ebe 100644
--- a/hw/ipmi/isa_ipmi_kcs.c
+++ b/hw/ipmi/isa_ipmi_kcs.c
@@ -91,7 +91,7 @@ static void ipmi_isa_realize(DeviceState *dev, Error **errp)
}
if (iik->isairq > 0) {
- isa_init_irq(isadev, &iik->irq, iik->isairq);
+ iik->irq = isa_get_irq(isadev, iik->isairq);
iik->kcs.use_irq = 1;
iik->kcs.raise_irq = isa_ipmi_kcs_raise_irq;
iik->kcs.lower_irq = isa_ipmi_kcs_lower_irq;
diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c
index 6c31398dda..0ad1c5fd65 100644
--- a/hw/isa/isa-bus.c
+++ b/hw/isa/isa-bus.c
@@ -21,21 +21,18 @@
#include "qemu/error-report.h"
#include "qemu/module.h"
#include "qapi/error.h"
-#include "monitor/monitor.h"
#include "hw/sysbus.h"
#include "sysemu/sysemu.h"
#include "hw/isa/isa.h"
static ISABus *isabus;
-static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent);
static char *isabus_get_fw_dev_path(DeviceState *dev);
static void isa_bus_class_init(ObjectClass *klass, void *data)
{
BusClass *k = BUS_CLASS(klass);
- k->print_dev = isabus_dev_print;
k->get_fw_dev_path = isabus_get_fw_dev_path;
}
@@ -88,19 +85,9 @@ qemu_irq isa_get_irq(ISADevice *dev, unsigned isairq)
return isabus->irqs[isairq];
}
-void isa_init_irq(ISADevice *dev, qemu_irq *p, unsigned isairq)
-{
- assert(dev->nirqs < ARRAY_SIZE(dev->isairq));
- assert(isairq < ISA_NUM_IRQS);
- dev->isairq[dev->nirqs] = isairq;
- *p = isa_get_irq(dev, isairq);
- dev->nirqs++;
-}
-
void isa_connect_gpio_out(ISADevice *isadev, int gpioirq, unsigned isairq)
{
- qemu_irq irq;
- isa_init_irq(isadev, &irq, isairq);
+ qemu_irq irq = isa_get_irq(isadev, isairq);
qdev_connect_gpio_out(DEVICE(isadev), gpioirq, irq);
}
@@ -153,14 +140,6 @@ int isa_register_portio_list(ISADevice *dev,
return 0;
}
-static void isa_device_init(Object *obj)
-{
- ISADevice *dev = ISA_DEVICE(obj);
-
- dev->isairq[0] = -1;
- dev->isairq[1] = -1;
-}
-
ISADevice *isa_new(const char *name)
{
return ISA_DEVICE(qdev_new(name));
@@ -222,19 +201,6 @@ void isa_build_aml(ISABus *bus, Aml *scope)
}
}
-static void isabus_dev_print(Monitor *mon, DeviceState *dev, int indent)
-{
- ISADevice *d = ISA_DEVICE(dev);
-
- if (d->isairq[1] != -1) {
- monitor_printf(mon, "%*sisa irqs %d,%d\n", indent, "",
- d->isairq[0], d->isairq[1]);
- } else if (d->isairq[0] != -1) {
- monitor_printf(mon, "%*sisa irq %d\n", indent, "",
- d->isairq[0]);
- }
-}
-
static void isabus_bridge_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -260,7 +226,6 @@ static const TypeInfo isa_device_type_info = {
.name = TYPE_ISA_DEVICE,
.parent = TYPE_DEVICE,
.instance_size = sizeof(ISADevice),
- .instance_init = isa_device_init,
.abstract = true,
.class_size = sizeof(ISADeviceClass),
.class_init = isa_device_class_init,
diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c
index 0fe7b69bc4..8607e0ac36 100644
--- a/hw/isa/piix4.c
+++ b/hw/isa/piix4.c
@@ -39,8 +39,6 @@
#include "sysemu/runstate.h"
#include "qom/object.h"
-PCIDevice *piix4_dev;
-
struct PIIX4State {
PCIDevice dev;
qemu_irq cpu_intr;
@@ -54,6 +52,27 @@ struct PIIX4State {
OBJECT_DECLARE_SIMPLE_TYPE(PIIX4State, PIIX4_PCI_DEVICE)
+static void piix4_set_irq(void *opaque, int irq_num, int level)
+{
+ int i, pic_irq, pic_level;
+ PIIX4State *s = opaque;
+ PCIBus *bus = pci_get_bus(&s->dev);
+
+ /* now we change the pic irq level according to the piix irq mappings */
+ /* XXX: optimize */
+ pic_irq = s->dev.config[PIIX_PIRQCA + irq_num];
+ if (pic_irq < ISA_NUM_IRQS) {
+ /* The pic level is the logical OR of all the PCI irqs mapped to it. */
+ pic_level = 0;
+ for (i = 0; i < PIIX_NUM_PIRQS; i++) {
+ if (pic_irq == s->dev.config[PIIX_PIRQCA + i]) {
+ pic_level |= pci_bus_get_irq_level(bus, i);
+ }
+ }
+ qemu_set_irq(s->isa[pic_irq], pic_level);
+ }
+}
+
static void piix4_isa_reset(DeviceState *dev)
{
PIIX4State *d = PIIX4_PCI_DEVICE(dev);
@@ -197,9 +216,7 @@ static void piix4_realize(PCIDevice *dev, Error **errp)
if (!qdev_realize(DEVICE(&s->rtc), BUS(isa_bus), errp)) {
return;
}
- isa_init_irq(ISA_DEVICE(&s->rtc), &s->rtc.irq, RTC_ISA_IRQ);
-
- piix4_dev = dev;
+ s->rtc.irq = isa_get_irq(ISA_DEVICE(&s->rtc), s->rtc.isairq);
}
static void piix4_init(Object *obj)
@@ -248,8 +265,34 @@ static void piix4_register_types(void)
type_init(piix4_register_types)
+static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
+{
+ int slot;
+
+ slot = PCI_SLOT(pci_dev->devfn);
+
+ switch (slot) {
+ /* PIIX4 USB */
+ case 10:
+ return 3;
+ /* AMD 79C973 Ethernet */
+ case 11:
+ return 1;
+ /* Crystal 4281 Sound */
+ case 12:
+ return 2;
+ /* PCI slot 1 to 4 */
+ case 18 ... 21:
+ return ((slot - 18) + irq_num) & 0x03;
+ /* Unknown device, don't do any translation */
+ default:
+ return irq_num;
+ }
+}
+
DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus)
{
+ PIIX4State *s;
PCIDevice *pci;
DeviceState *dev;
int devfn = PCI_DEVFN(10, 0);
@@ -257,6 +300,7 @@ DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus)
pci = pci_create_simple_multifunction(pci_bus, devfn, true,
TYPE_PIIX4_PCI_DEVICE);
dev = DEVICE(pci);
+ s = PIIX4_PCI_DEVICE(pci);
if (isa_bus) {
*isa_bus = ISA_BUS(qdev_get_child_bus(dev, "isa.0"));
}
@@ -271,5 +315,7 @@ DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus)
NULL, 0, NULL);
}
+ pci_bus_irqs(pci_bus, piix4_set_irq, pci_slot_get_pirq, s, PIIX_NUM_PIRQS);
+
return dev;
}
diff --git a/hw/mips/gt64xxx_pci.c b/hw/mips/gt64xxx_pci.c
index c7480bd019..e0ff1b5566 100644
--- a/hw/mips/gt64xxx_pci.c
+++ b/hw/mips/gt64xxx_pci.c
@@ -26,10 +26,8 @@
#include "qapi/error.h"
#include "qemu/units.h"
#include "qemu/log.h"
-#include "hw/mips/mips.h"
#include "hw/pci/pci.h"
#include "hw/pci/pci_host.h"
-#include "hw/southbridge/piix.h"
#include "migration/vmstate.h"
#include "hw/intc/i8259.h"
#include "hw/irq.h"
@@ -981,56 +979,6 @@ static const MemoryRegionOps isd_mem_ops = {
},
};
-static int gt64120_pci_map_irq(PCIDevice *pci_dev, int irq_num)
-{
- int slot;
-
- slot = PCI_SLOT(pci_dev->devfn);
-
- switch (slot) {
- /* PIIX4 USB */
- case 10:
- return 3;
- /* AMD 79C973 Ethernet */
- case 11:
- return 1;
- /* Crystal 4281 Sound */
- case 12:
- return 2;
- /* PCI slot 1 to 4 */
- case 18 ... 21:
- return ((slot - 18) + irq_num) & 0x03;
- /* Unknown device, don't do any translation */
- default:
- return irq_num;
- }
-}
-
-static int pci_irq_levels[4];
-
-static void gt64120_pci_set_irq(void *opaque, int irq_num, int level)
-{
- int i, pic_irq, pic_level;
- qemu_irq *pic = opaque;
-
- pci_irq_levels[irq_num] = level;
-
- /* now we change the pic irq level according to the piix irq mappings */
- /* XXX: optimize */
- pic_irq = piix4_dev->config[PIIX_PIRQCA + irq_num];
- if (pic_irq < 16) {
- /* The pic level is the logical OR of all the PCI irqs mapped to it. */
- pic_level = 0;
- for (i = 0; i < 4; i++) {
- if (pic_irq == piix4_dev->config[PIIX_PIRQCA + i]) {
- pic_level |= pci_irq_levels[i];
- }
- }
- qemu_set_irq(pic[pic_irq], pic_level);
- }
-}
-
-
static void gt64120_reset(DeviceState *dev)
{
GT64120State *s = GT64120_PCI_HOST_BRIDGE(dev);
@@ -1202,32 +1150,18 @@ static void gt64120_reset(DeviceState *dev)
static void gt64120_realize(DeviceState *dev, Error **errp)
{
GT64120State *s = GT64120_PCI_HOST_BRIDGE(dev);
+ PCIHostState *phb = PCI_HOST_BRIDGE(dev);
memory_region_init_io(&s->ISD_mem, OBJECT(dev), &isd_mem_ops, s,
"gt64120-isd", 0x1000);
-}
-
-PCIBus *gt64120_register(qemu_irq *pic)
-{
- GT64120State *d;
- PCIHostState *phb;
- DeviceState *dev;
-
- dev = qdev_new(TYPE_GT64120_PCI_HOST_BRIDGE);
- d = GT64120_PCI_HOST_BRIDGE(dev);
- phb = PCI_HOST_BRIDGE(dev);
- memory_region_init(&d->pci0_mem, OBJECT(dev), "pci0-mem", 4 * GiB);
- address_space_init(&d->pci0_mem_as, &d->pci0_mem, "pci0-mem");
- phb->bus = pci_register_root_bus(dev, "pci",
- gt64120_pci_set_irq, gt64120_pci_map_irq,
- pic,
- &d->pci0_mem,
- get_system_io(),
- PCI_DEVFN(18, 0), 4, TYPE_PCI_BUS);
- sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
+ memory_region_init(&s->pci0_mem, OBJECT(dev), "pci0-mem", 4 * GiB);
+ address_space_init(&s->pci0_mem_as, &s->pci0_mem, "pci0-mem");
+ phb->bus = pci_root_bus_new(dev, "pci",
+ &s->pci0_mem,
+ get_system_io(),
+ PCI_DEVFN(18, 0), TYPE_PCI_BUS);
pci_create_simple(phb->bus, PCI_DEVFN(0, 0), "gt64120_pci");
- return phb->bus;
}
static void gt64120_pci_realize(PCIDevice *d, Error **errp)
diff --git a/hw/mips/malta.c b/hw/mips/malta.c
index b770b8d367..55037eb90f 100644
--- a/hw/mips/malta.c
+++ b/hw/mips/malta.c
@@ -97,7 +97,6 @@ struct MaltaState {
Clock *cpuclk;
MIPSCPSState cps;
- qemu_irq i8259[ISA_NUM_IRQS];
};
static struct _loaderparams {
@@ -1391,7 +1390,8 @@ void mips_malta_init(MachineState *machine)
stl_p(memory_region_get_ram_ptr(bios_copy) + 0x10, 0x00000420);
/* Northbridge */
- pci_bus = gt64120_register(s->i8259);
+ dev = sysbus_create_simple("gt64120", -1, NULL);
+ pci_bus = PCI_BUS(qdev_get_child_bus(dev, "pci"));
/*
* The whole address space decoded by the GT-64120A doesn't generate
* exception when accessing invalid memory. Create an empty slot to
@@ -1404,9 +1404,6 @@ void mips_malta_init(MachineState *machine)
/* Interrupt controller */
qdev_connect_gpio_out_named(dev, "intr", 0, i8259_irq);
- for (int i = 0; i < ISA_NUM_IRQS; i++) {
- s->i8259[i] = qdev_get_gpio_in_named(dev, "isa", i);
- }
/* generate SPD EEPROM data */
generate_eeprom_spd(&smbus_eeprom_buf[0 * 256], ram_size);
diff --git a/hw/misc/pvpanic-isa.c b/hw/misc/pvpanic-isa.c
index a39fcdd1fc..b84d4d458d 100644
--- a/hw/misc/pvpanic-isa.c
+++ b/hw/misc/pvpanic-isa.c
@@ -21,6 +21,7 @@
#include "hw/misc/pvpanic.h"
#include "qom/object.h"
#include "hw/isa/isa.h"
+#include "standard-headers/linux/pvpanic.h"
OBJECT_DECLARE_SIMPLE_TYPE(PVPanicISAState, PVPANIC_ISA_DEVICE)
@@ -64,7 +65,8 @@ static void pvpanic_isa_realizefn(DeviceState *dev, Error **errp)
static Property pvpanic_isa_properties[] = {
DEFINE_PROP_UINT16(PVPANIC_IOPORT_PROP, PVPanicISAState, ioport, 0x505),
- DEFINE_PROP_UINT8("events", PVPanicISAState, pvpanic.events, PVPANIC_PANICKED | PVPANIC_CRASHLOADED),
+ DEFINE_PROP_UINT8("events", PVPanicISAState, pvpanic.events,
+ PVPANIC_PANICKED | PVPANIC_CRASH_LOADED),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/misc/pvpanic-pci.c b/hw/misc/pvpanic-pci.c
index 62e1be68c1..99cf7e2041 100644
--- a/hw/misc/pvpanic-pci.c
+++ b/hw/misc/pvpanic-pci.c
@@ -21,6 +21,7 @@
#include "hw/misc/pvpanic.h"
#include "qom/object.h"
#include "hw/pci/pci.h"
+#include "standard-headers/linux/pvpanic.h"
OBJECT_DECLARE_SIMPLE_TYPE(PVPanicPCIState, PVPANIC_PCI_DEVICE)
@@ -53,7 +54,8 @@ static void pvpanic_pci_realizefn(PCIDevice *dev, Error **errp)
}
static Property pvpanic_pci_properties[] = {
- DEFINE_PROP_UINT8("events", PVPanicPCIState, pvpanic.events, PVPANIC_PANICKED | PVPANIC_CRASHLOADED),
+ DEFINE_PROP_UINT8("events", PVPanicPCIState, pvpanic.events,
+ PVPANIC_PANICKED | PVPANIC_CRASH_LOADED),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c
index e2cb4a5d28..1540e9091a 100644
--- a/hw/misc/pvpanic.c
+++ b/hw/misc/pvpanic.c
@@ -21,12 +21,13 @@
#include "hw/qdev-properties.h"
#include "hw/misc/pvpanic.h"
#include "qom/object.h"
+#include "standard-headers/linux/pvpanic.h"
static void handle_event(int event)
{
static bool logged;
- if (event & ~(PVPANIC_PANICKED | PVPANIC_CRASHLOADED) && !logged) {
+ if (event & ~(PVPANIC_PANICKED | PVPANIC_CRASH_LOADED) && !logged) {
qemu_log_mask(LOG_GUEST_ERROR, "pvpanic: unknown event %#x.\n", event);
logged = true;
}
@@ -36,7 +37,7 @@ static void handle_event(int event)
return;
}
- if (event & PVPANIC_CRASHLOADED) {
+ if (event & PVPANIC_CRASH_LOADED) {
qemu_system_guest_crashloaded(NULL);
return;
}
diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c
index dd6f6e34d3..6ced6775ff 100644
--- a/hw/net/ne2000-isa.c
+++ b/hw/net/ne2000-isa.c
@@ -68,7 +68,7 @@ static void isa_ne2000_realizefn(DeviceState *dev, Error **errp)
ne2000_setup_io(s, DEVICE(isadev), 0x20);
isa_register_ioport(isadev, &s->io, isa->iobase);
- isa_init_irq(isadev, &s->irq, isa->isairq);
+ s->irq = isa_get_irq(isadev, isa->isairq);
qemu_macaddr_default_if_unset(&s->c.macaddr);
ne2000_reset(s);
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index cf8ab0f8af..b02a0632df 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -628,17 +628,20 @@ static int virtio_net_max_tx_queue_size(VirtIONet *n)
NetClientState *peer = n->nic_conf.peers.ncs[0];
/*
- * Backends other than vhost-user don't support max queue size.
+ * Backends other than vhost-user or vhost-vdpa don't support max queue
+ * size.
*/
if (!peer) {
return VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE;
}
- if (peer->info->type != NET_CLIENT_DRIVER_VHOST_USER) {
+ switch(peer->info->type) {
+ case NET_CLIENT_DRIVER_VHOST_USER:
+ case NET_CLIENT_DRIVER_VHOST_VDPA:
+ return VIRTQUEUE_MAX_SIZE;
+ default:
return VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE;
- }
-
- return VIRTQUEUE_MAX_SIZE;
+ };
}
static int peer_attach(VirtIONet *n, int index)
diff --git a/hw/pci-bridge/pci_expander_bridge.c b/hw/pci-bridge/pci_expander_bridge.c
index 10e6e7c2ab..de932286b5 100644
--- a/hw/pci-bridge/pci_expander_bridge.c
+++ b/hw/pci-bridge/pci_expander_bridge.c
@@ -193,6 +193,12 @@ static int pxb_map_irq_fn(PCIDevice *pci_dev, int pin)
PCIDevice *pxb = pci_get_bus(pci_dev)->parent_dev;
/*
+ * First carry out normal swizzle to handle
+ * multple root ports on a pxb instance.
+ */
+ pin = pci_swizzle_map_irq_fn(pci_dev, pin);
+
+ /*
* The bios does not index the pxb slot number when
* it computes the IRQ because it resides on bus 0
* and not on the current bus.
diff --git a/hw/pci-bridge/xio3130_downstream.c b/hw/pci-bridge/xio3130_downstream.c
index 04aae72cd6..05e2b06c0c 100644
--- a/hw/pci-bridge/xio3130_downstream.c
+++ b/hw/pci-bridge/xio3130_downstream.c
@@ -28,6 +28,7 @@
#include "migration/vmstate.h"
#include "qapi/error.h"
#include "qemu/module.h"
+#include "hw/pci-bridge/xio3130_downstream.h"
#define PCI_DEVICE_ID_TI_XIO3130D 0x8233 /* downstream port */
#define XIO3130_REVISION 0x1
@@ -84,7 +85,7 @@ static void xio3130_downstream_realize(PCIDevice *d, Error **errp)
XIO3130_SSVID_SVID, XIO3130_SSVID_SSID,
errp);
if (rc < 0) {
- goto err_bridge;
+ goto err_msi;
}
rc = pcie_cap_init(d, XIO3130_EXP_OFFSET, PCI_EXP_TYPE_DOWNSTREAM,
@@ -173,7 +174,7 @@ static void xio3130_downstream_class_init(ObjectClass *klass, void *data)
}
static const TypeInfo xio3130_downstream_info = {
- .name = "xio3130-downstream",
+ .name = TYPE_XIO3130_DOWNSTREAM,
.parent = TYPE_PCIE_SLOT,
.class_init = xio3130_downstream_class_init,
.interfaces = (InterfaceInfo[]) {
diff --git a/hw/pci-bridge/xio3130_upstream.c b/hw/pci-bridge/xio3130_upstream.c
index 5cd3af4fbc..5ff46ef050 100644
--- a/hw/pci-bridge/xio3130_upstream.c
+++ b/hw/pci-bridge/xio3130_upstream.c
@@ -75,7 +75,7 @@ static void xio3130_upstream_realize(PCIDevice *d, Error **errp)
XIO3130_SSVID_SVID, XIO3130_SSVID_SSID,
errp);
if (rc < 0) {
- goto err_bridge;
+ goto err_msi;
}
rc = pcie_cap_init(d, XIO3130_EXP_OFFSET, PCI_EXP_TYPE_UPSTREAM,
diff --git a/hw/pci/meson.build b/hw/pci/meson.build
index 5c4bbac817..bcc9c75919 100644
--- a/hw/pci/meson.build
+++ b/hw/pci/meson.build
@@ -5,6 +5,7 @@ pci_ss.add(files(
'pci.c',
'pci_bridge.c',
'pci_host.c',
+ 'pcie_sriov.c',
'shpc.c',
'slotid_cap.c'
))
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 5d30f9ca60..5cb1232e27 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -239,6 +239,9 @@ int pci_bar(PCIDevice *d, int reg)
{
uint8_t type;
+ /* PCIe virtual functions do not have their own BARs */
+ assert(!pci_is_vf(d));
+
if (reg != PCI_ROM_SLOT)
return PCI_BASE_ADDRESS_0 + reg * 4;
@@ -304,10 +307,30 @@ void pci_device_deassert_intx(PCIDevice *dev)
}
}
-static void pci_do_device_reset(PCIDevice *dev)
+static void pci_reset_regions(PCIDevice *dev)
{
int r;
+ if (pci_is_vf(dev)) {
+ return;
+ }
+
+ for (r = 0; r < PCI_NUM_REGIONS; ++r) {
+ PCIIORegion *region = &dev->io_regions[r];
+ if (!region->size) {
+ continue;
+ }
+ if (!(region->type & PCI_BASE_ADDRESS_SPACE_IO) &&
+ region->type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+ pci_set_quad(dev->config + pci_bar(dev, r), region->type);
+ } else {
+ pci_set_long(dev->config + pci_bar(dev, r), region->type);
+ }
+ }
+}
+
+static void pci_do_device_reset(PCIDevice *dev)
+{
pci_device_deassert_intx(dev);
assert(dev->irq_state == 0);
@@ -323,19 +346,7 @@ static void pci_do_device_reset(PCIDevice *dev)
pci_get_word(dev->wmask + PCI_INTERRUPT_LINE) |
pci_get_word(dev->w1cmask + PCI_INTERRUPT_LINE));
dev->config[PCI_CACHE_LINE_SIZE] = 0x0;
- for (r = 0; r < PCI_NUM_REGIONS; ++r) {
- PCIIORegion *region = &dev->io_regions[r];
- if (!region->size) {
- continue;
- }
-
- if (!(region->type & PCI_BASE_ADDRESS_SPACE_IO) &&
- region->type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
- pci_set_quad(dev->config + pci_bar(dev, r), region->type);
- } else {
- pci_set_long(dev->config + pci_bar(dev, r), region->type);
- }
- }
+ pci_reset_regions(dev);
pci_update_mappings(dev);
msi_reset(dev);
@@ -885,6 +896,16 @@ static void pci_init_multifunction(PCIBus *bus, PCIDevice *dev, Error **errp)
}
/*
+ * With SR/IOV and ARI, a device at function 0 need not be a multifunction
+ * device, as it may just be a VF that ended up with function 0 in
+ * the legacy PCI interpretation. Avoid failing in such cases:
+ */
+ if (pci_is_vf(dev) &&
+ dev->exp.sriov_vf.pf->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) {
+ return;
+ }
+
+ /*
* multifunction bit is interpreted in two ways as follows.
* - all functions must set the bit to 1.
* Example: Intel X53
@@ -1078,11 +1099,12 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev,
return NULL;
} else if (!pci_bus_devfn_available(bus, devfn)) {
error_setg(errp, "PCI: slot %d function %d not available for %s,"
- " in use by %s",
+ " in use by %s,id=%s",
PCI_SLOT(devfn), PCI_FUNC(devfn), name,
- bus->devices[devfn]->name);
+ bus->devices[devfn]->name, bus->devices[devfn]->qdev.id);
return NULL;
} else if (dev->hotplugged &&
+ !pci_is_vf(pci_dev) &&
pci_get_function_0(pci_dev)) {
error_setg(errp, "PCI: slot %d function 0 already occupied by %s,"
" new func %s cannot be exposed to guest.",
@@ -1191,6 +1213,7 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
pcibus_t size = memory_region_size(memory);
uint8_t hdr_type;
+ assert(!pci_is_vf(pci_dev)); /* VFs must use pcie_sriov_vf_register_bar */
assert(region_num >= 0);
assert(region_num < PCI_NUM_REGIONS);
assert(is_power_of_2(size));
@@ -1294,11 +1317,45 @@ pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num)
return pci_dev->io_regions[region_num].addr;
}
-static pcibus_t pci_bar_address(PCIDevice *d,
- int reg, uint8_t type, pcibus_t size)
+static pcibus_t pci_config_get_bar_addr(PCIDevice *d, int reg,
+ uint8_t type, pcibus_t size)
+{
+ pcibus_t new_addr;
+ if (!pci_is_vf(d)) {
+ int bar = pci_bar(d, reg);
+ if (type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+ new_addr = pci_get_quad(d->config + bar);
+ } else {
+ new_addr = pci_get_long(d->config + bar);
+ }
+ } else {
+ PCIDevice *pf = d->exp.sriov_vf.pf;
+ uint16_t sriov_cap = pf->exp.sriov_cap;
+ int bar = sriov_cap + PCI_SRIOV_BAR + reg * 4;
+ uint16_t vf_offset =
+ pci_get_word(pf->config + sriov_cap + PCI_SRIOV_VF_OFFSET);
+ uint16_t vf_stride =
+ pci_get_word(pf->config + sriov_cap + PCI_SRIOV_VF_STRIDE);
+ uint32_t vf_num = (d->devfn - (pf->devfn + vf_offset)) / vf_stride;
+
+ if (type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+ new_addr = pci_get_quad(pf->config + bar);
+ } else {
+ new_addr = pci_get_long(pf->config + bar);
+ }
+ new_addr += vf_num * size;
+ }
+ /* The ROM slot has a specific enable bit, keep it intact */
+ if (reg != PCI_ROM_SLOT) {
+ new_addr &= ~(size - 1);
+ }
+ return new_addr;
+}
+
+pcibus_t pci_bar_address(PCIDevice *d,
+ int reg, uint8_t type, pcibus_t size)
{
pcibus_t new_addr, last_addr;
- int bar = pci_bar(d, reg);
uint16_t cmd = pci_get_word(d->config + PCI_COMMAND);
Object *machine = qdev_get_machine();
ObjectClass *oc = object_get_class(machine);
@@ -1309,7 +1366,7 @@ static pcibus_t pci_bar_address(PCIDevice *d,
if (!(cmd & PCI_COMMAND_IO)) {
return PCI_BAR_UNMAPPED;
}
- new_addr = pci_get_long(d->config + bar) & ~(size - 1);
+ new_addr = pci_config_get_bar_addr(d, reg, type, size);
last_addr = new_addr + size - 1;
/* Check if 32 bit BAR wraps around explicitly.
* TODO: make priorities correct and remove this work around.
@@ -1324,11 +1381,7 @@ static pcibus_t pci_bar_address(PCIDevice *d,
if (!(cmd & PCI_COMMAND_MEMORY)) {
return PCI_BAR_UNMAPPED;
}
- if (type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
- new_addr = pci_get_quad(d->config + bar);
- } else {
- new_addr = pci_get_long(d->config + bar);
- }
+ new_addr = pci_config_get_bar_addr(d, reg, type, size);
/* the ROM slot has a specific enable bit */
if (reg == PCI_ROM_SLOT && !(new_addr & PCI_ROM_ADDRESS_ENABLE)) {
return PCI_BAR_UNMAPPED;
@@ -1473,6 +1526,7 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val_in, int
msi_write_config(d, addr, val_in, l);
msix_write_config(d, addr, val_in, l);
+ pcie_sriov_config_write(d, addr, val_in, l);
}
/***********************************************************/
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index d7d73a31e4..67a5d67372 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -366,6 +366,17 @@ static void hotplug_event_clear(PCIDevice *dev)
}
}
+void pcie_cap_slot_enable_power(PCIDevice *dev)
+{
+ uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
+ uint32_t sltcap = pci_get_long(exp_cap + PCI_EXP_SLTCAP);
+
+ if (sltcap & PCI_EXP_SLTCAP_PCP) {
+ pci_set_word_by_mask(exp_cap + PCI_EXP_SLTCTL,
+ PCI_EXP_SLTCTL_PCC, PCI_EXP_SLTCTL_PWR_ON);
+ }
+}
+
static void pcie_set_power_device(PCIBus *bus, PCIDevice *dev, void *opaque)
{
bool *power = opaque;
@@ -446,6 +457,11 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
PCIDevice *pci_dev = PCI_DEVICE(dev);
uint32_t lnkcap = pci_get_long(exp_cap + PCI_EXP_LNKCAP);
+ if (pci_is_vf(pci_dev)) {
+ /* Virtual function cannot be physically disconnected */
+ return;
+ }
+
/* Don't send event when device is enabled during qemu machine creation:
* it is present on boot, no hotplug event is necessary. We do send an
* event when the device is disabled later. */
diff --git a/hw/pci/pcie_sriov.c b/hw/pci/pcie_sriov.c
new file mode 100644
index 0000000000..87abad6ac8
--- /dev/null
+++ b/hw/pci/pcie_sriov.c
@@ -0,0 +1,302 @@
+/*
+ * pcie_sriov.c:
+ *
+ * Implementation of SR/IOV emulation support.
+ *
+ * Copyright (c) 2015-2017 Knut Omang <knut.omang@oracle.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/pci/pci.h"
+#include "hw/pci/pcie.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/qdev-properties.h"
+#include "qemu/error-report.h"
+#include "qemu/range.h"
+#include "qapi/error.h"
+#include "trace.h"
+
+static PCIDevice *register_vf(PCIDevice *pf, int devfn,
+ const char *name, uint16_t vf_num);
+static void unregister_vfs(PCIDevice *dev);
+
+void pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset,
+ const char *vfname, uint16_t vf_dev_id,
+ uint16_t init_vfs, uint16_t total_vfs,
+ uint16_t vf_offset, uint16_t vf_stride)
+{
+ uint8_t *cfg = dev->config + offset;
+ uint8_t *wmask;
+
+ pcie_add_capability(dev, PCI_EXT_CAP_ID_SRIOV, 1,
+ offset, PCI_EXT_CAP_SRIOV_SIZEOF);
+ dev->exp.sriov_cap = offset;
+ dev->exp.sriov_pf.num_vfs = 0;
+ dev->exp.sriov_pf.vfname = g_strdup(vfname);
+ dev->exp.sriov_pf.vf = NULL;
+
+ pci_set_word(cfg + PCI_SRIOV_VF_OFFSET, vf_offset);
+ pci_set_word(cfg + PCI_SRIOV_VF_STRIDE, vf_stride);
+
+ /*
+ * Mandatory page sizes to support.
+ * Device implementations can call pcie_sriov_pf_add_sup_pgsize()
+ * to set more bits:
+ */
+ pci_set_word(cfg + PCI_SRIOV_SUP_PGSIZE, SRIOV_SUP_PGSIZE_MINREQ);
+
+ /*
+ * Default is to use 4K pages, software can modify it
+ * to any of the supported bits
+ */
+ pci_set_word(cfg + PCI_SRIOV_SYS_PGSIZE, 0x1);
+
+ /* Set up device ID and initial/total number of VFs available */
+ pci_set_word(cfg + PCI_SRIOV_VF_DID, vf_dev_id);
+ pci_set_word(cfg + PCI_SRIOV_INITIAL_VF, init_vfs);
+ pci_set_word(cfg + PCI_SRIOV_TOTAL_VF, total_vfs);
+ pci_set_word(cfg + PCI_SRIOV_NUM_VF, 0);
+
+ /* Write enable control bits */
+ wmask = dev->wmask + offset;
+ pci_set_word(wmask + PCI_SRIOV_CTRL,
+ PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE | PCI_SRIOV_CTRL_ARI);
+ pci_set_word(wmask + PCI_SRIOV_NUM_VF, 0xffff);
+ pci_set_word(wmask + PCI_SRIOV_SYS_PGSIZE, 0x553);
+
+ qdev_prop_set_bit(&dev->qdev, "multifunction", true);
+}
+
+void pcie_sriov_pf_exit(PCIDevice *dev)
+{
+ unregister_vfs(dev);
+ g_free((char *)dev->exp.sriov_pf.vfname);
+ dev->exp.sriov_pf.vfname = NULL;
+}
+
+void pcie_sriov_pf_init_vf_bar(PCIDevice *dev, int region_num,
+ uint8_t type, dma_addr_t size)
+{
+ uint32_t addr;
+ uint64_t wmask;
+ uint16_t sriov_cap = dev->exp.sriov_cap;
+
+ assert(sriov_cap > 0);
+ assert(region_num >= 0);
+ assert(region_num < PCI_NUM_REGIONS);
+ assert(region_num != PCI_ROM_SLOT);
+
+ wmask = ~(size - 1);
+ addr = sriov_cap + PCI_SRIOV_BAR + region_num * 4;
+
+ pci_set_long(dev->config + addr, type);
+ if (!(type & PCI_BASE_ADDRESS_SPACE_IO) &&
+ type & PCI_BASE_ADDRESS_MEM_TYPE_64) {
+ pci_set_quad(dev->wmask + addr, wmask);
+ pci_set_quad(dev->cmask + addr, ~0ULL);
+ } else {
+ pci_set_long(dev->wmask + addr, wmask & 0xffffffff);
+ pci_set_long(dev->cmask + addr, 0xffffffff);
+ }
+ dev->exp.sriov_pf.vf_bar_type[region_num] = type;
+}
+
+void pcie_sriov_vf_register_bar(PCIDevice *dev, int region_num,
+ MemoryRegion *memory)
+{
+ PCIIORegion *r;
+ PCIBus *bus = pci_get_bus(dev);
+ uint8_t type;
+ pcibus_t size = memory_region_size(memory);
+
+ assert(pci_is_vf(dev)); /* PFs must use pci_register_bar */
+ assert(region_num >= 0);
+ assert(region_num < PCI_NUM_REGIONS);
+ type = dev->exp.sriov_vf.pf->exp.sriov_pf.vf_bar_type[region_num];
+
+ if (!is_power_of_2(size)) {
+ error_report("%s: PCI region size must be a power"
+ " of two - type=0x%x, size=0x%"FMT_PCIBUS,
+ __func__, type, size);
+ exit(1);
+ }
+
+ r = &dev->io_regions[region_num];
+ r->memory = memory;
+ r->address_space =
+ type & PCI_BASE_ADDRESS_SPACE_IO
+ ? bus->address_space_io
+ : bus->address_space_mem;
+ r->size = size;
+ r->type = type;
+
+ r->addr = pci_bar_address(dev, region_num, r->type, r->size);
+ if (r->addr != PCI_BAR_UNMAPPED) {
+ memory_region_add_subregion_overlap(r->address_space,
+ r->addr, r->memory, 1);
+ }
+}
+
+static PCIDevice *register_vf(PCIDevice *pf, int devfn, const char *name,
+ uint16_t vf_num)
+{
+ PCIDevice *dev = pci_new(devfn, name);
+ dev->exp.sriov_vf.pf = pf;
+ dev->exp.sriov_vf.vf_number = vf_num;
+ PCIBus *bus = pci_get_bus(pf);
+ Error *local_err = NULL;
+
+ qdev_realize(&dev->qdev, &bus->qbus, &local_err);
+ if (local_err) {
+ error_report_err(local_err);
+ return NULL;
+ }
+
+ /* set vid/did according to sr/iov spec - they are not used */
+ pci_config_set_vendor_id(dev->config, 0xffff);
+ pci_config_set_device_id(dev->config, 0xffff);
+
+ return dev;
+}
+
+static void register_vfs(PCIDevice *dev)
+{
+ uint16_t num_vfs;
+ uint16_t i;
+ uint16_t sriov_cap = dev->exp.sriov_cap;
+ uint16_t vf_offset =
+ pci_get_word(dev->config + sriov_cap + PCI_SRIOV_VF_OFFSET);
+ uint16_t vf_stride =
+ pci_get_word(dev->config + sriov_cap + PCI_SRIOV_VF_STRIDE);
+ int32_t devfn = dev->devfn + vf_offset;
+
+ assert(sriov_cap > 0);
+ num_vfs = pci_get_word(dev->config + sriov_cap + PCI_SRIOV_NUM_VF);
+
+ dev->exp.sriov_pf.vf = g_malloc(sizeof(PCIDevice *) * num_vfs);
+ assert(dev->exp.sriov_pf.vf);
+
+ trace_sriov_register_vfs(dev->name, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), num_vfs);
+ for (i = 0; i < num_vfs; i++) {
+ dev->exp.sriov_pf.vf[i] = register_vf(dev, devfn,
+ dev->exp.sriov_pf.vfname, i);
+ if (!dev->exp.sriov_pf.vf[i]) {
+ num_vfs = i;
+ break;
+ }
+ devfn += vf_stride;
+ }
+ dev->exp.sriov_pf.num_vfs = num_vfs;
+}
+
+static void unregister_vfs(PCIDevice *dev)
+{
+ Error *local_err = NULL;
+ uint16_t num_vfs = dev->exp.sriov_pf.num_vfs;
+ uint16_t i;
+
+ trace_sriov_unregister_vfs(dev->name, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), num_vfs);
+ for (i = 0; i < num_vfs; i++) {
+ PCIDevice *vf = dev->exp.sriov_pf.vf[i];
+ object_property_set_bool(OBJECT(vf), "realized", false, &local_err);
+ if (local_err) {
+ fprintf(stderr, "Failed to unplug: %s\n",
+ error_get_pretty(local_err));
+ error_free(local_err);
+ }
+ object_unparent(OBJECT(vf));
+ }
+ g_free(dev->exp.sriov_pf.vf);
+ dev->exp.sriov_pf.vf = NULL;
+ dev->exp.sriov_pf.num_vfs = 0;
+ pci_set_word(dev->config + dev->exp.sriov_cap + PCI_SRIOV_NUM_VF, 0);
+}
+
+void pcie_sriov_config_write(PCIDevice *dev, uint32_t address,
+ uint32_t val, int len)
+{
+ uint32_t off;
+ uint16_t sriov_cap = dev->exp.sriov_cap;
+
+ if (!sriov_cap || address < sriov_cap) {
+ return;
+ }
+ off = address - sriov_cap;
+ if (off >= PCI_EXT_CAP_SRIOV_SIZEOF) {
+ return;
+ }
+
+ trace_sriov_config_write(dev->name, PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn), off, val, len);
+
+ if (range_covers_byte(off, len, PCI_SRIOV_CTRL)) {
+ if (dev->exp.sriov_pf.num_vfs) {
+ if (!(val & PCI_SRIOV_CTRL_VFE)) {
+ unregister_vfs(dev);
+ }
+ } else {
+ if (val & PCI_SRIOV_CTRL_VFE) {
+ register_vfs(dev);
+ }
+ }
+ }
+}
+
+
+/* Reset SR/IOV VF Enable bit to trigger an unregister of all VFs */
+void pcie_sriov_pf_disable_vfs(PCIDevice *dev)
+{
+ uint16_t sriov_cap = dev->exp.sriov_cap;
+ if (sriov_cap) {
+ uint32_t val = pci_get_byte(dev->config + sriov_cap + PCI_SRIOV_CTRL);
+ if (val & PCI_SRIOV_CTRL_VFE) {
+ val &= ~PCI_SRIOV_CTRL_VFE;
+ pcie_sriov_config_write(dev, sriov_cap + PCI_SRIOV_CTRL, val, 1);
+ }
+ }
+}
+
+/* Add optional supported page sizes to the mask of supported page sizes */
+void pcie_sriov_pf_add_sup_pgsize(PCIDevice *dev, uint16_t opt_sup_pgsize)
+{
+ uint8_t *cfg = dev->config + dev->exp.sriov_cap;
+ uint8_t *wmask = dev->wmask + dev->exp.sriov_cap;
+
+ uint16_t sup_pgsize = pci_get_word(cfg + PCI_SRIOV_SUP_PGSIZE);
+
+ sup_pgsize |= opt_sup_pgsize;
+
+ /*
+ * Make sure the new bits are set, and that system page size
+ * also can be set to any of the new values according to spec:
+ */
+ pci_set_word(cfg + PCI_SRIOV_SUP_PGSIZE, sup_pgsize);
+ pci_set_word(wmask + PCI_SRIOV_SYS_PGSIZE, sup_pgsize);
+}
+
+
+uint16_t pcie_sriov_vf_number(PCIDevice *dev)
+{
+ assert(pci_is_vf(dev));
+ return dev->exp.sriov_vf.vf_number;
+}
+
+PCIDevice *pcie_sriov_get_pf(PCIDevice *dev)
+{
+ return dev->exp.sriov_vf.pf;
+}
+
+PCIDevice *pcie_sriov_get_vf_at_index(PCIDevice *dev, int n)
+{
+ assert(!pci_is_vf(dev));
+ if (n < dev->exp.sriov_pf.num_vfs) {
+ return dev->exp.sriov_pf.vf[n];
+ }
+ return NULL;
+}
diff --git a/hw/pci/trace-events b/hw/pci/trace-events
index 7570752c40..aaf46bc92d 100644
--- a/hw/pci/trace-events
+++ b/hw/pci/trace-events
@@ -10,3 +10,8 @@ pci_cfg_write(const char *dev, uint32_t bus, uint32_t slot, uint32_t func, unsig
# msix.c
msix_write_config(char *name, bool enabled, bool masked) "dev %s enabled %d masked %d"
+
+# hw/pci/pcie_sriov.c
+sriov_register_vfs(const char *name, int slot, int function, int num_vfs) "%s %02x:%x: creating %d vf devs"
+sriov_unregister_vfs(const char *name, int slot, int function, int num_vfs) "%s %02x:%x: Unregistering %d vf devs"
+sriov_config_write(const char *name, int slot, int fun, uint32_t offset, uint32_t val, uint32_t len) "%s %02x:%x: sriov offset 0x%x val 0x%x len %d"
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 4cc204f90d..953fc65fa8 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -27,6 +27,7 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/datadir.h"
+#include "qemu/memalign.h"
#include "qapi/error.h"
#include "qapi/qapi-events-machine.h"
#include "qapi/qapi-events-qdev.h"
diff --git a/hw/ppc/spapr_softmmu.c b/hw/ppc/spapr_softmmu.c
index 4ee03c83e4..5170a33369 100644
--- a/hw/ppc/spapr_softmmu.c
+++ b/hw/ppc/spapr_softmmu.c
@@ -1,5 +1,6 @@
#include "qemu/osdep.h"
#include "qemu/cutils.h"
+#include "qemu/memalign.h"
#include "cpu.h"
#include "helper_regs.h"
#include "hw/ppc/spapr.h"
diff --git a/hw/rtc/m48t59-isa.c b/hw/rtc/m48t59-isa.c
index dc21fb10a5..e61f7ec370 100644
--- a/hw/rtc/m48t59-isa.c
+++ b/hw/rtc/m48t59-isa.c
@@ -42,6 +42,7 @@ struct M48txxISAState {
ISADevice parent_obj;
M48t59State state;
uint32_t io_base;
+ uint8_t isairq;
MemoryRegion io;
};
@@ -79,6 +80,7 @@ static void m48txx_isa_toggle_lock(Nvram *obj, int lock)
static Property m48t59_isa_properties[] = {
DEFINE_PROP_INT32("base-year", M48txxISAState, state.base_year, 0),
DEFINE_PROP_UINT32("iobase", M48txxISAState, io_base, 0x74),
+ DEFINE_PROP_UINT8("irq", M48txxISAState, isairq, 8),
DEFINE_PROP_END_OF_LIST(),
};
@@ -97,9 +99,14 @@ static void m48t59_isa_realize(DeviceState *dev, Error **errp)
M48txxISAState *d = M48TXX_ISA(dev);
M48t59State *s = &d->state;
+ if (d->isairq >= ISA_NUM_IRQS) {
+ error_setg(errp, "Maximum value for \"irq\" is: %u", ISA_NUM_IRQS - 1);
+ return;
+ }
+
s->model = u->info.model;
s->size = u->info.size;
- isa_init_irq(isadev, &s->IRQ, 8);
+ s->IRQ = isa_get_irq(isadev, d->isairq);
m48t59_realize_common(s, errp);
memory_region_init_io(&d->io, OBJECT(dev), &m48t59_io_ops, s, "m48t59", 4);
if (d->io_base != 0) {
diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c
index ac9a60c90e..f235c2ddbe 100644
--- a/hw/rtc/mc146818rtc.c
+++ b/hw/rtc/mc146818rtc.c
@@ -912,6 +912,11 @@ static void rtc_realizefn(DeviceState *dev, Error **errp)
s->base_year = 0;
}
+ if (s->isairq >= ISA_NUM_IRQS) {
+ error_setg(errp, "Maximum value for \"irq\" is: %u", ISA_NUM_IRQS - 1);
+ return;
+ }
+
rtc_set_date_from_host(isadev);
switch (s->lost_tick_policy) {
@@ -957,15 +962,17 @@ ISADevice *mc146818_rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq)
{
DeviceState *dev;
ISADevice *isadev;
+ RTCState *s;
isadev = isa_new(TYPE_MC146818_RTC);
dev = DEVICE(isadev);
+ s = MC146818_RTC(isadev);
qdev_prop_set_int32(dev, "base_year", base_year);
isa_realize_and_unref(isadev, bus, &error_fatal);
if (intercept_irq) {
qdev_connect_gpio_out(dev, 0, intercept_irq);
} else {
- isa_connect_gpio_out(isadev, 0, RTC_ISA_IRQ);
+ isa_connect_gpio_out(isadev, 0, s->isairq);
}
object_property_add_alias(qdev_get_machine(), "rtc-time", OBJECT(isadev),
@@ -976,6 +983,7 @@ ISADevice *mc146818_rtc_init(ISABus *bus, int base_year, qemu_irq intercept_irq)
static Property mc146818rtc_properties[] = {
DEFINE_PROP_INT32("base_year", RTCState, base_year, 1980),
+ DEFINE_PROP_UINT8("irq", RTCState, isairq, RTC_ISA_IRQ),
DEFINE_PROP_LOSTTICKPOLICY("lost_tick_policy", RTCState,
lost_tick_policy, LOST_TICK_POLICY_DISCARD),
DEFINE_PROP_END_OF_LIST(),
@@ -1011,6 +1019,7 @@ static void rtc_reset_hold(Object *obj)
static void rtc_build_aml(ISADevice *isadev, Aml *scope)
{
+ RTCState *s = MC146818_RTC(isadev);
Aml *dev;
Aml *crs;
@@ -1021,7 +1030,7 @@ static void rtc_build_aml(ISADevice *isadev, Aml *scope)
crs = aml_resource_template();
aml_append(crs, aml_io(AML_DECODE16, RTC_ISA_BASE, RTC_ISA_BASE,
0x01, 0x08));
- aml_append(crs, aml_irq_no_flags(RTC_ISA_IRQ));
+ aml_append(crs, aml_irq_no_flags(s->isairq));
dev = aml_device("RTC");
aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0B00")));
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 3666b8d946..072686ed58 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -26,6 +26,7 @@
#include "qemu/main-loop.h"
#include "qemu/module.h"
#include "qemu/hw-version.h"
+#include "qemu/memalign.h"
#include "hw/scsi/scsi.h"
#include "migration/qemu-file-types.h"
#include "migration/vmstate.h"
diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
index 6013df1698..60349ee402 100644
--- a/hw/smbios/smbios.c
+++ b/hw/smbios/smbios.c
@@ -104,9 +104,11 @@ static struct {
const char *sock_pfx, *manufacturer, *version, *serial, *asset, *part;
uint64_t max_speed;
uint64_t current_speed;
+ uint64_t processor_id;
} type4 = {
.max_speed = DEFAULT_CPU_SPEED,
- .current_speed = DEFAULT_CPU_SPEED
+ .current_speed = DEFAULT_CPU_SPEED,
+ .processor_id = 0,
};
static struct {
@@ -327,6 +329,10 @@ static const QemuOptDesc qemu_smbios_type4_opts[] = {
.name = "part",
.type = QEMU_OPT_STRING,
.help = "part number",
+ }, {
+ .name = "processor-id",
+ .type = QEMU_OPT_NUMBER,
+ .help = "processor id",
},
{ /* end of list */ }
};
@@ -549,9 +555,23 @@ bool smbios_skip_table(uint8_t type, bool required_table)
return true;
}
+#define T0_BASE 0x000
+#define T1_BASE 0x100
+#define T2_BASE 0x200
+#define T3_BASE 0x300
+#define T4_BASE 0x400
+#define T11_BASE 0xe00
+
+#define T16_BASE 0x1000
+#define T17_BASE 0x1100
+#define T19_BASE 0x1300
+#define T32_BASE 0x2000
+#define T41_BASE 0x2900
+#define T127_BASE 0x7F00
+
static void smbios_build_type_0_table(void)
{
- SMBIOS_BUILD_TABLE_PRE(0, 0x000, false); /* optional, leave up to BIOS */
+ SMBIOS_BUILD_TABLE_PRE(0, T0_BASE, false); /* optional, leave up to BIOS */
SMBIOS_TABLE_SET_STR(0, vendor_str, type0.vendor);
SMBIOS_TABLE_SET_STR(0, bios_version_str, type0.version);
@@ -599,7 +619,7 @@ static void smbios_encode_uuid(struct smbios_uuid *uuid, QemuUUID *in)
static void smbios_build_type_1_table(void)
{
- SMBIOS_BUILD_TABLE_PRE(1, 0x100, true); /* required */
+ SMBIOS_BUILD_TABLE_PRE(1, T1_BASE, true); /* required */
SMBIOS_TABLE_SET_STR(1, manufacturer_str, type1.manufacturer);
SMBIOS_TABLE_SET_STR(1, product_name_str, type1.product);
@@ -619,7 +639,7 @@ static void smbios_build_type_1_table(void)
static void smbios_build_type_2_table(void)
{
- SMBIOS_BUILD_TABLE_PRE(2, 0x200, false); /* optional */
+ SMBIOS_BUILD_TABLE_PRE(2, T2_BASE, false); /* optional */
SMBIOS_TABLE_SET_STR(2, manufacturer_str, type2.manufacturer);
SMBIOS_TABLE_SET_STR(2, product_str, type2.product);
@@ -637,7 +657,7 @@ static void smbios_build_type_2_table(void)
static void smbios_build_type_3_table(void)
{
- SMBIOS_BUILD_TABLE_PRE(3, 0x300, true); /* required */
+ SMBIOS_BUILD_TABLE_PRE(3, T3_BASE, true); /* required */
SMBIOS_TABLE_SET_STR(3, manufacturer_str, type3.manufacturer);
t->type = 0x01; /* Other */
@@ -662,15 +682,20 @@ static void smbios_build_type_4_table(MachineState *ms, unsigned instance)
{
char sock_str[128];
- SMBIOS_BUILD_TABLE_PRE(4, 0x400 + instance, true); /* required */
+ SMBIOS_BUILD_TABLE_PRE(4, T4_BASE + instance, true); /* required */
snprintf(sock_str, sizeof(sock_str), "%s%2x", type4.sock_pfx, instance);
SMBIOS_TABLE_SET_STR(4, socket_designation_str, sock_str);
t->processor_type = 0x03; /* CPU */
t->processor_family = 0x01; /* Other */
SMBIOS_TABLE_SET_STR(4, processor_manufacturer_str, type4.manufacturer);
- t->processor_id[0] = cpu_to_le32(smbios_cpuid_version);
- t->processor_id[1] = cpu_to_le32(smbios_cpuid_features);
+ if (type4.processor_id == 0) {
+ t->processor_id[0] = cpu_to_le32(smbios_cpuid_version);
+ t->processor_id[1] = cpu_to_le32(smbios_cpuid_features);
+ } else {
+ t->processor_id[0] = cpu_to_le32((uint32_t)type4.processor_id);
+ t->processor_id[1] = cpu_to_le32(type4.processor_id >> 32);
+ }
SMBIOS_TABLE_SET_STR(4, processor_version_str, type4.version);
t->voltage = 0;
t->external_clock = cpu_to_le16(0); /* Unknown */
@@ -702,7 +727,7 @@ static void smbios_build_type_11_table(void)
return;
}
- SMBIOS_BUILD_TABLE_PRE(11, 0xe00, true); /* required */
+ SMBIOS_BUILD_TABLE_PRE(11, T11_BASE, true); /* required */
snprintf(count_str, sizeof(count_str), "%zu", type11.nvalues);
t->count = type11.nvalues;
@@ -722,7 +747,7 @@ static void smbios_build_type_16_table(unsigned dimm_cnt)
{
uint64_t size_kb;
- SMBIOS_BUILD_TABLE_PRE(16, 0x1000, true); /* required */
+ SMBIOS_BUILD_TABLE_PRE(16, T16_BASE, true); /* required */
t->location = 0x01; /* Other */
t->use = 0x03; /* System memory */
@@ -749,7 +774,7 @@ static void smbios_build_type_17_table(unsigned instance, uint64_t size)
char loc_str[128];
uint64_t size_mb;
- SMBIOS_BUILD_TABLE_PRE(17, 0x1100 + instance, true); /* required */
+ SMBIOS_BUILD_TABLE_PRE(17, T17_BASE + instance, true); /* required */
t->physical_memory_array_handle = cpu_to_le16(0x1000); /* Type 16 above */
t->memory_error_information_handle = cpu_to_le16(0xFFFE); /* Not provided */
@@ -785,12 +810,13 @@ static void smbios_build_type_17_table(unsigned instance, uint64_t size)
SMBIOS_BUILD_TABLE_POST;
}
-static void smbios_build_type_19_table(unsigned instance,
+static void smbios_build_type_19_table(unsigned instance, unsigned offset,
uint64_t start, uint64_t size)
{
uint64_t end, start_kb, end_kb;
- SMBIOS_BUILD_TABLE_PRE(19, 0x1300 + instance, true); /* required */
+ SMBIOS_BUILD_TABLE_PRE(19, T19_BASE + offset + instance,
+ true); /* required */
end = start + size - 1;
assert(end > start);
@@ -814,7 +840,7 @@ static void smbios_build_type_19_table(unsigned instance,
static void smbios_build_type_32_table(void)
{
- SMBIOS_BUILD_TABLE_PRE(32, 0x2000, true); /* required */
+ SMBIOS_BUILD_TABLE_PRE(32, T32_BASE, true); /* required */
memset(t->reserved, 0, 6);
t->boot_status = 0; /* No errors detected */
@@ -828,7 +854,7 @@ static void smbios_build_type_41_table(Error **errp)
struct type41_instance *t41;
QTAILQ_FOREACH(t41, &type41, next) {
- SMBIOS_BUILD_TABLE_PRE(41, 0x2900 + instance, true);
+ SMBIOS_BUILD_TABLE_PRE(41, T41_BASE + instance, true);
SMBIOS_TABLE_SET_STR(41, reference_designation_str, t41->designation);
t->device_type = t41->kind;
@@ -871,7 +897,7 @@ static void smbios_build_type_41_table(Error **errp)
static void smbios_build_type_127_table(void)
{
- SMBIOS_BUILD_TABLE_PRE(127, 0x7F00, true); /* required */
+ SMBIOS_BUILD_TABLE_PRE(127, T127_BASE, true); /* required */
SMBIOS_BUILD_TABLE_POST;
}
@@ -982,7 +1008,7 @@ void smbios_get_tables(MachineState *ms,
uint8_t **anchor, size_t *anchor_len,
Error **errp)
{
- unsigned i, dimm_cnt;
+ unsigned i, dimm_cnt, offset;
if (smbios_legacy) {
*tables = *anchor = NULL;
@@ -1012,6 +1038,16 @@ void smbios_get_tables(MachineState *ms,
dimm_cnt = QEMU_ALIGN_UP(current_machine->ram_size, MAX_DIMM_SZ) / MAX_DIMM_SZ;
+ /*
+ * The offset determines if we need to keep additional space betweeen
+ * table 17 and table 19 header handle numbers so that they do
+ * not overlap. For example, for a VM with larger than 8 TB guest
+ * memory and DIMM like chunks of 16 GiB, the default space between
+ * the two tables (T19_BASE - T17_BASE = 512) is not enough.
+ */
+ offset = (dimm_cnt > (T19_BASE - T17_BASE)) ? \
+ dimm_cnt - (T19_BASE - T17_BASE) : 0;
+
smbios_build_type_16_table(dimm_cnt);
for (i = 0; i < dimm_cnt; i++) {
@@ -1019,10 +1055,16 @@ void smbios_get_tables(MachineState *ms,
}
for (i = 0; i < mem_array_size; i++) {
- smbios_build_type_19_table(i, mem_array[i].address,
+ smbios_build_type_19_table(i, offset, mem_array[i].address,
mem_array[i].length);
}
+ /*
+ * make sure 16 bit handle numbers in the headers of tables 19
+ * and 32 do not overlap.
+ */
+ assert((mem_array_size + offset) < (T32_BASE - T19_BASE));
+
smbios_build_type_32_table();
smbios_build_type_38_table();
smbios_build_type_41_table(errp);
@@ -1292,6 +1334,8 @@ void smbios_entry_add(QemuOpts *opts, Error **errp)
save_opt(&type4.serial, opts, "serial");
save_opt(&type4.asset, opts, "asset");
save_opt(&type4.part, opts, "part");
+ /* If the value is 0, it will take the value from the CPU model. */
+ type4.processor_id = qemu_opt_get_number(opts, "processor-id", 0);
type4.max_speed = qemu_opt_get_number(opts, "max-speed",
DEFAULT_CPU_SPEED);
type4.current_speed = qemu_opt_get_number(opts, "current-speed",
diff --git a/hw/tpm/tpm_ppi.c b/hw/tpm/tpm_ppi.c
index 6dbb9f41e4..c89ac53e65 100644
--- a/hw/tpm/tpm_ppi.c
+++ b/hw/tpm/tpm_ppi.c
@@ -12,7 +12,7 @@
*/
#include "qemu/osdep.h"
-
+#include "qemu/memalign.h"
#include "qapi/error.h"
#include "sysemu/memory_mapping.h"
#include "migration/vmstate.h"
diff --git a/hw/tpm/tpm_tis_isa.c b/hw/tpm/tpm_tis_isa.c
index 10d8a14f19..3477afd735 100644
--- a/hw/tpm/tpm_tis_isa.c
+++ b/hw/tpm/tpm_tis_isa.c
@@ -127,7 +127,7 @@ static void tpm_tis_isa_realizefn(DeviceState *dev, Error **errp)
return;
}
- isa_init_irq(ISA_DEVICE(dev), &s->irq, s->irq_num);
+ s->irq = isa_get_irq(ISA_DEVICE(dev), s->irq_num);
memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
TPM_TIS_ADDR_BASE, &s->mmio);
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index f7ad6be5fb..a5102eac9e 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -89,9 +89,11 @@ virtio_mmio_setting_irq(int level) "virtio_mmio setting IRQ %d"
# virtio-iommu.c
virtio_iommu_device_reset(void) "reset!"
+virtio_iommu_system_reset(void) "system reset!"
virtio_iommu_get_features(uint64_t features) "device supports features=0x%"PRIx64
virtio_iommu_device_status(uint8_t status) "driver status = %d"
-virtio_iommu_get_config(uint64_t page_size_mask, uint64_t start, uint64_t end, uint32_t domain_start, uint32_t domain_end, uint32_t probe_size) "page_size_mask=0x%"PRIx64" input range start=0x%"PRIx64" input range end=0x%"PRIx64" domain range start=%d domain range end=%d probe_size=0x%x"
+virtio_iommu_get_config(uint64_t page_size_mask, uint64_t start, uint64_t end, uint32_t domain_start, uint32_t domain_end, uint32_t probe_size, uint8_t bypass) "page_size_mask=0x%"PRIx64" input range start=0x%"PRIx64" input range end=0x%"PRIx64" domain range start=%d domain range end=%d probe_size=0x%x bypass=0x%x"
+virtio_iommu_set_config(uint8_t bypass) "bypass=0x%x"
virtio_iommu_attach(uint32_t domain_id, uint32_t ep_id) "domain=%d endpoint=%d"
virtio_iommu_detach(uint32_t domain_id, uint32_t ep_id) "domain=%d endpoint=%d"
virtio_iommu_map(uint32_t domain_id, uint64_t virt_start, uint64_t virt_end, uint64_t phys_start, uint32_t flags) "domain=%d virt_start=0x%"PRIx64" virt_end=0x%"PRIx64 " phys_start=0x%"PRIx64" flags=%d"
diff --git a/hw/virtio/vhost-user-i2c.c b/hw/virtio/vhost-user-i2c.c
index d172632bb0..42c7f6d9e5 100644
--- a/hw/virtio/vhost-user-i2c.c
+++ b/hw/virtio/vhost-user-i2c.c
@@ -19,6 +19,11 @@
#define VIRTIO_ID_I2C_ADAPTER 34
#endif
+static const int feature_bits[] = {
+ VIRTIO_I2C_F_ZERO_LENGTH_REQUEST,
+ VHOST_INVALID_FEATURE_BIT
+};
+
static void vu_i2c_start(VirtIODevice *vdev)
{
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
@@ -113,8 +118,10 @@ static void vu_i2c_set_status(VirtIODevice *vdev, uint8_t status)
static uint64_t vu_i2c_get_features(VirtIODevice *vdev,
uint64_t requested_features, Error **errp)
{
- /* No feature bits used yet */
- return requested_features;
+ VHostUserI2C *i2c = VHOST_USER_I2C(vdev);
+
+ virtio_add_feature(&requested_features, VIRTIO_I2C_F_ZERO_LENGTH_REQUEST);
+ return vhost_get_features(&i2c->vhost_dev, feature_bits, requested_features);
}
static void vu_i2c_handle_output(VirtIODevice *vdev, VirtQueue *vq)
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 662853513e..6abbc9da32 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -25,6 +25,7 @@
#include "migration/migration.h"
#include "migration/postcopy-ram.h"
#include "trace.h"
+#include "exec/ramblock.h"
#include <sys/ioctl.h>
#include <sys/socket.h>
@@ -1162,37 +1163,32 @@ static int vhost_user_set_vring_num(struct vhost_dev *dev,
return vhost_set_vring(dev, VHOST_USER_SET_VRING_NUM, ring);
}
-static void vhost_user_host_notifier_restore(struct vhost_dev *dev,
- int queue_idx)
+static void vhost_user_host_notifier_free(VhostUserHostNotifier *n)
{
- struct vhost_user *u = dev->opaque;
- VhostUserHostNotifier *n = &u->user->notifier[queue_idx];
- VirtIODevice *vdev = dev->vdev;
-
- if (n->addr && !n->set) {
- virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, true);
- n->set = true;
- }
+ assert(n && n->unmap_addr);
+ munmap(n->unmap_addr, qemu_real_host_page_size);
+ n->unmap_addr = NULL;
}
-static void vhost_user_host_notifier_remove(struct vhost_dev *dev,
- int queue_idx)
+static void vhost_user_host_notifier_remove(VhostUserState *user,
+ VirtIODevice *vdev, int queue_idx)
{
- struct vhost_user *u = dev->opaque;
- VhostUserHostNotifier *n = &u->user->notifier[queue_idx];
- VirtIODevice *vdev = dev->vdev;
+ VhostUserHostNotifier *n = &user->notifier[queue_idx];
- if (n->addr && n->set) {
- virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, false);
- n->set = false;
+ if (n->addr) {
+ if (vdev) {
+ virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, false);
+ }
+ assert(!n->unmap_addr);
+ n->unmap_addr = n->addr;
+ n->addr = NULL;
+ call_rcu(n, vhost_user_host_notifier_free, rcu);
}
}
static int vhost_user_set_vring_base(struct vhost_dev *dev,
struct vhost_vring_state *ring)
{
- vhost_user_host_notifier_restore(dev, ring->index);
-
return vhost_set_vring(dev, VHOST_USER_SET_VRING_BASE, ring);
}
@@ -1235,8 +1231,9 @@ static int vhost_user_get_vring_base(struct vhost_dev *dev,
.payload.state = *ring,
.hdr.size = sizeof(msg.payload.state),
};
+ struct vhost_user *u = dev->opaque;
- vhost_user_host_notifier_remove(dev, ring->index);
+ vhost_user_host_notifier_remove(u->user, dev->vdev, ring->index);
ret = vhost_user_write(dev, &msg, NULL, 0);
if (ret < 0) {
@@ -1522,12 +1519,7 @@ static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev,
n = &user->notifier[queue_idx];
- if (n->addr) {
- virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, false);
- object_unparent(OBJECT(&n->mr));
- munmap(n->addr, page_size);
- n->addr = NULL;
- }
+ vhost_user_host_notifier_remove(user, vdev, queue_idx);
if (area->u64 & VHOST_USER_VRING_NOFD_MASK) {
return 0;
@@ -1546,9 +1538,12 @@ static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev,
name = g_strdup_printf("vhost-user/host-notifier@%p mmaps[%d]",
user, queue_idx);
- if (!n->mr.ram) /* Don't init again after suspend. */
+ if (!n->mr.ram) { /* Don't init again after suspend. */
memory_region_init_ram_device_ptr(&n->mr, OBJECT(vdev), name,
page_size, addr);
+ } else {
+ n->mr.ram_block->host = addr;
+ }
g_free(name);
if (virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, true)) {
@@ -1558,7 +1553,6 @@ static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev,
}
n->addr = addr;
- n->set = true;
return 0;
}
@@ -2522,17 +2516,16 @@ bool vhost_user_init(VhostUserState *user, CharBackend *chr, Error **errp)
void vhost_user_cleanup(VhostUserState *user)
{
int i;
+ VhostUserHostNotifier *n;
if (!user->chr) {
return;
}
memory_region_transaction_begin();
for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
- if (user->notifier[i].addr) {
- object_unparent(OBJECT(&user->notifier[i].mr));
- munmap(user->notifier[i].addr, qemu_real_host_page_size);
- user->notifier[i].addr = NULL;
- }
+ n = &user->notifier[i];
+ vhost_user_host_notifier_remove(user, NULL, i);
+ object_unparent(OBJECT(&n->mr));
}
memory_region_transaction_commit();
user->chr = NULL;
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index 04ea43704f..6c67d5f034 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -395,15 +395,6 @@ static void vhost_vdpa_host_notifier_uninit(struct vhost_dev *dev,
}
}
-static void vhost_vdpa_host_notifiers_uninit(struct vhost_dev *dev, int n)
-{
- int i;
-
- for (i = 0; i < n; i++) {
- vhost_vdpa_host_notifier_uninit(dev, i);
- }
-}
-
static int vhost_vdpa_host_notifier_init(struct vhost_dev *dev, int queue_index)
{
size_t page_size = qemu_real_host_page_size;
@@ -431,6 +422,7 @@ static int vhost_vdpa_host_notifier_init(struct vhost_dev *dev, int queue_index)
g_free(name);
if (virtio_queue_set_host_notifier_mr(vdev, queue_index, &n->mr, true)) {
+ object_unparent(OBJECT(&n->mr));
munmap(addr, page_size);
goto err;
}
@@ -442,6 +434,15 @@ err:
return -1;
}
+static void vhost_vdpa_host_notifiers_uninit(struct vhost_dev *dev, int n)
+{
+ int i;
+
+ for (i = dev->vq_index; i < dev->vq_index + n; i++) {
+ vhost_vdpa_host_notifier_uninit(dev, i);
+ }
+}
+
static void vhost_vdpa_host_notifiers_init(struct vhost_dev *dev)
{
int i;
@@ -455,7 +456,7 @@ static void vhost_vdpa_host_notifiers_init(struct vhost_dev *dev)
return;
err:
- vhost_vdpa_host_notifiers_uninit(dev, i);
+ vhost_vdpa_host_notifiers_uninit(dev, i - dev->vq_index);
return;
}
diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c
index 3f3771274e..ed706681ac 100644
--- a/hw/virtio/vhost-vsock-common.c
+++ b/hw/virtio/vhost-vsock-common.c
@@ -153,19 +153,23 @@ static void vhost_vsock_common_send_transport_reset(VHostVSockCommon *vvc)
if (elem->out_num) {
error_report("invalid vhost-vsock event virtqueue element with "
"out buffers");
- goto out;
+ goto err;
}
if (iov_from_buf(elem->in_sg, elem->in_num, 0,
&event, sizeof(event)) != sizeof(event)) {
error_report("vhost-vsock event virtqueue element is too short");
- goto out;
+ goto err;
}
virtqueue_push(vq, elem, sizeof(event));
virtio_notify(VIRTIO_DEVICE(vvc), vq);
-out:
+ g_free(elem);
+ return;
+
+err:
+ virtqueue_detach_element(vq, elem, 0);
g_free(elem);
}
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 7b03efccec..b643f42ea4 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -1287,7 +1287,7 @@ static int vhost_virtqueue_init(struct vhost_dev *dev,
return r;
}
- file.fd = event_notifier_get_fd(&vq->masked_notifier);
+ file.fd = event_notifier_get_wfd(&vq->masked_notifier);
r = dev->vhost_ops->vhost_set_vring_call(dev, &file);
if (r) {
VHOST_OPS_DEBUG(r, "vhost_set_vring_call failed");
@@ -1542,9 +1542,9 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n,
if (mask) {
assert(vdev->use_guest_notifier_mask);
- file.fd = event_notifier_get_fd(&hdev->vqs[index].masked_notifier);
+ file.fd = event_notifier_get_wfd(&hdev->vqs[index].masked_notifier);
} else {
- file.fd = event_notifier_get_fd(virtio_queue_get_guest_notifier(vvq));
+ file.fd = event_notifier_get_wfd(virtio_queue_get_guest_notifier(vvq));
}
file.index = hdev->vhost_ops->vhost_get_vq_index(hdev, n);
diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
index d23db98c56..0f69d1c742 100644
--- a/hw/virtio/virtio-bus.c
+++ b/hw/virtio/virtio-bus.c
@@ -48,6 +48,7 @@ void virtio_bus_device_plugged(VirtIODevice *vdev, Error **errp)
VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(bus);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
bool has_iommu = virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM);
+ bool vdev_has_iommu;
Error *local_err = NULL;
DPRINTF("%s: plug device.\n", qbus->name);
@@ -69,11 +70,6 @@ void virtio_bus_device_plugged(VirtIODevice *vdev, Error **errp)
return;
}
- if (has_iommu && !virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM)) {
- error_setg(errp, "iommu_platform=true is not supported by the device");
- return;
- }
-
if (klass->device_plugged != NULL) {
klass->device_plugged(qbus->parent, &local_err);
}
@@ -82,9 +78,15 @@ void virtio_bus_device_plugged(VirtIODevice *vdev, Error **errp)
return;
}
+ vdev_has_iommu = virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM);
if (klass->get_dma_as != NULL && has_iommu) {
virtio_add_feature(&vdev->host_features, VIRTIO_F_IOMMU_PLATFORM);
vdev->dma_as = klass->get_dma_as(qbus->parent);
+ if (!vdev_has_iommu && vdev->dma_as != &address_space_memory) {
+ error_setg(errp,
+ "iommu_platform=true is not supported by the device");
+ return;
+ }
} else {
vdev->dma_as = &address_space_memory;
}
diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
index aa9c16a17b..239fe97b12 100644
--- a/hw/virtio/virtio-iommu.c
+++ b/hw/virtio/virtio-iommu.c
@@ -24,6 +24,7 @@
#include "hw/qdev-properties.h"
#include "hw/virtio/virtio.h"
#include "sysemu/kvm.h"
+#include "sysemu/reset.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "trace.h"
@@ -42,6 +43,7 @@
typedef struct VirtIOIOMMUDomain {
uint32_t id;
+ bool bypass;
GTree *mappings;
QLIST_HEAD(, VirtIOIOMMUEndpoint) endpoint_list;
} VirtIOIOMMUDomain;
@@ -257,12 +259,16 @@ static void virtio_iommu_put_endpoint(gpointer data)
}
static VirtIOIOMMUDomain *virtio_iommu_get_domain(VirtIOIOMMU *s,
- uint32_t domain_id)
+ uint32_t domain_id,
+ bool bypass)
{
VirtIOIOMMUDomain *domain;
domain = g_tree_lookup(s->domains, GUINT_TO_POINTER(domain_id));
if (domain) {
+ if (domain->bypass != bypass) {
+ return NULL;
+ }
return domain;
}
domain = g_malloc0(sizeof(*domain));
@@ -270,6 +276,7 @@ static VirtIOIOMMUDomain *virtio_iommu_get_domain(VirtIOIOMMU *s,
domain->mappings = g_tree_new_full((GCompareDataFunc)interval_cmp,
NULL, (GDestroyNotify)g_free,
(GDestroyNotify)g_free);
+ domain->bypass = bypass;
g_tree_insert(s->domains, GUINT_TO_POINTER(domain_id), domain);
QLIST_INIT(&domain->endpoint_list);
trace_virtio_iommu_get_domain(domain_id);
@@ -333,11 +340,16 @@ static int virtio_iommu_attach(VirtIOIOMMU *s,
{
uint32_t domain_id = le32_to_cpu(req->domain);
uint32_t ep_id = le32_to_cpu(req->endpoint);
+ uint32_t flags = le32_to_cpu(req->flags);
VirtIOIOMMUDomain *domain;
VirtIOIOMMUEndpoint *ep;
trace_virtio_iommu_attach(domain_id, ep_id);
+ if (flags & ~VIRTIO_IOMMU_ATTACH_F_BYPASS) {
+ return VIRTIO_IOMMU_S_INVAL;
+ }
+
ep = virtio_iommu_get_endpoint(s, ep_id);
if (!ep) {
return VIRTIO_IOMMU_S_NOENT;
@@ -355,7 +367,12 @@ static int virtio_iommu_attach(VirtIOIOMMU *s,
}
}
- domain = virtio_iommu_get_domain(s, domain_id);
+ domain = virtio_iommu_get_domain(s, domain_id,
+ flags & VIRTIO_IOMMU_ATTACH_F_BYPASS);
+ if (!domain) {
+ /* Incompatible bypass flag */
+ return VIRTIO_IOMMU_S_INVAL;
+ }
QLIST_INSERT_HEAD(&domain->endpoint_list, ep, next);
ep->domain = domain;
@@ -418,6 +435,10 @@ static int virtio_iommu_map(VirtIOIOMMU *s,
return VIRTIO_IOMMU_S_NOENT;
}
+ if (domain->bypass) {
+ return VIRTIO_IOMMU_S_INVAL;
+ }
+
interval = g_malloc0(sizeof(*interval));
interval->low = virt_start;
@@ -463,6 +484,11 @@ static int virtio_iommu_unmap(VirtIOIOMMU *s,
if (!domain) {
return VIRTIO_IOMMU_S_NOENT;
}
+
+ if (domain->bypass) {
+ return VIRTIO_IOMMU_S_INVAL;
+ }
+
interval.low = virt_start;
interval.high = virt_end;
@@ -728,8 +754,7 @@ static IOMMUTLBEntry virtio_iommu_translate(IOMMUMemoryRegion *mr, hwaddr addr,
.perm = IOMMU_NONE,
};
- bypass_allowed = virtio_vdev_has_feature(&s->parent_obj,
- VIRTIO_IOMMU_F_BYPASS);
+ bypass_allowed = s->config.bypass;
sid = virtio_iommu_get_bdf(sdev);
@@ -780,6 +805,9 @@ static IOMMUTLBEntry virtio_iommu_translate(IOMMUMemoryRegion *mr, hwaddr addr,
entry.perm = flag;
}
goto unlock;
+ } else if (ep->domain->bypass) {
+ entry.perm = flag;
+ goto unlock;
}
found = g_tree_lookup_extended(ep->domain->mappings, (gpointer)(&interval),
@@ -831,13 +859,37 @@ static void virtio_iommu_get_config(VirtIODevice *vdev, uint8_t *config_data)
out_config->domain_range.start = cpu_to_le32(dev_config->domain_range.start);
out_config->domain_range.end = cpu_to_le32(dev_config->domain_range.end);
out_config->probe_size = cpu_to_le32(dev_config->probe_size);
+ out_config->bypass = dev_config->bypass;
trace_virtio_iommu_get_config(dev_config->page_size_mask,
dev_config->input_range.start,
dev_config->input_range.end,
dev_config->domain_range.start,
dev_config->domain_range.end,
- dev_config->probe_size);
+ dev_config->probe_size,
+ dev_config->bypass);
+}
+
+static void virtio_iommu_set_config(VirtIODevice *vdev,
+ const uint8_t *config_data)
+{
+ VirtIOIOMMU *dev = VIRTIO_IOMMU(vdev);
+ struct virtio_iommu_config *dev_config = &dev->config;
+ const struct virtio_iommu_config *in_config = (void *)config_data;
+
+ if (in_config->bypass != dev_config->bypass) {
+ if (!virtio_vdev_has_feature(vdev, VIRTIO_IOMMU_F_BYPASS_CONFIG)) {
+ virtio_error(vdev, "cannot set config.bypass");
+ return;
+ } else if (in_config->bypass != 0 && in_config->bypass != 1) {
+ virtio_error(vdev, "invalid config.bypass value '%u'",
+ in_config->bypass);
+ return;
+ }
+ dev_config->bypass = in_config->bypass;
+ }
+
+ trace_virtio_iommu_set_config(in_config->bypass);
}
static uint64_t virtio_iommu_get_features(VirtIODevice *vdev, uint64_t f,
@@ -963,6 +1015,19 @@ static int virtio_iommu_set_page_size_mask(IOMMUMemoryRegion *mr,
return 0;
}
+static void virtio_iommu_system_reset(void *opaque)
+{
+ VirtIOIOMMU *s = opaque;
+
+ trace_virtio_iommu_system_reset();
+
+ /*
+ * config.bypass is sticky across device reset, but should be restored on
+ * system reset
+ */
+ s->config.bypass = s->boot_bypass;
+}
+
static void virtio_iommu_device_realize(DeviceState *dev, Error **errp)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
@@ -988,9 +1053,9 @@ static void virtio_iommu_device_realize(DeviceState *dev, Error **errp)
virtio_add_feature(&s->features, VIRTIO_IOMMU_F_INPUT_RANGE);
virtio_add_feature(&s->features, VIRTIO_IOMMU_F_DOMAIN_RANGE);
virtio_add_feature(&s->features, VIRTIO_IOMMU_F_MAP_UNMAP);
- virtio_add_feature(&s->features, VIRTIO_IOMMU_F_BYPASS);
virtio_add_feature(&s->features, VIRTIO_IOMMU_F_MMIO);
virtio_add_feature(&s->features, VIRTIO_IOMMU_F_PROBE);
+ virtio_add_feature(&s->features, VIRTIO_IOMMU_F_BYPASS_CONFIG);
qemu_mutex_init(&s->mutex);
@@ -1001,6 +1066,8 @@ static void virtio_iommu_device_realize(DeviceState *dev, Error **errp)
} else {
error_setg(errp, "VIRTIO-IOMMU is not attached to any PCI bus!");
}
+
+ qemu_register_reset(virtio_iommu_system_reset, s);
}
static void virtio_iommu_device_unrealize(DeviceState *dev)
@@ -1008,6 +1075,8 @@ static void virtio_iommu_device_unrealize(DeviceState *dev)
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIOIOMMU *s = VIRTIO_IOMMU(dev);
+ qemu_unregister_reset(virtio_iommu_system_reset, s);
+
g_hash_table_destroy(s->as_by_busptr);
if (s->domains) {
g_tree_destroy(s->domains);
@@ -1098,8 +1167,8 @@ static const VMStateDescription vmstate_endpoint = {
static const VMStateDescription vmstate_domain = {
.name = "domain",
- .version_id = 1,
- .minimum_version_id = 1,
+ .version_id = 2,
+ .minimum_version_id = 2,
.pre_load = domain_preload,
.fields = (VMStateField[]) {
VMSTATE_UINT32(id, VirtIOIOMMUDomain),
@@ -1108,6 +1177,7 @@ static const VMStateDescription vmstate_domain = {
VirtIOIOMMUInterval, VirtIOIOMMUMapping),
VMSTATE_QLIST_V(endpoint_list, VirtIOIOMMUDomain, 1,
vmstate_endpoint, VirtIOIOMMUEndpoint, next),
+ VMSTATE_BOOL_V(bypass, VirtIOIOMMUDomain, 2),
VMSTATE_END_OF_LIST()
}
};
@@ -1141,21 +1211,22 @@ static int iommu_post_load(void *opaque, int version_id)
static const VMStateDescription vmstate_virtio_iommu_device = {
.name = "virtio-iommu-device",
- .minimum_version_id = 1,
- .version_id = 1,
+ .minimum_version_id = 2,
+ .version_id = 2,
.post_load = iommu_post_load,
.fields = (VMStateField[]) {
- VMSTATE_GTREE_DIRECT_KEY_V(domains, VirtIOIOMMU, 1,
+ VMSTATE_GTREE_DIRECT_KEY_V(domains, VirtIOIOMMU, 2,
&vmstate_domain, VirtIOIOMMUDomain),
+ VMSTATE_UINT8_V(config.bypass, VirtIOIOMMU, 2),
VMSTATE_END_OF_LIST()
},
};
static const VMStateDescription vmstate_virtio_iommu = {
.name = "virtio-iommu",
- .minimum_version_id = 1,
+ .minimum_version_id = 2,
.priority = MIG_PRI_IOMMU,
- .version_id = 1,
+ .version_id = 2,
.fields = (VMStateField[]) {
VMSTATE_VIRTIO_DEVICE,
VMSTATE_END_OF_LIST()
@@ -1164,6 +1235,7 @@ static const VMStateDescription vmstate_virtio_iommu = {
static Property virtio_iommu_properties[] = {
DEFINE_PROP_LINK("primary-bus", VirtIOIOMMU, primary_bus, "PCI", PCIBus *),
+ DEFINE_PROP_BOOL("boot-bypass", VirtIOIOMMU, boot_bypass, true),
DEFINE_PROP_END_OF_LIST(),
};
@@ -1180,6 +1252,7 @@ static void virtio_iommu_class_init(ObjectClass *klass, void *data)
vdc->unrealize = virtio_iommu_device_unrealize;
vdc->reset = virtio_iommu_device_reset;
vdc->get_config = virtio_iommu_get_config;
+ vdc->set_config = virtio_iommu_set_config;
vdc->get_features = virtio_iommu_get_features;
vdc->set_status = virtio_iommu_set_status;
vdc->vmsd = &vmstate_virtio_iommu_device;
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 84caf5c3d9..c0f0fab28a 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -433,10 +433,6 @@ int cpu_exec(CPUState *cpu);
void tcg_exec_realizefn(CPUState *cpu, Error **errp);
void tcg_exec_unrealizefn(CPUState *cpu);
-/* Returns: 0 on success, -1 on error */
-int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
- void *ptr, target_ulong len, bool is_write);
-
/**
* cpu_set_cpustate_pointers(cpu)
* @cpu: The cpu object
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index de5f444b19..7f7b5943c7 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -7,6 +7,18 @@
#include "exec/hwaddr.h"
#endif
+/**
+ * vaddr:
+ * Type wide enough to contain any #target_ulong virtual address.
+ */
+typedef uint64_t vaddr;
+#define VADDR_PRId PRId64
+#define VADDR_PRIu PRIu64
+#define VADDR_PRIo PRIo64
+#define VADDR_PRIx PRIx64
+#define VADDR_PRIX PRIX64
+#define VADDR_MAX UINT64_MAX
+
/* Using intptr_t ensures that qemu_*_page_mask is sign-extended even
* when intptr_t is 32-bit and we are aligning a long long.
*/
@@ -78,6 +90,28 @@ void qemu_ram_unset_migratable(RAMBlock *rb);
size_t qemu_ram_pagesize(RAMBlock *block);
size_t qemu_ram_pagesize_largest(void);
+/**
+ * cpu_address_space_init:
+ * @cpu: CPU to add this address space to
+ * @asidx: integer index of this address space
+ * @prefix: prefix to be used as name of address space
+ * @mr: the root memory region of address space
+ *
+ * Add the specified address space to the CPU's cpu_ases list.
+ * The address space added with @asidx 0 is the one used for the
+ * convenience pointer cpu->as.
+ * The target-specific code which registers ASes is responsible
+ * for defining what semantics address space 0, 1, 2, etc have.
+ *
+ * Before the first call to this function, the caller must set
+ * cpu->num_ases to the total number of address spaces it needs
+ * to support.
+ *
+ * Note that with KVM only one address space is supported.
+ */
+void cpu_address_space_init(CPUState *cpu, int asidx,
+ const char *prefix, MemoryRegion *mr);
+
void cpu_physical_memory_rw(hwaddr addr, void *buf,
hwaddr len, bool is_write);
static inline void cpu_physical_memory_read(hwaddr addr,
@@ -90,6 +124,7 @@ static inline void cpu_physical_memory_write(hwaddr addr,
{
cpu_physical_memory_rw(addr, (void *)buf, len, true);
}
+void cpu_reloading_memory_map(void);
void *cpu_physical_memory_map(hwaddr addr,
hwaddr *plen,
bool is_write);
@@ -116,6 +151,10 @@ int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length);
#endif
+/* Returns: 0 on success, -1 on error */
+int cpu_memory_rw_debug(CPUState *cpu, vaddr addr,
+ void *ptr, size_t len, bool is_write);
+
/* vl.c */
extern int singlestep;
diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
index da987fe8ad..6adacf8928 100644
--- a/include/exec/cpu_ldst.h
+++ b/include/exec/cpu_ldst.h
@@ -64,6 +64,7 @@
#include "exec/memopidx.h"
#include "qemu/int128.h"
+#include "cpu.h"
#if defined(CONFIG_USER_ONLY)
/* sparc32plus has 64bit long but 32bit space address
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 227e10ba56..d2cb0981f4 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -24,7 +24,6 @@
#ifdef CONFIG_TCG
#include "exec/cpu_ldst.h"
#endif
-#include "sysemu/cpu-timers.h"
/* allow to see translation results - the slowdown should be negligible, so we leave it */
#define DEBUG_DISAS
@@ -81,31 +80,6 @@ static inline bool cpu_loop_exit_requested(CPUState *cpu)
return (int32_t)qatomic_read(&cpu_neg(cpu)->icount_decr.u32) < 0;
}
-#if !defined(CONFIG_USER_ONLY)
-void cpu_reloading_memory_map(void);
-/**
- * cpu_address_space_init:
- * @cpu: CPU to add this address space to
- * @asidx: integer index of this address space
- * @prefix: prefix to be used as name of address space
- * @mr: the root memory region of address space
- *
- * Add the specified address space to the CPU's cpu_ases list.
- * The address space added with @asidx 0 is the one used for the
- * convenience pointer cpu->as.
- * The target-specific code which registers ASes is responsible
- * for defining what semantics address space 0, 1, 2, etc have.
- *
- * Before the first call to this function, the caller must set
- * cpu->num_ases to the total number of address spaces it needs
- * to support.
- *
- * Note that with KVM only one address space is supported.
- */
-void cpu_address_space_init(CPUState *cpu, int asidx,
- const char *prefix, MemoryRegion *mr);
-#endif
-
#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG)
/* cputlb.c */
/**
diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
index a024a0350d..89edf94d28 100644
--- a/include/exec/gdbstub.h
+++ b/include/exec/gdbstub.h
@@ -45,17 +45,6 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...);
*/
void gdb_do_syscallv(gdb_syscall_complete_cb cb, const char *fmt, va_list va);
int use_gdb_syscalls(void);
-void gdb_set_stop_cpu(CPUState *cpu);
-
-/**
- * gdb_exit: exit gdb session, reporting inferior status
- * @code: exit code reported
- *
- * This closes the session and sends a final packet to GDB reporting
- * the exit status of the program. It also cleans up any connections
- * detritus before returning.
- */
-void gdb_exit(int code);
#ifdef CONFIG_USER_ONLY
/**
@@ -165,7 +154,7 @@ static inline uint8_t * gdb_get_reg_ptr(GByteArray *buf, int len)
#define ldtul_p(addr) ldl_p(addr)
#endif
-#endif
+#endif /* NEED_CPU_H */
/**
* gdbserver_start: start the gdb server
@@ -178,6 +167,18 @@ static inline uint8_t * gdb_get_reg_ptr(GByteArray *buf, int len)
int gdbserver_start(const char *port_or_device);
/**
+ * gdb_exit: exit gdb session, reporting inferior status
+ * @code: exit code reported
+ *
+ * This closes the session and sends a final packet to GDB reporting
+ * the exit status of the program. It also cleans up any connections
+ * detritus before returning.
+ */
+void gdb_exit(int code);
+
+void gdb_set_stop_cpu(CPUState *cpu);
+
+/**
* gdb_has_xml:
* This is an ugly hack to cope with both new and old gdb.
* If gdb sends qXfer:features:read then assume we're talking to a newish
diff --git a/include/exec/poison.h b/include/exec/poison.h
index 7ad4ad18e8..7c5c02f03f 100644
--- a/include/exec/poison.h
+++ b/include/exec/poison.h
@@ -51,8 +51,6 @@
#pragma GCC poison TARGET_PAGE_BITS
#pragma GCC poison TARGET_PAGE_ALIGN
-#pragma GCC poison CPUArchState
-
#pragma GCC poison CPU_INTERRUPT_HARD
#pragma GCC poison CPU_INTERRUPT_EXITTB
#pragma GCC poison CPU_INTERRUPT_HALT
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index c97e8633ad..2b42e4192b 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -77,6 +77,7 @@ typedef struct AcpiFadtData {
uint16_t plvl2_lat; /* P_LVL2_LAT */
uint16_t plvl3_lat; /* P_LVL3_LAT */
uint16_t arm_boot_arch; /* ARM_BOOT_ARCH */
+ uint16_t iapc_boot_arch; /* IAPC_BOOT_ARCH */
uint8_t minor_ver; /* FADT Minor Version */
/*
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index c1ea17d0de..7e76ee2619 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -132,6 +132,7 @@ struct VirtMachineClass {
bool no_secure_gpio;
/* Machines < 6.2 have no support for describing cpu topology to guest */
bool no_cpu_topology;
+ bool no_tcg_lpa2;
};
struct VirtMachineState {
diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index 76ab3b851c..0efc6153ed 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -22,6 +22,7 @@
#include "hw/qdev-core.h"
#include "disas/dis-asm.h"
+#include "exec/cpu-common.h"
#include "exec/hwaddr.h"
#include "exec/memattrs.h"
#include "qapi/qapi-types-run-state.h"
@@ -36,18 +37,6 @@ typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size,
void *opaque);
/**
- * vaddr:
- * Type wide enough to contain any #target_ulong virtual address.
- */
-typedef uint64_t vaddr;
-#define VADDR_PRId PRId64
-#define VADDR_PRIu PRIu64
-#define VADDR_PRIo PRIo64
-#define VADDR_PRIx PRIx64
-#define VADDR_PRIX PRIX64
-#define VADDR_MAX UINT64_MAX
-
-/**
* SECTION:cpu
* @section_id: QEMU-cpu
* @title: CPU Class
@@ -66,6 +55,24 @@ typedef struct CPUClass CPUClass;
DECLARE_CLASS_CHECKERS(CPUClass, CPU,
TYPE_CPU)
+/**
+ * OBJECT_DECLARE_CPU_TYPE:
+ * @CpuInstanceType: instance struct name
+ * @CpuClassType: class struct name
+ * @CPU_MODULE_OBJ_NAME: the CPU name in uppercase with underscore separators
+ *
+ * This macro is typically used in "cpu-qom.h" header file, and will:
+ *
+ * - create the typedefs for the CPU object and class structs
+ * - register the type for use with g_autoptr
+ * - provide three standard type cast functions
+ *
+ * The object struct and class struct need to be declared manually.
+ */
+#define OBJECT_DECLARE_CPU_TYPE(CpuInstanceType, CpuClassType, CPU_MODULE_OBJ_NAME) \
+ typedef struct ArchCPU CpuInstanceType; \
+ OBJECT_DECLARE_TYPE(ArchCPU, CpuClassType, CPU_MODULE_OBJ_NAME);
+
typedef enum MMUAccessType {
MMU_DATA_LOAD = 0,
MMU_DATA_STORE = 1,
@@ -351,7 +358,7 @@ struct CPUState {
AddressSpace *as;
MemoryRegion *memory;
- void *env_ptr; /* CPUArchState */
+ CPUArchState *env_ptr;
IcountDecr *icount_decr_ptr;
/* Accessed in parallel; all accesses must be atomic */
diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h
index 41783ee46d..3b5ac869db 100644
--- a/include/hw/i386/intel_iommu.h
+++ b/include/hw/i386/intel_iommu.h
@@ -228,6 +228,7 @@ struct IntelIOMMUState {
bool caching_mode; /* RO - is cap CM enabled? */
bool scalable_mode; /* RO - is Scalable Mode supported? */
+ bool snoop_control; /* RO - is SNP filed supported? */
dma_addr_t root; /* Current root table pointer */
bool root_scalable; /* Type of root table (scalable or not) */
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 9c9f4ac748..1a27de9c8b 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -48,6 +48,7 @@ typedef struct PCMachineState {
bool sata_enabled;
bool pit_enabled;
bool hpet_enabled;
+ bool i8042_enabled;
bool default_bus_bypass_iommu;
uint64_t max_fw_size;
@@ -64,6 +65,7 @@ typedef struct PCMachineState {
#define PC_MACHINE_SMBUS "smbus"
#define PC_MACHINE_SATA "sata"
#define PC_MACHINE_PIT "pit"
+#define PC_MACHINE_I8042 "i8042"
#define PC_MACHINE_MAX_FW_SIZE "max-fw-size"
#define PC_MACHINE_SMBIOS_EP "smbios-entry-point-type"
diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h
index a145a30370..916cc325ee 100644
--- a/include/hw/i386/x86.h
+++ b/include/hw/i386/x86.h
@@ -35,8 +35,6 @@ struct X86MachineClass {
/* TSC rate migration: */
bool save_tsc_khz;
- /* Enables contiguous-apic-ID mode */
- bool compat_apic_id_mode;
/* use DMA capable linuxboot option rom */
bool fwcfg_dma_enabled;
};
diff --git a/include/hw/input/i8042.h b/include/hw/input/i8042.h
index 1d90432dae..e070f546e4 100644
--- a/include/hw/input/i8042.h
+++ b/include/hw/input/i8042.h
@@ -23,4 +23,19 @@ void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq,
void i8042_isa_mouse_fake_event(ISAKBDState *isa);
void i8042_setup_a20_line(ISADevice *dev, qemu_irq a20_out);
+static inline bool i8042_present(void)
+{
+ bool amb = false;
+ return object_resolve_path_type("", TYPE_I8042, &amb) || amb;
+}
+
+/*
+ * ACPI v2, Table 5-10 - Fixed ACPI Description Table Boot Architecture
+ * Flags, bit offset 1 - 8042.
+ */
+static inline uint16_t iapc_boot_arch_8042(void)
+{
+ return i8042_present() ? 0x1 << 1 : 0x0 ;
+}
+
#endif /* HW_INPUT_I8042_H */
diff --git a/include/hw/isa/isa.h b/include/hw/isa/isa.h
index d4417b34b6..034d706ba1 100644
--- a/include/hw/isa/isa.h
+++ b/include/hw/isa/isa.h
@@ -83,8 +83,6 @@ struct ISADevice {
DeviceState parent_obj;
/*< public >*/
- int8_t isairq[2]; /* -1 = unassigned */
- int nirqs;
int ioport_id;
};
@@ -92,7 +90,6 @@ ISABus *isa_bus_new(DeviceState *dev, MemoryRegion *address_space,
MemoryRegion *address_space_io, Error **errp);
void isa_bus_irqs(ISABus *bus, qemu_irq *irqs);
qemu_irq isa_get_irq(ISADevice *dev, unsigned isairq);
-void isa_init_irq(ISADevice *dev, qemu_irq *p, unsigned isairq);
void isa_connect_gpio_out(ISADevice *isadev, int gpioirq, unsigned isairq);
void isa_bus_dma(ISABus *bus, IsaDma *dma8, IsaDma *dma16);
IsaDma *isa_get_dma(ISABus *bus, int nchan);
diff --git a/include/hw/mips/mips.h b/include/hw/mips/mips.h
index 6c9c8805f3..101799f7d3 100644
--- a/include/hw/mips/mips.h
+++ b/include/hw/mips/mips.h
@@ -9,9 +9,6 @@
#include "exec/memory.h"
-/* gt64xxx.c */
-PCIBus *gt64120_register(qemu_irq *pic);
-
/* bonito.c */
PCIBus *bonito_init(qemu_irq *pic);
diff --git a/include/hw/misc/pvpanic.h b/include/hw/misc/pvpanic.h
index ca3c5bb533..7f16cc9b16 100644
--- a/include/hw/misc/pvpanic.h
+++ b/include/hw/misc/pvpanic.h
@@ -22,14 +22,6 @@
#define PVPANIC_IOPORT_PROP "ioport"
-/* The bit of supported pv event, TODO: include uapi header and remove this */
-#define PVPANIC_F_PANICKED 0
-#define PVPANIC_F_CRASHLOADED 1
-
-/* The pv event value */
-#define PVPANIC_PANICKED (1 << PVPANIC_F_PANICKED)
-#define PVPANIC_CRASHLOADED (1 << PVPANIC_F_CRASHLOADED)
-
/*
* PVPanicState for any device type
*/
diff --git a/include/hw/pci-bridge/xio3130_downstream.h b/include/hw/pci-bridge/xio3130_downstream.h
new file mode 100644
index 0000000000..1d10139aea
--- /dev/null
+++ b/include/hw/pci-bridge/xio3130_downstream.h
@@ -0,0 +1,15 @@
+/*
+ * TI X3130 pci express downstream port switch
+ *
+ * Copyright (C) 2022 Igor Mammedov <imammedo@redhat.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef HW_PCI_BRIDGE_XIO3130_DOWNSTREAM_H
+#define HW_PCI_BRIDGE_XIO3130_DOWNSTREAM_H
+
+#define TYPE_XIO3130_DOWNSTREAM "xio3130-downstream"
+
+#endif
+
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index c3f3c90473..3a32b8dd40 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -7,9 +7,6 @@
/* PCI includes legacy ISA access. */
#include "hw/isa/isa.h"
-#include "hw/pci/pcie.h"
-#include "qom/object.h"
-
extern bool pci_available;
/* PCI bus */
@@ -157,6 +154,7 @@ enum {
#define QEMU_PCI_VGA_IO_HI_SIZE 0x20
#include "hw/pci/pci_regs.h"
+#include "hw/pci/pcie.h"
/* PCI HEADER_TYPE */
#define PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
@@ -499,6 +497,9 @@ typedef AddressSpace *(*PCIIOMMUFunc)(PCIBus *, void *, int);
AddressSpace *pci_device_iommu_address_space(PCIDevice *dev);
void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque);
+pcibus_t pci_bar_address(PCIDevice *d,
+ int reg, uint8_t type, pcibus_t size);
+
static inline void
pci_set_byte(uint8_t *config, uint8_t val)
{
@@ -779,6 +780,11 @@ static inline int pci_is_express_downstream_port(const PCIDevice *d)
return type == PCI_EXP_TYPE_DOWNSTREAM || type == PCI_EXP_TYPE_ROOT_PORT;
}
+static inline int pci_is_vf(const PCIDevice *d)
+{
+ return d->exp.sriov_vf.pf != NULL;
+}
+
static inline uint32_t pci_config_size(const PCIDevice *d)
{
return pci_is_express(d) ? PCIE_CONFIG_SPACE_SIZE : PCI_CONFIG_SPACE_SIZE;
diff --git a/include/hw/pci/pci_regs.h b/include/hw/pci/pci_regs.h
index 77ba64b931..a590140962 100644
--- a/include/hw/pci/pci_regs.h
+++ b/include/hw/pci/pci_regs.h
@@ -4,5 +4,6 @@
#include "standard-headers/linux/pci_regs.h"
#define PCI_PM_CAP_VER_1_1 0x0002 /* PCI PM spec ver. 1.1 */
+#define PCI_PM_CAP_VER_1_2 0x0003 /* PCI PM spec ver. 1.2 */
#endif
diff --git a/include/hw/pci/pcie.h b/include/hw/pci/pcie.h
index 6063bee0ec..798a262a0a 100644
--- a/include/hw/pci/pcie.h
+++ b/include/hw/pci/pcie.h
@@ -24,6 +24,7 @@
#include "hw/pci/pci_regs.h"
#include "hw/pci/pcie_regs.h"
#include "hw/pci/pcie_aer.h"
+#include "hw/pci/pcie_sriov.h"
#include "hw/hotplug.h"
typedef enum {
@@ -81,6 +82,11 @@ struct PCIExpressDevice {
/* ACS */
uint16_t acs_cap;
+
+ /* SR/IOV */
+ uint16_t sriov_cap;
+ PCIESriovPF sriov_pf;
+ PCIESriovVF sriov_vf;
};
#define COMPAT_PROP_PCP "power_controller_present"
@@ -112,6 +118,7 @@ void pcie_cap_slot_write_config(PCIDevice *dev,
uint32_t addr, uint32_t val, int len);
int pcie_cap_slot_post_load(void *opaque, int version_id);
void pcie_cap_slot_push_attention_button(PCIDevice *dev);
+void pcie_cap_slot_enable_power(PCIDevice *dev);
void pcie_cap_root_init(PCIDevice *dev);
void pcie_cap_root_reset(PCIDevice *dev);
diff --git a/include/hw/pci/pcie_sriov.h b/include/hw/pci/pcie_sriov.h
new file mode 100644
index 0000000000..80f5c84e75
--- /dev/null
+++ b/include/hw/pci/pcie_sriov.h
@@ -0,0 +1,77 @@
+/*
+ * pcie_sriov.h:
+ *
+ * Implementation of SR/IOV emulation support.
+ *
+ * Copyright (c) 2015 Knut Omang <knut.omang@oracle.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.
+ *
+ */
+
+#ifndef QEMU_PCIE_SRIOV_H
+#define QEMU_PCIE_SRIOV_H
+
+struct PCIESriovPF {
+ uint16_t num_vfs; /* Number of virtual functions created */
+ uint8_t vf_bar_type[PCI_NUM_REGIONS]; /* Store type for each VF bar */
+ const char *vfname; /* Reference to the device type used for the VFs */
+ PCIDevice **vf; /* Pointer to an array of num_vfs VF devices */
+};
+
+struct PCIESriovVF {
+ PCIDevice *pf; /* Pointer back to owner physical function */
+ uint16_t vf_number; /* Logical VF number of this function */
+};
+
+void pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset,
+ const char *vfname, uint16_t vf_dev_id,
+ uint16_t init_vfs, uint16_t total_vfs,
+ uint16_t vf_offset, uint16_t vf_stride);
+void pcie_sriov_pf_exit(PCIDevice *dev);
+
+/* Set up a VF bar in the SR/IOV bar area */
+void pcie_sriov_pf_init_vf_bar(PCIDevice *dev, int region_num,
+ uint8_t type, dma_addr_t size);
+
+/* Instantiate a bar for a VF */
+void pcie_sriov_vf_register_bar(PCIDevice *dev, int region_num,
+ MemoryRegion *memory);
+
+/*
+ * Default (minimal) page size support values
+ * as required by the SR/IOV standard:
+ * 0x553 << 12 = 0x553000 = 4K + 8K + 64K + 256K + 1M + 4M
+ */
+#define SRIOV_SUP_PGSIZE_MINREQ 0x553
+
+/*
+ * Optionally add supported page sizes to the mask of supported page sizes
+ * Page size values are interpreted as opt_sup_pgsize << 12.
+ */
+void pcie_sriov_pf_add_sup_pgsize(PCIDevice *dev, uint16_t opt_sup_pgsize);
+
+/* SR/IOV capability config write handler */
+void pcie_sriov_config_write(PCIDevice *dev, uint32_t address,
+ uint32_t val, int len);
+
+/* Reset SR/IOV VF Enable bit to unregister all VFs */
+void pcie_sriov_pf_disable_vfs(PCIDevice *dev);
+
+/* Get logical VF number of a VF - only valid for VFs */
+uint16_t pcie_sriov_vf_number(PCIDevice *dev);
+
+/*
+ * Get the physical function that owns this VF.
+ * Returns NULL if dev is not a virtual function
+ */
+PCIDevice *pcie_sriov_get_pf(PCIDevice *dev);
+
+/*
+ * Get the n-th VF of this physical function - only valid for PF.
+ * Returns NULL if index is invalid
+ */
+PCIDevice *pcie_sriov_get_vf_at_index(PCIDevice *dev, int n);
+
+#endif /* QEMU_PCIE_SRIOV_H */
diff --git a/include/hw/rtc/mc146818rtc.h b/include/hw/rtc/mc146818rtc.h
index 5b45b22924..deef93f89a 100644
--- a/include/hw/rtc/mc146818rtc.h
+++ b/include/hw/rtc/mc146818rtc.h
@@ -25,6 +25,7 @@ struct RTCState {
MemoryRegion coalesced_io;
uint8_t cmos_data[128];
uint8_t cmos_index;
+ uint8_t isairq;
int32_t base_year;
uint64_t base_rtc;
uint64_t last_update;
diff --git a/include/hw/southbridge/piix.h b/include/hw/southbridge/piix.h
index 6387f2b612..f63f83e5c6 100644
--- a/include/hw/southbridge/piix.h
+++ b/include/hw/southbridge/piix.h
@@ -70,8 +70,6 @@ typedef struct PIIXState PIIX3State;
DECLARE_INSTANCE_CHECKER(PIIX3State, PIIX3_PCI_DEVICE,
TYPE_PIIX3_PCI_DEVICE)
-extern PCIDevice *piix4_dev;
-
PIIX3State *piix3_create(PCIBus *pci_bus, ISABus **isa_bus);
DeviceState *piix4_create(PCIBus *pci_bus, ISABus **isa_bus, I2CBus **smbus);
diff --git a/include/hw/virtio/vhost-user-i2c.h b/include/hw/virtio/vhost-user-i2c.h
index deae47a76d..d8372f3b43 100644
--- a/include/hw/virtio/vhost-user-i2c.h
+++ b/include/hw/virtio/vhost-user-i2c.h
@@ -25,4 +25,7 @@ struct VHostUserI2C {
bool connected;
};
+/* Virtio Feature bits */
+#define VIRTIO_I2C_F_ZERO_LENGTH_REQUEST 0
+
#endif /* _QEMU_VHOST_USER_I2C_H */
diff --git a/include/hw/virtio/vhost-user.h b/include/hw/virtio/vhost-user.h
index a9abca3288..e44a41bb70 100644
--- a/include/hw/virtio/vhost-user.h
+++ b/include/hw/virtio/vhost-user.h
@@ -12,9 +12,10 @@
#include "hw/virtio/virtio.h"
typedef struct VhostUserHostNotifier {
+ struct rcu_head rcu;
MemoryRegion mr;
void *addr;
- bool set;
+ void *unmap_addr;
} VhostUserHostNotifier;
typedef struct VhostUserState {
diff --git a/include/hw/virtio/virtio-iommu.h b/include/hw/virtio/virtio-iommu.h
index e2339e5b72..84391f8448 100644
--- a/include/hw/virtio/virtio-iommu.h
+++ b/include/hw/virtio/virtio-iommu.h
@@ -58,6 +58,7 @@ struct VirtIOIOMMU {
GTree *domains;
QemuMutex mutex;
GTree *endpoints;
+ bool boot_bypass;
};
#endif
diff --git a/include/qemu-common.h b/include/qemu-common.h
index 68b2e3bc10..8c0d9ab0f7 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -26,8 +26,6 @@
int qemu_main(int argc, char **argv, char **envp);
#endif
-void *qemu_oom_check(void *ptr);
-
ssize_t qemu_write_full(int fd, const void *buf, size_t count)
QEMU_WARN_UNUSED_RESULT;
diff --git a/include/qemu/event_notifier.h b/include/qemu/event_notifier.h
index b79add035d..8a4ff308e1 100644
--- a/include/qemu/event_notifier.h
+++ b/include/qemu/event_notifier.h
@@ -38,6 +38,7 @@ int event_notifier_test_and_clear(EventNotifier *);
#ifdef CONFIG_POSIX
void event_notifier_init_fd(EventNotifier *, int fd);
int event_notifier_get_fd(const EventNotifier *);
+int event_notifier_get_wfd(const EventNotifier *);
#else
HANDLE event_notifier_get_handle(EventNotifier *);
#endif
diff --git a/include/qemu/memalign.h b/include/qemu/memalign.h
new file mode 100644
index 0000000000..fa299f3bf6
--- /dev/null
+++ b/include/qemu/memalign.h
@@ -0,0 +1,61 @@
+/*
+ * Allocation and free functions for aligned memory
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef QEMU_MEMALIGN_H
+#define QEMU_MEMALIGN_H
+
+/**
+ * qemu_try_memalign: Allocate aligned memory
+ * @alignment: required alignment, in bytes
+ * @size: size of allocation, in bytes
+ *
+ * Allocate memory on an aligned boundary (i.e. the returned
+ * address will be an exact multiple of @alignment).
+ * @alignment must be a power of 2, or the function will assert().
+ * On success, returns allocated memory; on failure, returns NULL.
+ *
+ * The memory allocated through this function must be freed via
+ * qemu_vfree() (and not via free()).
+ */
+void *qemu_try_memalign(size_t alignment, size_t size);
+/**
+ * qemu_memalign: Allocate aligned memory, without failing
+ * @alignment: required alignment, in bytes
+ * @size: size of allocation, in bytes
+ *
+ * Allocate memory in the same way as qemu_try_memalign(), but
+ * abort() with an error message if the memory allocation fails.
+ *
+ * The memory allocated through this function must be freed via
+ * qemu_vfree() (and not via free()).
+ */
+void *qemu_memalign(size_t alignment, size_t size);
+/**
+ * qemu_vfree: Free memory allocated through qemu_memalign
+ * @ptr: memory to free
+ *
+ * This function must be used to free memory allocated via qemu_memalign()
+ * or qemu_try_memalign(). (Using the wrong free function will cause
+ * subtle bugs on Windows hosts.)
+ */
+void qemu_vfree(void *ptr);
+/*
+ * It's an analog of GLIB's g_autoptr_cleanup_generic_gfree(), used to define
+ * g_autofree macro.
+ */
+static inline void qemu_cleanup_generic_vfree(void *p)
+{
+ void **pp = (void **)p;
+ qemu_vfree(*pp);
+}
+
+/*
+ * Analog of g_autofree, but qemu_vfree is called on cleanup instead of g_free.
+ */
+#define QEMU_AUTO_VFREE __attribute__((cleanup(qemu_cleanup_generic_vfree)))
+
+#endif
diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
index 7bcce3bceb..c9ec7830c9 100644
--- a/include/qemu/osdep.h
+++ b/include/qemu/osdep.h
@@ -379,28 +379,10 @@ extern "C" {
#endif
int qemu_daemon(int nochdir, int noclose);
-void *qemu_try_memalign(size_t alignment, size_t size);
-void *qemu_memalign(size_t alignment, size_t size);
void *qemu_anon_ram_alloc(size_t size, uint64_t *align, bool shared,
bool noreserve);
-void qemu_vfree(void *ptr);
void qemu_anon_ram_free(void *ptr, size_t size);
-/*
- * It's an analog of GLIB's g_autoptr_cleanup_generic_gfree(), used to define
- * g_autofree macro.
- */
-static inline void qemu_cleanup_generic_vfree(void *p)
-{
- void **pp = (void **)p;
- qemu_vfree(*pp);
-}
-
-/*
- * Analog of g_autofree, but qemu_vfree is called on cleanup instead of g_free.
- */
-#define QEMU_AUTO_VFREE __attribute__((cleanup(qemu_cleanup_generic_vfree)))
-
#ifdef _WIN32
#define HAVE_CHARDEV_SERIAL 1
#elif defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
@@ -673,19 +655,6 @@ static inline int platform_does_not_support_system(const char *command)
}
#endif /* !HAVE_SYSTEM_FUNCTION */
-/**
- * Duplicate directory entry @dent.
- *
- * It is highly recommended to use this function instead of open coding
- * duplication of @c dirent objects, because the actual @c struct @c dirent
- * size may be bigger or shorter than @c sizeof(struct dirent) and correct
- * handling is platform specific (see gitlab issue #841).
- *
- * @dent - original directory entry to be duplicated
- * @returns duplicated directory entry which should be freed with g_free()
- */
-struct dirent *qemu_dirent_dup(struct dirent *dent);
-
#ifdef __cplusplus
}
#endif
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index ee60eb3de4..42f4ceb701 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -26,6 +26,7 @@ typedef struct AddressSpace AddressSpace;
typedef struct AioContext AioContext;
typedef struct Aml Aml;
typedef struct AnnounceTimer AnnounceTimer;
+typedef struct ArchCPU ArchCPU;
typedef struct BdrvDirtyBitmap BdrvDirtyBitmap;
typedef struct BdrvDirtyBitmapIter BdrvDirtyBitmapIter;
typedef struct BlockBackend BlockBackend;
@@ -39,6 +40,7 @@ typedef struct CompatProperty CompatProperty;
typedef struct CoMutex CoMutex;
typedef struct ConfidentialGuestSupport ConfidentialGuestSupport;
typedef struct CPUAddressSpace CPUAddressSpace;
+typedef struct CPUArchState CPUArchState;
typedef struct CPUState CPUState;
typedef struct DeviceListener DeviceListener;
typedef struct DeviceState DeviceState;
@@ -86,6 +88,8 @@ typedef struct PCIDevice PCIDevice;
typedef struct PCIEAERErr PCIEAERErr;
typedef struct PCIEAERLog PCIEAERLog;
typedef struct PCIEAERMsg PCIEAERMsg;
+typedef struct PCIESriovPF PCIESriovPF;
+typedef struct PCIESriovVF PCIESriovVF;
typedef struct PCIEPort PCIEPort;
typedef struct PCIESlot PCIESlot;
typedef struct PCIExpressDevice PCIExpressDevice;
diff --git a/include/qemu/xattr.h b/include/qemu/xattr.h
index a83fe8e749..f1d0f7be74 100644
--- a/include/qemu/xattr.h
+++ b/include/qemu/xattr.h
@@ -22,7 +22,9 @@
#ifdef CONFIG_LIBATTR
# include <attr/xattr.h>
#else
-# define ENOATTR ENODATA
+# if !defined(ENOATTR)
+# define ENOATTR ENODATA
+# endif
# include <sys/xattr.h>
#endif
diff --git a/include/standard-headers/linux/pvpanic.h b/include/standard-headers/linux/pvpanic.h
new file mode 100644
index 0000000000..54b7485390
--- /dev/null
+++ b/include/standard-headers/linux/pvpanic.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+
+#ifndef __PVPANIC_H__
+#define __PVPANIC_H__
+
+#define PVPANIC_PANICKED (1 << 0)
+#define PVPANIC_CRASH_LOADED (1 << 1)
+
+#endif /* __PVPANIC_H__ */
diff --git a/include/sysemu/accel-ops.h b/include/sysemu/accel-ops.h
index 032f6979d7..6013c9444c 100644
--- a/include/sysemu/accel-ops.h
+++ b/include/sysemu/accel-ops.h
@@ -28,8 +28,11 @@ struct AccelOpsClass {
/* initialization function called when accel is chosen */
void (*ops_init)(AccelOpsClass *ops);
+ bool (*cpus_are_resettable)(void);
+
void (*create_vcpu_thread)(CPUState *cpu); /* MANDATORY NON-NULL */
void (*kick_vcpu_thread)(CPUState *cpu);
+ bool (*cpu_thread_is_idle)(CPUState *cpu);
void (*synchronize_post_reset)(CPUState *cpu);
void (*synchronize_post_init)(CPUState *cpu);
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index 70c579560a..79c2591425 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -28,4 +28,6 @@ enum {
extern const uint32_t arch_type;
+void qemu_init_arch_modules(void);
+
#endif
diff --git a/include/sysemu/hax.h b/include/sysemu/hax.h
index 247f0661d1..bf8f99a824 100644
--- a/include/sysemu/hax.h
+++ b/include/sysemu/hax.h
@@ -25,17 +25,23 @@
int hax_sync_vcpus(void);
#ifdef NEED_CPU_H
+# ifdef CONFIG_HAX
+# define CONFIG_HAX_IS_POSSIBLE
+# endif
+#else /* !NEED_CPU_H */
+# define CONFIG_HAX_IS_POSSIBLE
+#endif
-#ifdef CONFIG_HAX
+#ifdef CONFIG_HAX_IS_POSSIBLE
-int hax_enabled(void);
+extern bool hax_allowed;
-#else /* CONFIG_HAX */
+#define hax_enabled() (hax_allowed)
-#define hax_enabled() (0)
+#else /* !CONFIG_HAX_IS_POSSIBLE */
-#endif /* CONFIG_HAX */
+#define hax_enabled() (0)
-#endif /* NEED_CPU_H */
+#endif /* CONFIG_HAX_IS_POSSIBLE */
#endif /* QEMU_HAX_H */
diff --git a/include/sysemu/hw_accel.h b/include/sysemu/hw_accel.h
index 01b5ebf442..22903a55f7 100644
--- a/include/sysemu/hw_accel.h
+++ b/include/sysemu/hw_accel.h
@@ -23,9 +23,4 @@ void cpu_synchronize_post_reset(CPUState *cpu);
void cpu_synchronize_post_init(CPUState *cpu);
void cpu_synchronize_pre_loadvm(CPUState *cpu);
-static inline bool cpu_check_are_resettable(void)
-{
- return kvm_enabled() ? kvm_cpu_check_are_resettable() : true;
-}
-
#endif /* QEMU_HW_ACCEL_H */
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 6eb39a088b..a5bec96fb0 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -249,6 +249,9 @@ int kvm_has_intx_set_mask(void);
bool kvm_arm_supports_user_irq(void);
+int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
+int kvm_on_sigbus(int code, void *addr);
+
#ifdef NEED_CPU_H
#include "cpu.h"
@@ -261,9 +264,6 @@ int kvm_remove_breakpoint(CPUState *cpu, target_ulong addr,
void kvm_remove_all_breakpoints(CPUState *cpu);
int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap);
-int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
-int kvm_on_sigbus(int code, void *addr);
-
/* internal API */
int kvm_ioctl(KVMState *s, int type, ...);
diff --git a/include/sysemu/memory_mapping.h b/include/sysemu/memory_mapping.h
index 4b20f1a639..3bbeb1bcb4 100644
--- a/include/sysemu/memory_mapping.h
+++ b/include/sysemu/memory_mapping.h
@@ -15,8 +15,7 @@
#define MEMORY_MAPPING_H
#include "qemu/queue.h"
-#include "exec/cpu-defs.h"
-#include "exec/memory.h"
+#include "exec/cpu-common.h"
typedef struct GuestPhysBlock {
/* visible to guest, reflects PCI hole, etc */
@@ -43,7 +42,7 @@ typedef struct GuestPhysBlockList {
/* The physical and virtual address in the memory mapping are contiguous. */
typedef struct MemoryMapping {
hwaddr phys_addr;
- target_ulong virt_addr;
+ vaddr virt_addr;
ram_addr_t length;
QTAILQ_ENTRY(MemoryMapping) next;
} MemoryMapping;
diff --git a/meson.build b/meson.build
index 038502714a..2d6601467f 100644
--- a/meson.build
+++ b/meson.build
@@ -1462,14 +1462,16 @@ dbus_display = get_option('dbus_display') \
.allowed()
have_virtfs = get_option('virtfs') \
- .require(targetos == 'linux',
- error_message: 'virtio-9p (virtfs) requires Linux') \
- .require(libattr.found() and libcap_ng.found(),
- error_message: 'virtio-9p (virtfs) requires libcap-ng-devel and libattr-devel') \
+ .require(targetos == 'linux' or targetos == 'darwin',
+ error_message: 'virtio-9p (virtfs) requires Linux or macOS') \
+ .require(targetos == 'linux' or cc.has_function('pthread_fchdir_np'),
+ error_message: 'virtio-9p (virtfs) on macOS requires the presence of pthread_fchdir_np') \
+ .require(targetos == 'darwin' or (libattr.found() and libcap_ng.found()),
+ error_message: 'virtio-9p (virtfs) on Linux requires libcap-ng-devel and libattr-devel') \
.disable_auto_if(not have_tools and not have_system) \
.allowed()
-have_virtfs_proxy_helper = have_virtfs and have_tools
+have_virtfs_proxy_helper = targetos != 'darwin' and have_virtfs and have_tools
foreach k : get_option('trace_backends')
config_host_data.set('CONFIG_TRACE_' + k.to_upper(), true)
@@ -1619,9 +1621,15 @@ config_host_data.set('CONFIG_CLOCK_ADJTIME', cc.has_function('clock_adjtime'))
config_host_data.set('CONFIG_DUP3', cc.has_function('dup3'))
config_host_data.set('CONFIG_FALLOCATE', cc.has_function('fallocate'))
config_host_data.set('CONFIG_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
-config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign'))
+# Note that we need to specify prefix: here to avoid incorrectly
+# thinking that Windows has posix_memalign()
+config_host_data.set('CONFIG_POSIX_MEMALIGN', cc.has_function('posix_memalign', prefix: '#include <stdlib.h>'))
+config_host_data.set('CONFIG_ALIGNED_MALLOC', cc.has_function('_aligned_malloc'))
+config_host_data.set('CONFIG_VALLOC', cc.has_function('valloc'))
+config_host_data.set('CONFIG_MEMALIGN', cc.has_function('memalign'))
config_host_data.set('CONFIG_PPOLL', cc.has_function('ppoll'))
config_host_data.set('CONFIG_PREADV', cc.has_function('preadv', prefix: '#include <sys/uio.h>'))
+config_host_data.set('CONFIG_PTHREAD_FCHDIR_NP', cc.has_function('pthread_fchdir_np'))
config_host_data.set('CONFIG_SEM_TIMEDWAIT', cc.has_function('sem_timedwait', dependencies: threads))
config_host_data.set('CONFIG_SENDFILE', cc.has_function('sendfile'))
config_host_data.set('CONFIG_SETNS', cc.has_function('setns') and cc.has_function('unshare'))
@@ -2432,8 +2440,8 @@ if get_option('cfi') and slirp_opt == 'system'
endif
fdt = not_found
-fdt_opt = get_option('fdt')
if have_system
+ fdt_opt = get_option('fdt')
if fdt_opt in ['enabled', 'auto', 'system']
have_internal = fs.exists(meson.current_source_dir() / 'dtc/libfdt/Makefile.libfdt')
fdt = cc.find_library('fdt', kwargs: static_kwargs,
@@ -2476,6 +2484,8 @@ if have_system
fdt = declare_dependency(link_with: libfdt,
include_directories: fdt_inc)
endif
+else
+ fdt_opt = 'disabled'
endif
if not fdt.found() and fdt_required.length() > 0
error('fdt not available but required by targets ' + ', '.join(fdt_required))
@@ -2715,7 +2725,7 @@ if have_system or have_user
endif
vhost_user = not_found
-if 'CONFIG_VHOST_USER' in config_host
+if targetos == 'linux' and 'CONFIG_VHOST_USER' in config_host
libvhost_user = subproject('libvhost-user')
vhost_user = libvhost_user.get_variable('vhost_user_dep')
endif
diff --git a/nbd/server.c b/nbd/server.c
index ba6f71e15d..5da884c2fc 100644
--- a/nbd/server.c
+++ b/nbd/server.c
@@ -25,6 +25,7 @@
#include "trace.h"
#include "nbd-internal.h"
#include "qemu/units.h"
+#include "qemu/memalign.h"
#define NBD_META_ID_BASE_ALLOCATION 0
#define NBD_META_ID_ALLOCATION_DEPTH 1
diff --git a/net/l2tpv3.c b/net/l2tpv3.c
index e4d4218db6..b8faa8796c 100644
--- a/net/l2tpv3.c
+++ b/net/l2tpv3.c
@@ -34,7 +34,7 @@
#include "qemu/sockets.h"
#include "qemu/iov.h"
#include "qemu/main-loop.h"
-
+#include "qemu/memalign.h"
/* The buffer size needs to be investigated for optimum numbers and
* optimum means of paging in on different systems. This size is
diff --git a/pc-bios/bios-256k.bin b/pc-bios/bios-256k.bin
index e0796344df..6163fb8149 100644
--- a/pc-bios/bios-256k.bin
+++ b/pc-bios/bios-256k.bin
Binary files differ
diff --git a/pc-bios/bios-microvm.bin b/pc-bios/bios-microvm.bin
index f0215521b0..97fbd3192a 100644
--- a/pc-bios/bios-microvm.bin
+++ b/pc-bios/bios-microvm.bin
Binary files differ
diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index bcf8b484c9..68f65ff2fd 100644
--- a/pc-bios/bios.bin
+++ b/pc-bios/bios.bin
Binary files differ
diff --git a/pc-bios/vgabios-ati.bin b/pc-bios/vgabios-ati.bin
index 7171a56f9d..4533d0d063 100644
--- a/pc-bios/vgabios-ati.bin
+++ b/pc-bios/vgabios-ati.bin
Binary files differ
diff --git a/pc-bios/vgabios-bochs-display.bin b/pc-bios/vgabios-bochs-display.bin
index afea4c930d..3ecf92de01 100644
--- a/pc-bios/vgabios-bochs-display.bin
+++ b/pc-bios/vgabios-bochs-display.bin
Binary files differ
diff --git a/pc-bios/vgabios-cirrus.bin b/pc-bios/vgabios-cirrus.bin
index 194c8139a7..9b4ffdf45f 100644
--- a/pc-bios/vgabios-cirrus.bin
+++ b/pc-bios/vgabios-cirrus.bin
Binary files differ
diff --git a/pc-bios/vgabios-qxl.bin b/pc-bios/vgabios-qxl.bin
index 056b6657b3..8a27dac557 100644
--- a/pc-bios/vgabios-qxl.bin
+++ b/pc-bios/vgabios-qxl.bin
Binary files differ
diff --git a/pc-bios/vgabios-ramfb.bin b/pc-bios/vgabios-ramfb.bin
index 02662006f2..ec9541cfb4 100644
--- a/pc-bios/vgabios-ramfb.bin
+++ b/pc-bios/vgabios-ramfb.bin
Binary files differ
diff --git a/pc-bios/vgabios-stdvga.bin b/pc-bios/vgabios-stdvga.bin
index cf81ce2876..55390c45c9 100644
--- a/pc-bios/vgabios-stdvga.bin
+++ b/pc-bios/vgabios-stdvga.bin
Binary files differ
diff --git a/pc-bios/vgabios-virtio.bin b/pc-bios/vgabios-virtio.bin
index f4178f70de..2334733a75 100644
--- a/pc-bios/vgabios-virtio.bin
+++ b/pc-bios/vgabios-virtio.bin
Binary files differ
diff --git a/pc-bios/vgabios-vmware.bin b/pc-bios/vgabios-vmware.bin
index 8fae88af28..b668ac04a6 100644
--- a/pc-bios/vgabios-vmware.bin
+++ b/pc-bios/vgabios-vmware.bin
Binary files differ
diff --git a/pc-bios/vgabios.bin b/pc-bios/vgabios.bin
index e5f45f0c9e..a924891ea5 100644
--- a/pc-bios/vgabios.bin
+++ b/pc-bios/vgabios.bin
Binary files differ
diff --git a/plugins/loader.c b/plugins/loader.c
index 4883b0a1cb..88c30bde2d 100644
--- a/plugins/loader.c
+++ b/plugins/loader.c
@@ -27,6 +27,7 @@
#include "qemu/cacheinfo.h"
#include "qemu/xxhash.h"
#include "qemu/plugin.h"
+#include "qemu/memalign.h"
#include "hw/core/cpu.h"
#include "exec/exec-all.h"
#ifndef CONFIG_USER_ONLY
diff --git a/python/qemu/aqmp/legacy.py b/python/qemu/aqmp/legacy.py
index 6baa5f3409..46026e9fdc 100644
--- a/python/qemu/aqmp/legacy.py
+++ b/python/qemu/aqmp/legacy.py
@@ -57,7 +57,7 @@ class QEMUMonitorProtocol(qemu.qmp.QEMUMonitorProtocol):
self._timeout: Optional[float] = None
if server:
- self._aqmp._bind_hack(address) # pylint: disable=protected-access
+ self._sync(self._aqmp.start_server(self._address))
_T = TypeVar('_T')
@@ -90,10 +90,7 @@ class QEMUMonitorProtocol(qemu.qmp.QEMUMonitorProtocol):
self._aqmp.await_greeting = True
self._aqmp.negotiate = True
- self._sync(
- self._aqmp.accept(self._address),
- timeout
- )
+ self._sync(self._aqmp.accept(), timeout)
ret = self._get_greeting()
assert ret is not None
diff --git a/python/qemu/aqmp/protocol.py b/python/qemu/aqmp/protocol.py
index 33358f5cd7..36fae57f27 100644
--- a/python/qemu/aqmp/protocol.py
+++ b/python/qemu/aqmp/protocol.py
@@ -10,12 +10,14 @@ In this package, it is used as the implementation for the `QMPClient`
class.
"""
+# It's all the docstrings ... ! It's long for a good reason ^_^;
+# pylint: disable=too-many-lines
+
import asyncio
from asyncio import StreamReader, StreamWriter
from enum import Enum
from functools import wraps
import logging
-import socket
from ssl import SSLContext
from typing import (
Any,
@@ -239,8 +241,9 @@ class AsyncProtocol(Generic[T]):
self._runstate = Runstate.IDLE
self._runstate_changed: Optional[asyncio.Event] = None
- # Workaround for bind()
- self._sock: Optional[socket.socket] = None
+ # Server state for start_server() and _incoming()
+ self._server: Optional[asyncio.AbstractServer] = None
+ self._accepted: Optional[asyncio.Event] = None
def __repr__(self) -> str:
cls_name = type(self).__name__
@@ -265,21 +268,90 @@ class AsyncProtocol(Generic[T]):
@upper_half
@require(Runstate.IDLE)
- async def accept(self, address: SocketAddrT,
- ssl: Optional[SSLContext] = None) -> None:
+ async def start_server_and_accept(
+ self, address: SocketAddrT,
+ ssl: Optional[SSLContext] = None
+ ) -> None:
"""
Accept a connection and begin processing message queues.
If this call fails, `runstate` is guaranteed to be set back to `IDLE`.
+ This method is precisely equivalent to calling `start_server()`
+ followed by `accept()`.
+
+ :param address:
+ Address to listen on; UNIX socket path or TCP address/port.
+ :param ssl: SSL context to use, if any.
+
+ :raise StateError: When the `Runstate` is not `IDLE`.
+ :raise ConnectError:
+ When a connection or session cannot be established.
+
+ This exception will wrap a more concrete one. In most cases,
+ the wrapped exception will be `OSError` or `EOFError`. If a
+ protocol-level failure occurs while establishing a new
+ session, the wrapped error may also be an `QMPError`.
+ """
+ await self.start_server(address, ssl)
+ await self.accept()
+ assert self.runstate == Runstate.RUNNING
+
+ @upper_half
+ @require(Runstate.IDLE)
+ async def start_server(self, address: SocketAddrT,
+ ssl: Optional[SSLContext] = None) -> None:
+ """
+ Start listening for an incoming connection, but do not wait for a peer.
+
+ This method starts listening for an incoming connection, but
+ does not block waiting for a peer. This call will return
+ immediately after binding and listening on a socket. A later
+ call to `accept()` must be made in order to finalize the
+ incoming connection.
:param address:
- Address to listen to; UNIX socket path or TCP address/port.
+ Address to listen on; UNIX socket path or TCP address/port.
:param ssl: SSL context to use, if any.
:raise StateError: When the `Runstate` is not `IDLE`.
- :raise ConnectError: If a connection could not be accepted.
+ :raise ConnectError:
+ When the server could not start listening on this address.
+
+ This exception will wrap a more concrete one. In most cases,
+ the wrapped exception will be `OSError`.
+ """
+ await self._session_guard(
+ self._do_start_server(address, ssl),
+ 'Failed to establish connection')
+ assert self.runstate == Runstate.CONNECTING
+
+ @upper_half
+ @require(Runstate.CONNECTING)
+ async def accept(self) -> None:
+ """
+ Accept an incoming connection and begin processing message queues.
+
+ If this call fails, `runstate` is guaranteed to be set back to `IDLE`.
+
+ :raise StateError: When the `Runstate` is not `CONNECTING`.
+ :raise QMPError: When `start_server()` was not called yet.
+ :raise ConnectError:
+ When a connection or session cannot be established.
+
+ This exception will wrap a more concrete one. In most cases,
+ the wrapped exception will be `OSError` or `EOFError`. If a
+ protocol-level failure occurs while establishing a new
+ session, the wrapped error may also be an `QMPError`.
"""
- await self._new_session(address, ssl, accept=True)
+ if self._accepted is None:
+ raise QMPError("Cannot call accept() before start_server().")
+ await self._session_guard(
+ self._do_accept(),
+ 'Failed to establish connection')
+ await self._session_guard(
+ self._establish_session(),
+ 'Failed to establish session')
+ assert self.runstate == Runstate.RUNNING
@upper_half
@require(Runstate.IDLE)
@@ -295,9 +367,21 @@ class AsyncProtocol(Generic[T]):
:param ssl: SSL context to use, if any.
:raise StateError: When the `Runstate` is not `IDLE`.
- :raise ConnectError: If a connection cannot be made to the server.
+ :raise ConnectError:
+ When a connection or session cannot be established.
+
+ This exception will wrap a more concrete one. In most cases,
+ the wrapped exception will be `OSError` or `EOFError`. If a
+ protocol-level failure occurs while establishing a new
+ session, the wrapped error may also be an `QMPError`.
"""
- await self._new_session(address, ssl)
+ await self._session_guard(
+ self._do_connect(address, ssl),
+ 'Failed to establish connection')
+ await self._session_guard(
+ self._establish_session(),
+ 'Failed to establish session')
+ assert self.runstate == Runstate.RUNNING
@upper_half
async def disconnect(self) -> None:
@@ -317,153 +401,146 @@ class AsyncProtocol(Generic[T]):
# Section: Session machinery
# --------------------------
- @property
- def _runstate_event(self) -> asyncio.Event:
- # asyncio.Event() objects should not be created prior to entrance into
- # an event loop, so we can ensure we create it in the correct context.
- # Create it on-demand *only* at the behest of an 'async def' method.
- if not self._runstate_changed:
- self._runstate_changed = asyncio.Event()
- return self._runstate_changed
-
- @upper_half
- @bottom_half
- def _set_state(self, state: Runstate) -> None:
- """
- Change the `Runstate` of the protocol connection.
-
- Signals the `runstate_changed` event.
- """
- if state == self._runstate:
- return
-
- self.logger.debug("Transitioning from '%s' to '%s'.",
- str(self._runstate), str(state))
- self._runstate = state
- self._runstate_event.set()
- self._runstate_event.clear()
-
- @upper_half
- async def _new_session(self,
- address: SocketAddrT,
- ssl: Optional[SSLContext] = None,
- accept: bool = False) -> None:
+ async def _session_guard(self, coro: Awaitable[None], emsg: str) -> None:
"""
- Establish a new connection and initialize the session.
+ Async guard function used to roll back to `IDLE` on any error.
- Connect or accept a new connection, then begin the protocol
- session machinery. If this call fails, `runstate` is guaranteed
- to be set back to `IDLE`.
+ On any Exception, the state machine will be reset back to
+ `IDLE`. Most Exceptions will be wrapped with `ConnectError`, but
+ `BaseException` events will be left alone (This includes
+ asyncio.CancelledError, even prior to Python 3.8).
- :param address:
- Address to connect to/listen on;
- UNIX socket path or TCP address/port.
- :param ssl: SSL context to use, if any.
- :param accept: Accept a connection instead of connecting when `True`.
+ :param error_message:
+ Human-readable string describing what connection phase failed.
+ :raise BaseException:
+ When `BaseException` occurs in the guarded block.
:raise ConnectError:
- When a connection or session cannot be established.
-
- This exception will wrap a more concrete one. In most cases,
- the wrapped exception will be `OSError` or `EOFError`. If a
- protocol-level failure occurs while establishing a new
- session, the wrapped error may also be an `QMPError`.
+ When any other error is encountered in the guarded block.
"""
- assert self.runstate == Runstate.IDLE
-
+ # Note: After Python 3.6 support is removed, this should be an
+ # @asynccontextmanager instead of accepting a callback.
try:
- phase = "connection"
- await self._establish_connection(address, ssl, accept)
-
- phase = "session"
- await self._establish_session()
-
+ await coro
except BaseException as err:
- emsg = f"Failed to establish {phase}"
self.logger.error("%s: %s", emsg, exception_summary(err))
self.logger.debug("%s:\n%s\n", emsg, pretty_traceback())
try:
- # Reset from CONNECTING back to IDLE.
+ # Reset the runstate back to IDLE.
await self.disconnect()
except:
- emsg = "Unexpected bottom half exception"
+ # We don't expect any Exceptions from the disconnect function
+ # here, because we failed to connect in the first place.
+ # The disconnect() function is intended to perform
+ # only cannot-fail cleanup here, but you never know.
+ emsg = (
+ "Unexpected bottom half exception. "
+ "This is a bug in the QMP library. "
+ "Please report it to <qemu-devel@nongnu.org> and "
+ "CC: John Snow <jsnow@redhat.com>."
+ )
self.logger.critical("%s:\n%s\n", emsg, pretty_traceback())
raise
+ # CancelledError is an Exception with special semantic meaning;
+ # We do NOT want to wrap it up under ConnectError.
# NB: CancelledError is not a BaseException before Python 3.8
if isinstance(err, asyncio.CancelledError):
raise
+ # Any other kind of error can be treated as some kind of connection
+ # failure broadly. Inspect the 'exc' field to explore the root
+ # cause in greater detail.
if isinstance(err, Exception):
raise ConnectError(emsg, err) from err
# Raise BaseExceptions un-wrapped, they're more important.
raise
- assert self.runstate == Runstate.RUNNING
+ @property
+ def _runstate_event(self) -> asyncio.Event:
+ # asyncio.Event() objects should not be created prior to entrance into
+ # an event loop, so we can ensure we create it in the correct context.
+ # Create it on-demand *only* at the behest of an 'async def' method.
+ if not self._runstate_changed:
+ self._runstate_changed = asyncio.Event()
+ return self._runstate_changed
@upper_half
- async def _establish_connection(
- self,
- address: SocketAddrT,
- ssl: Optional[SSLContext] = None,
- accept: bool = False
- ) -> None:
+ @bottom_half
+ def _set_state(self, state: Runstate) -> None:
"""
- Establish a new connection.
+ Change the `Runstate` of the protocol connection.
- :param address:
- Address to connect to/listen on;
- UNIX socket path or TCP address/port.
- :param ssl: SSL context to use, if any.
- :param accept: Accept a connection instead of connecting when `True`.
+ Signals the `runstate_changed` event.
"""
- assert self.runstate == Runstate.IDLE
- self._set_state(Runstate.CONNECTING)
-
- # Allow runstate watchers to witness 'CONNECTING' state; some
- # failures in the streaming layer are synchronous and will not
- # otherwise yield.
- await asyncio.sleep(0)
+ if state == self._runstate:
+ return
- if accept:
- await self._do_accept(address, ssl)
- else:
- await self._do_connect(address, ssl)
+ self.logger.debug("Transitioning from '%s' to '%s'.",
+ str(self._runstate), str(state))
+ self._runstate = state
+ self._runstate_event.set()
+ self._runstate_event.clear()
- def _bind_hack(self, address: Union[str, Tuple[str, int]]) -> None:
+ @bottom_half
+ async def _stop_server(self) -> None:
+ """
+ Stop listening for / accepting new incoming connections.
"""
- Used to create a socket in advance of accept().
+ if self._server is None:
+ return
- This is a workaround to ensure that we can guarantee timing of
- precisely when a socket exists to avoid a connection attempt
- bouncing off of nothing.
+ try:
+ self.logger.debug("Stopping server.")
+ self._server.close()
+ await self._server.wait_closed()
+ self.logger.debug("Server stopped.")
+ finally:
+ self._server = None
- Python 3.7+ adds a feature to separate the server creation and
- listening phases instead, and should be used instead of this
- hack.
+ @bottom_half # However, it does not run from the R/W tasks.
+ async def _incoming(self,
+ reader: asyncio.StreamReader,
+ writer: asyncio.StreamWriter) -> None:
"""
- if isinstance(address, tuple):
- family = socket.AF_INET
- else:
- family = socket.AF_UNIX
+ Accept an incoming connection and signal the upper_half.
- sock = socket.socket(family, socket.SOCK_STREAM)
- sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ This method does the minimum necessary to accept a single
+ incoming connection. It signals back to the upper_half ASAP so
+ that any errors during session initialization can occur
+ naturally in the caller's stack.
- try:
- sock.bind(address)
- except:
- sock.close()
- raise
+ :param reader: Incoming `asyncio.StreamReader`
+ :param writer: Incoming `asyncio.StreamWriter`
+ """
+ peer = writer.get_extra_info('peername', 'Unknown peer')
+ self.logger.debug("Incoming connection from %s", peer)
+
+ if self._reader or self._writer:
+ # Sadly, we can have more than one pending connection
+ # because of https://bugs.python.org/issue46715
+ # Close any extra connections we don't actually want.
+ self.logger.warning("Extraneous connection inadvertently accepted")
+ writer.close()
+ return
- self._sock = sock
+ # A connection has been accepted; stop listening for new ones.
+ assert self._accepted is not None
+ await self._stop_server()
+ self._reader, self._writer = (reader, writer)
+ self._accepted.set()
@upper_half
- async def _do_accept(self, address: SocketAddrT,
- ssl: Optional[SSLContext] = None) -> None:
+ async def _do_start_server(self, address: SocketAddrT,
+ ssl: Optional[SSLContext] = None) -> None:
"""
- Acting as the transport server, accept a single connection.
+ Start listening for an incoming connection, but do not wait for a peer.
+
+ This method starts listening for an incoming connection, but does not
+ block waiting for a peer. This call will return immediately after
+ binding and listening to a socket. A later call to accept() must be
+ made in order to finalize the incoming connection.
:param address:
Address to listen on; UNIX socket path or TCP address/port.
@@ -471,52 +548,54 @@ class AsyncProtocol(Generic[T]):
:raise OSError: For stream-related errors.
"""
- self.logger.debug("Awaiting connection on %s ...", address)
- connected = asyncio.Event()
- server: Optional[asyncio.AbstractServer] = None
-
- async def _client_connected_cb(reader: asyncio.StreamReader,
- writer: asyncio.StreamWriter) -> None:
- """Used to accept a single incoming connection, see below."""
- nonlocal server
- nonlocal connected
-
- # A connection has been accepted; stop listening for new ones.
- assert server is not None
- server.close()
- await server.wait_closed()
- server = None
-
- # Register this client as being connected
- self._reader, self._writer = (reader, writer)
+ assert self.runstate == Runstate.IDLE
+ self._set_state(Runstate.CONNECTING)
- # Signal back: We've accepted a client!
- connected.set()
+ self.logger.debug("Awaiting connection on %s ...", address)
+ self._accepted = asyncio.Event()
if isinstance(address, tuple):
coro = asyncio.start_server(
- _client_connected_cb,
- host=None if self._sock else address[0],
- port=None if self._sock else address[1],
+ self._incoming,
+ host=address[0],
+ port=address[1],
ssl=ssl,
backlog=1,
limit=self._limit,
- sock=self._sock,
)
else:
coro = asyncio.start_unix_server(
- _client_connected_cb,
- path=None if self._sock else address,
+ self._incoming,
+ path=address,
ssl=ssl,
backlog=1,
limit=self._limit,
- sock=self._sock,
)
- server = await coro # Starts listening
- await connected.wait() # Waits for the callback to fire (and finish)
- assert server is None
- self._sock = None
+ # Allow runstate watchers to witness 'CONNECTING' state; some
+ # failures in the streaming layer are synchronous and will not
+ # otherwise yield.
+ await asyncio.sleep(0)
+
+ # This will start the server (bind(2), listen(2)). It will also
+ # call accept(2) if we yield, but we don't block on that here.
+ self._server = await coro
+ self.logger.debug("Server listening on %s", address)
+
+ @upper_half
+ async def _do_accept(self) -> None:
+ """
+ Wait for and accept an incoming connection.
+
+ Requires that we have not yet accepted an incoming connection
+ from the upper_half, but it's OK if the server is no longer
+ running because the bottom_half has already accepted the
+ connection.
+ """
+ assert self._accepted is not None
+ await self._accepted.wait()
+ assert self._server is None
+ self._accepted = None
self.logger.debug("Connection accepted.")
@@ -532,6 +611,14 @@ class AsyncProtocol(Generic[T]):
:raise OSError: For stream-related errors.
"""
+ assert self.runstate == Runstate.IDLE
+ self._set_state(Runstate.CONNECTING)
+
+ # Allow runstate watchers to witness 'CONNECTING' state; some
+ # failures in the streaming layer are synchronous and will not
+ # otherwise yield.
+ await asyncio.sleep(0)
+
self.logger.debug("Connecting to %s ...", address)
if isinstance(address, tuple):
@@ -644,6 +731,7 @@ class AsyncProtocol(Generic[T]):
self._reader = None
self._writer = None
+ self._accepted = None
# NB: _runstate_changed cannot be cleared because we still need it to
# send the final runstate changed event ...!
@@ -667,6 +755,9 @@ class AsyncProtocol(Generic[T]):
def _done(task: Optional['asyncio.Future[Any]']) -> bool:
return task is not None and task.done()
+ # If the server is running, stop it.
+ await self._stop_server()
+
# Are we already in an error pathway? If either of the tasks are
# already done, or if we have no tasks but a reader/writer; we
# must be.
diff --git a/python/tests/protocol.py b/python/tests/protocol.py
index 5cd7938be3..d6849ad306 100644
--- a/python/tests/protocol.py
+++ b/python/tests/protocol.py
@@ -41,12 +41,25 @@ class NullProtocol(AsyncProtocol[None]):
self.trigger_input = asyncio.Event()
await super()._establish_session()
- async def _do_accept(self, address, ssl=None):
- if not self.fake_session:
- await super()._do_accept(address, ssl)
+ async def _do_start_server(self, address, ssl=None):
+ if self.fake_session:
+ self._accepted = asyncio.Event()
+ self._set_state(Runstate.CONNECTING)
+ await asyncio.sleep(0)
+ else:
+ await super()._do_start_server(address, ssl)
+
+ async def _do_accept(self):
+ if self.fake_session:
+ self._accepted = None
+ else:
+ await super()._do_accept()
async def _do_connect(self, address, ssl=None):
- if not self.fake_session:
+ if self.fake_session:
+ self._set_state(Runstate.CONNECTING)
+ await asyncio.sleep(0)
+ else:
await super()._do_connect(address, ssl)
async def _do_recv(self) -> None:
@@ -413,14 +426,14 @@ class Accept(Connect):
assert family in ('INET', 'UNIX')
if family == 'INET':
- await self.proto.accept(('example.com', 1))
+ await self.proto.start_server_and_accept(('example.com', 1))
elif family == 'UNIX':
- await self.proto.accept('/dev/null')
+ await self.proto.start_server_and_accept('/dev/null')
async def _hanging_connection(self):
with TemporaryDirectory(suffix='.aqmp') as tmpdir:
sock = os.path.join(tmpdir, type(self.proto).__name__ + ".sock")
- await self.proto.accept(sock)
+ await self.proto.start_server_and_accept(sock)
class FakeSession(TestBase):
@@ -449,13 +462,13 @@ class FakeSession(TestBase):
@TestBase.async_test
async def testFakeAccept(self):
"""Test the full state lifecycle (via accept) with a no-op session."""
- await self.proto.accept('/not/a/real/path')
+ await self.proto.start_server_and_accept('/not/a/real/path')
self.assertEqual(self.proto.runstate, Runstate.RUNNING)
@TestBase.async_test
async def testFakeRecv(self):
"""Test receiving a fake/null message."""
- await self.proto.accept('/not/a/real/path')
+ await self.proto.start_server_and_accept('/not/a/real/path')
logname = self.proto.logger.name
with self.assertLogs(logname, level='DEBUG') as context:
@@ -471,7 +484,7 @@ class FakeSession(TestBase):
@TestBase.async_test
async def testFakeSend(self):
"""Test sending a fake/null message."""
- await self.proto.accept('/not/a/real/path')
+ await self.proto.start_server_and_accept('/not/a/real/path')
logname = self.proto.logger.name
with self.assertLogs(logname, level='DEBUG') as context:
@@ -493,7 +506,7 @@ class FakeSession(TestBase):
):
with self.assertRaises(StateError) as context:
if accept:
- await self.proto.accept('/not/a/real/path')
+ await self.proto.start_server_and_accept('/not/a/real/path')
else:
await self.proto.connect('/not/a/real/path')
@@ -504,7 +517,7 @@ class FakeSession(TestBase):
@TestBase.async_test
async def testAcceptRequireRunning(self):
"""Test that accept() cannot be called when Runstate=RUNNING"""
- await self.proto.accept('/not/a/real/path')
+ await self.proto.start_server_and_accept('/not/a/real/path')
await self._prod_session_api(
Runstate.RUNNING,
@@ -515,7 +528,7 @@ class FakeSession(TestBase):
@TestBase.async_test
async def testConnectRequireRunning(self):
"""Test that connect() cannot be called when Runstate=RUNNING"""
- await self.proto.accept('/not/a/real/path')
+ await self.proto.start_server_and_accept('/not/a/real/path')
await self._prod_session_api(
Runstate.RUNNING,
@@ -526,7 +539,7 @@ class FakeSession(TestBase):
@TestBase.async_test
async def testAcceptRequireDisconnecting(self):
"""Test that accept() cannot be called when Runstate=DISCONNECTING"""
- await self.proto.accept('/not/a/real/path')
+ await self.proto.start_server_and_accept('/not/a/real/path')
# Cheat: force a disconnect.
await self.proto.simulate_disconnect()
@@ -541,7 +554,7 @@ class FakeSession(TestBase):
@TestBase.async_test
async def testConnectRequireDisconnecting(self):
"""Test that connect() cannot be called when Runstate=DISCONNECTING"""
- await self.proto.accept('/not/a/real/path')
+ await self.proto.start_server_and_accept('/not/a/real/path')
# Cheat: force a disconnect.
await self.proto.simulate_disconnect()
@@ -576,7 +589,7 @@ class SimpleSession(TestBase):
async def testSmoke(self):
with TemporaryDirectory(suffix='.aqmp') as tmpdir:
sock = os.path.join(tmpdir, type(self.proto).__name__ + ".sock")
- server_task = create_task(self.server.accept(sock))
+ server_task = create_task(self.server.start_server_and_accept(sock))
# give the server a chance to start listening [...]
await asyncio.sleep(0)
diff --git a/qemu-img.c b/qemu-img.c
index 6fe2466032..5dffb3e616 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -42,6 +42,7 @@
#include "qemu/module.h"
#include "qemu/sockets.h"
#include "qemu/units.h"
+#include "qemu/memalign.h"
#include "qom/object_interfaces.h"
#include "sysemu/block-backend.h"
#include "block/block_int.h"
diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c
index 45a9570933..2f0d8ac25a 100644
--- a/qemu-io-cmds.c
+++ b/qemu-io-cmds.c
@@ -21,6 +21,7 @@
#include "qemu/option.h"
#include "qemu/timer.h"
#include "qemu/cutils.h"
+#include "qemu/memalign.h"
#define CMD_NOFILE_OK 0x01
diff --git a/qemu-options.hx b/qemu-options.hx
index 094a6c1d7c..5ce0ada75e 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2537,6 +2537,7 @@ DEF("smbios", HAS_ARG, QEMU_OPTION_smbios,
" specify SMBIOS type 3 fields\n"
"-smbios type=4[,sock_pfx=str][,manufacturer=str][,version=str][,serial=str]\n"
" [,asset=str][,part=str][,max-speed=%d][,current-speed=%d]\n"
+ " [,processor-id=%d]\n"
" specify SMBIOS type 4 fields\n"
"-smbios type=11[,value=str][,path=filename]\n"
" specify SMBIOS type 11 fields\n"
@@ -2562,7 +2563,7 @@ SRST
``-smbios type=3[,manufacturer=str][,version=str][,serial=str][,asset=str][,sku=str]``
Specify SMBIOS type 3 fields
-``-smbios type=4[,sock_pfx=str][,manufacturer=str][,version=str][,serial=str][,asset=str][,part=str]``
+``-smbios type=4[,sock_pfx=str][,manufacturer=str][,version=str][,serial=str][,asset=str][,part=str][,processor-id=%d]``
Specify SMBIOS type 4 fields
``-smbios type=11[,value=str][,path=filename]``
diff --git a/qom/object.c b/qom/object.c
index 9f7a33139d..d34608558e 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -16,6 +16,7 @@
#include "qom/object.h"
#include "qom/object_interfaces.h"
#include "qemu/cutils.h"
+#include "qemu/memalign.h"
#include "qapi/visitor.h"
#include "qapi/string-input-visitor.h"
#include "qapi/string-output-visitor.h"
@@ -1167,10 +1168,14 @@ GSList *object_class_get_list_sorted(const char *implements_type,
Object *object_ref(void *objptr)
{
Object *obj = OBJECT(objptr);
+ uint32_t ref;
+
if (!obj) {
return NULL;
}
- qatomic_inc(&obj->ref);
+ ref = qatomic_fetch_inc(&obj->ref);
+ /* Assert waaay before the integer overflows */
+ g_assert(ref < INT_MAX);
return obj;
}
diff --git a/roms/seabios b/roms/seabios
-Subproject 6a62e0cb0dfe9cd28b70547dbea5caf76847c3a
+Subproject d239552ce7220e448ae81f41515138f7b9e3c4d
diff --git a/scripts/qmp/qmp-shell-wrap b/scripts/qmp/qmp-shell-wrap
index 9e94da114f..66846e36d1 100755
--- a/scripts/qmp/qmp-shell-wrap
+++ b/scripts/qmp/qmp-shell-wrap
@@ -4,7 +4,7 @@ import os
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
-from qemu.qmp import qmp_shell
+from qemu.aqmp import qmp_shell
if __name__ == '__main__':
diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh
index fe850763c5..839a5ec614 100755
--- a/scripts/update-linux-headers.sh
+++ b/scripts/update-linux-headers.sh
@@ -214,7 +214,8 @@ for i in "$tmpdir"/include/linux/*virtio*.h \
"$tmpdir/include/linux/const.h" \
"$tmpdir/include/linux/kernel.h" \
"$tmpdir/include/linux/vhost_types.h" \
- "$tmpdir/include/linux/sysinfo.h"; do
+ "$tmpdir/include/linux/sysinfo.h" \
+ "$tmpdir/include/misc/pvpanic.h"; do
cp_portable "$i" "$output/include/standard-headers/linux"
done
mkdir -p "$output/include/standard-headers/drm"
diff --git a/softmmu/arch_init.c b/softmmu/arch_init.c
index 8919405c7b..79716f959b 100644
--- a/softmmu/arch_init.c
+++ b/softmmu/arch_init.c
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
+#include "qemu/module.h"
#include "sysemu/arch_init.h"
#ifdef TARGET_SPARC
@@ -39,3 +40,11 @@ int graphic_depth = 32;
#endif
const uint32_t arch_type = QEMU_ARCH;
+
+void qemu_init_arch_modules(void)
+{
+#ifdef CONFIG_MODULES
+ module_init_info(qemu_modinfo);
+ module_allow_arch(TARGET_NAME);
+#endif
+}
diff --git a/softmmu/cpu-timers.c b/softmmu/cpu-timers.c
index 34ddfa02f1..204d946a17 100644
--- a/softmmu/cpu-timers.c
+++ b/softmmu/cpu-timers.c
@@ -28,7 +28,6 @@
#include "migration/vmstate.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
-#include "exec/exec-all.h"
#include "sysemu/cpus.h"
#include "qemu/main-loop.h"
#include "qemu/option.h"
diff --git a/softmmu/cpus.c b/softmmu/cpus.c
index 1681844b61..e1d84c8ccb 100644
--- a/softmmu/cpus.c
+++ b/softmmu/cpus.c
@@ -33,7 +33,7 @@
#include "qapi/qmp/qerror.h"
#include "exec/gdbstub.h"
#include "sysemu/hw_accel.h"
-#include "exec/exec-all.h"
+#include "exec/cpu-common.h"
#include "qemu/thread.h"
#include "qemu/plugin.h"
#include "sysemu/cpus.h"
@@ -67,6 +67,11 @@
static QemuMutex qemu_global_mutex;
+/*
+ * The chosen accelerator is supposed to register this.
+ */
+static const AccelOpsClass *cpus_accel;
+
bool cpu_is_stopped(CPUState *cpu)
{
return cpu->stopped || !runstate_is_running();
@@ -85,10 +90,12 @@ bool cpu_thread_is_idle(CPUState *cpu)
if (cpu_is_stopped(cpu)) {
return true;
}
- if (!cpu->halted || cpu_has_work(cpu) ||
- kvm_halt_in_kernel() || whpx_apic_in_platform()) {
+ if (!cpu->halted || cpu_has_work(cpu)) {
return false;
}
+ if (cpus_accel->cpu_thread_is_idle) {
+ return cpus_accel->cpu_thread_is_idle(cpu);
+ }
return true;
}
@@ -122,11 +129,6 @@ void hw_error(const char *fmt, ...)
abort();
}
-/*
- * The chosen accelerator is supposed to register this.
- */
-static const AccelOpsClass *cpus_accel;
-
void cpu_synchronize_all_states(void)
{
CPUState *cpu;
@@ -193,7 +195,10 @@ void cpu_synchronize_pre_loadvm(CPUState *cpu)
bool cpus_are_resettable(void)
{
- return cpu_check_are_resettable();
+ if (cpus_accel->cpus_are_resettable) {
+ return cpus_accel->cpus_are_resettable();
+ }
+ return true;
}
int64_t cpus_get_virtual_clock(void)
diff --git a/softmmu/globals.c b/softmmu/globals.c
index 7d0fc81183..3ebd718e35 100644
--- a/softmmu/globals.c
+++ b/softmmu/globals.c
@@ -25,8 +25,6 @@
#include "qemu/osdep.h"
#include "exec/cpu-common.h"
#include "hw/display/vga.h"
-#include "hw/i386/pc.h"
-#include "hw/i386/x86.h"
#include "hw/loader.h"
#include "hw/xen/xen.h"
#include "net/net.h"
diff --git a/softmmu/memory_mapping.c b/softmmu/memory_mapping.c
index a62eaa49cc..8320165ea2 100644
--- a/softmmu/memory_mapping.c
+++ b/softmmu/memory_mapping.c
@@ -17,6 +17,7 @@
#include "sysemu/memory_mapping.h"
#include "exec/memory.h"
#include "exec/address-spaces.h"
+#include "hw/core/cpu.h"
//#define DEBUG_GUEST_PHYS_REGION_ADD
diff --git a/softmmu/meson.build b/softmmu/meson.build
index 39f766ce7c..8138248661 100644
--- a/softmmu/meson.build
+++ b/softmmu/meson.build
@@ -1,20 +1,9 @@
specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files(
'arch_init.c',
- 'balloon.c',
- 'cpus.c',
- 'cpu-throttle.c',
- 'datadir.c',
- 'globals.c',
- 'physmem.c',
'ioport.c',
- 'rtc.c',
- 'runstate.c',
'memory.c',
- 'memory_mapping.c',
+ 'physmem.c',
'qtest.c',
- 'vl.c',
- 'cpu-timers.c',
- 'runstate-action.c',
)])
specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: [files(
@@ -22,9 +11,20 @@ specific_ss.add(when: ['CONFIG_SOFTMMU', 'CONFIG_TCG'], if_true: [files(
)])
softmmu_ss.add(files(
+ 'balloon.c',
'bootdevice.c',
+ 'cpus.c',
+ 'cpu-throttle.c',
+ 'cpu-timers.c',
+ 'datadir.c',
'dma-helpers.c',
+ 'globals.c',
+ 'memory_mapping.c',
'qdev-monitor.c',
+ 'rtc.c',
+ 'runstate-action.c',
+ 'runstate.c',
+ 'vl.c',
), sdl, libpmem, libdaxctl)
if have_tpm
diff --git a/softmmu/physmem.c b/softmmu/physmem.c
index a13289a594..43ae70fbe2 100644
--- a/softmmu/physmem.c
+++ b/softmmu/physmem.c
@@ -42,6 +42,7 @@
#include "qemu/config-file.h"
#include "qemu/error-report.h"
#include "qemu/qemu-print.h"
+#include "qemu/memalign.h"
#include "exec/memory.h"
#include "exec/ioport.h"
#include "sysemu/dma.h"
@@ -61,7 +62,6 @@
#include "exec/memory-internal.h"
#include "exec/ram_addr.h"
-#include "exec/log.h"
#include "qemu/pmem.h"
@@ -3436,11 +3436,11 @@ address_space_write_cached_slow(MemoryRegionCache *cache, hwaddr addr,
#include "memory_ldst.c.inc"
/* virtual memory access for debug (includes writing to ROM) */
-int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
- void *ptr, target_ulong len, bool is_write)
+int cpu_memory_rw_debug(CPUState *cpu, vaddr addr,
+ void *ptr, size_t len, bool is_write)
{
hwaddr phys_addr;
- target_ulong l, page;
+ vaddr l, page;
uint8_t *buf = ptr;
cpu_synchronize_state(cpu);
diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c
index fe6cf268ff..12fe60c467 100644
--- a/softmmu/qdev-monitor.c
+++ b/softmmu/qdev-monitor.c
@@ -1038,6 +1038,13 @@ int qemu_global_option(const char *str)
if (!opts) {
return -1;
}
+ if (!qemu_opt_get(opts, "driver")
+ || !qemu_opt_get(opts, "property")
+ || !qemu_opt_get(opts, "value")) {
+ error_report("options 'driver', 'property', and 'value'"
+ " are required");
+ return -1;
+ }
return 0;
}
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 1fe028800f..0b81f61535 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -2815,10 +2815,7 @@ void qemu_init(int argc, char **argv, char **envp)
error_init(argv[0]);
qemu_init_exec_dir(argv[0]);
-#ifdef CONFIG_MODULES
- module_init_info(qemu_modinfo);
- module_allow_arch(TARGET_NAME);
-#endif
+ qemu_init_arch_modules();
qemu_init_subsystems();
diff --git a/target/alpha/cpu-qom.h b/target/alpha/cpu-qom.h
index 7bb9173c57..1f200724b6 100644
--- a/target/alpha/cpu-qom.h
+++ b/target/alpha/cpu-qom.h
@@ -25,8 +25,7 @@
#define TYPE_ALPHA_CPU "alpha-cpu"
-OBJECT_DECLARE_TYPE(AlphaCPU, AlphaCPUClass,
- ALPHA_CPU)
+OBJECT_DECLARE_CPU_TYPE(AlphaCPU, AlphaCPUClass, ALPHA_CPU)
/**
* AlphaCPUClass:
diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h
index e819211503..58f00b7814 100644
--- a/target/alpha/cpu.h
+++ b/target/alpha/cpu.h
@@ -197,9 +197,7 @@ enum {
#define MMU_USER_IDX 1
#define MMU_PHYS_IDX 2
-typedef struct CPUAlphaState CPUAlphaState;
-
-struct CPUAlphaState {
+typedef struct CPUArchState {
uint64_t ir[31];
float64 fir[31];
uint64_t pc;
@@ -251,7 +249,7 @@ struct CPUAlphaState {
uint32_t features;
uint32_t amask;
int implver;
-};
+} CPUAlphaState;
/**
* AlphaCPU:
@@ -259,7 +257,7 @@ struct CPUAlphaState {
*
* An Alpha CPU.
*/
-struct AlphaCPU {
+struct ArchCPU {
/*< private >*/
CPUState parent_obj;
/*< public >*/
@@ -285,9 +283,6 @@ int alpha_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
#define cpu_list alpha_cpu_list
-typedef CPUAlphaState CPUArchState;
-typedef AlphaCPU ArchCPU;
-
#include "exec/cpu-all.h"
enum {
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index ca78a0faed..66768ab47a 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -20,7 +20,6 @@
#include "qemu/osdep.h"
#include "cpu.h"
#include "sysemu/cpus.h"
-#include "sysemu/cpu-timers.h"
#include "disas/disas.h"
#include "qemu/host-utils.h"
#include "exec/exec-all.h"
diff --git a/target/arm/cpu-qom.h b/target/arm/cpu-qom.h
index a22bd506d0..64c44cef2d 100644
--- a/target/arm/cpu-qom.h
+++ b/target/arm/cpu-qom.h
@@ -27,8 +27,7 @@ struct arm_boot_info;
#define TYPE_ARM_CPU "arm-cpu"
-OBJECT_DECLARE_TYPE(ARMCPU, ARMCPUClass,
- ARM_CPU)
+OBJECT_DECLARE_CPU_TYPE(ARMCPU, ARMCPUClass, ARM_CPU)
#define TYPE_ARM_MAX_CPU "max-" TYPE_ARM_CPU
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 7091684a16..185d4e774d 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1392,6 +1392,12 @@ void arm_cpu_finalize_features(ARMCPU *cpu, Error **errp)
error_propagate(errp, local_err);
return;
}
+
+ arm_cpu_lpa2_finalize(cpu, &local_err);
+ if (local_err != NULL) {
+ error_propagate(errp, local_err);
+ return;
+ }
}
if (kvm_enabled()) {
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 24d9fff170..157f214cce 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -204,10 +204,12 @@ typedef struct {
# define ARM_MAX_VQ 16
void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp);
void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp);
+void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp);
#else
# define ARM_MAX_VQ 1
static inline void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) { }
static inline void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp) { }
+static inline void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp) { }
#endif
typedef struct ARMVectorReg {
@@ -232,7 +234,7 @@ typedef struct CPUARMTBFlags {
target_ulong flags2;
} CPUARMTBFlags;
-typedef struct CPUARMState {
+typedef struct CPUArchState {
/* Regs for current mode. */
uint32_t regs[16];
@@ -774,7 +776,7 @@ typedef struct ARMISARegisters ARMISARegisters;
*
* An ARM CPU core.
*/
-struct ARMCPU {
+struct ArchCPU {
/*< private >*/
CPUState parent_obj;
/*< public >*/
@@ -975,10 +977,11 @@ struct ARMCPU {
/*
* Intermediate values used during property parsing.
- * Once finalized, the values should be read from ID_AA64ISAR1.
+ * Once finalized, the values should be read from ID_AA64*.
*/
bool prop_pauth;
bool prop_pauth_impdef;
+ bool prop_lpa2;
/* DCZ blocksize, in log_2(words), ie low 4 bits of DCZID_EL0 */
uint32_t dcz_blocksize;
@@ -3410,9 +3413,6 @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
}
}
-typedef CPUARMState CPUArchState;
-typedef ARMCPU ArchCPU;
-
#include "exec/cpu-all.h"
/*
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 2fdc16bf18..eb44c05822 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -688,6 +688,29 @@ void aarch64_add_pauth_properties(Object *obj)
}
}
+static Property arm_cpu_lpa2_property =
+ DEFINE_PROP_BOOL("lpa2", ARMCPU, prop_lpa2, true);
+
+void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp)
+{
+ uint64_t t;
+
+ /*
+ * We only install the property for tcg -cpu max; this is the
+ * only situation in which the cpu field can be true.
+ */
+ if (!cpu->prop_lpa2) {
+ return;
+ }
+
+ t = cpu->isar.id_aa64mmfr0;
+ t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16, 2); /* 16k pages w/ LPA2 */
+ t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4, 1); /* 4k pages w/ LPA2 */
+ t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN16_2, 3); /* 16k stage2 w/ LPA2 */
+ t = FIELD_DP64(t, ID_AA64MMFR0, TGRAN4_2, 3); /* 4k stage2 w/ LPA2 */
+ cpu->isar.id_aa64mmfr0 = t;
+}
+
static void aarch64_host_initfn(Object *obj)
{
#if defined(CONFIG_KVM)
@@ -897,6 +920,7 @@ static void aarch64_max_initfn(Object *obj)
aarch64_add_sve_properties(obj);
object_property_add(obj, "sve-max-vq", "uint32", cpu_max_get_sve_max_vq,
cpu_max_set_sve_max_vq, NULL, NULL);
+ qdev_property_add_static(DEVICE(obj), &arm_cpu_lpa2_property);
}
static void aarch64_a64fx_initfn(Object *obj)
diff --git a/target/arm/hvf_arm.h b/target/arm/hvf_arm.h
index ea238cff83..9a9d1a0bf5 100644
--- a/target/arm/hvf_arm.h
+++ b/target/arm/hvf_arm.h
@@ -13,6 +13,6 @@
#include "cpu.h"
-void hvf_arm_set_cpu_features_from_host(struct ARMCPU *cpu);
+void hvf_arm_set_cpu_features_from_host(ARMCPU *cpu);
#endif
diff --git a/target/arm/translate-neon.c b/target/arm/translate-neon.c
index 3854dd3516..384604c009 100644
--- a/target/arm/translate-neon.c
+++ b/target/arm/translate-neon.c
@@ -657,21 +657,24 @@ static bool trans_VLDST_single(DisasContext *s, arg_VLDST_single *a)
/* Catch the UNDEF cases. This is unavoidably a bit messy. */
switch (nregs) {
case 1:
+ if (a->stride != 1) {
+ return false;
+ }
if (((a->align & (1 << a->size)) != 0) ||
(a->size == 2 && (a->align == 1 || a->align == 2))) {
return false;
}
break;
- case 3:
- if ((a->align & 1) != 0) {
- return false;
- }
- /* fall through */
case 2:
if (a->size == 2 && (a->align & 2) != 0) {
return false;
}
break;
+ case 3:
+ if (a->align != 0) {
+ return false;
+ }
+ break;
case 4:
if (a->size == 2 && a->align == 3) {
return false;
diff --git a/target/avr/cpu-qom.h b/target/avr/cpu-qom.h
index 14e5b3ce72..32a1c762e6 100644
--- a/target/avr/cpu-qom.h
+++ b/target/avr/cpu-qom.h
@@ -26,8 +26,7 @@
#define TYPE_AVR_CPU "avr-cpu"
-OBJECT_DECLARE_TYPE(AVRCPU, AVRCPUClass,
- AVR_CPU)
+OBJECT_DECLARE_CPU_TYPE(AVRCPU, AVRCPUClass, AVR_CPU)
/**
* AVRCPUClass:
diff --git a/target/avr/cpu.h b/target/avr/cpu.h
index dceacf3cd7..55497f851d 100644
--- a/target/avr/cpu.h
+++ b/target/avr/cpu.h
@@ -108,9 +108,7 @@ typedef enum AVRFeature {
AVR_FEATURE_RAMPZ,
} AVRFeature;
-typedef struct CPUAVRState CPUAVRState;
-
-struct CPUAVRState {
+typedef struct CPUArchState {
uint32_t pc_w; /* 0x003fffff up to 22 bits */
uint32_t sregC; /* 0x00000001 1 bit */
@@ -137,7 +135,7 @@ struct CPUAVRState {
bool fullacc; /* CPU/MEM if true MEM only otherwise */
uint64_t features;
-};
+} CPUAVRState;
/**
* AVRCPU:
@@ -145,14 +143,14 @@ struct CPUAVRState {
*
* A AVR CPU.
*/
-typedef struct AVRCPU {
+struct ArchCPU {
/*< private >*/
CPUState parent_obj;
/*< public >*/
CPUNegativeOffsetState neg;
CPUAVRState env;
-} AVRCPU;
+};
extern const struct VMStateDescription vms_avr_cpu;
@@ -247,9 +245,6 @@ bool avr_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr);
-typedef CPUAVRState CPUArchState;
-typedef AVRCPU ArchCPU;
-
#include "exec/cpu-all.h"
#endif /* !defined (QEMU_AVR_CPU_H) */
diff --git a/target/cris/cpu-qom.h b/target/cris/cpu-qom.h
index 2596edc7e3..71e8af0e70 100644
--- a/target/cris/cpu-qom.h
+++ b/target/cris/cpu-qom.h
@@ -25,8 +25,7 @@
#define TYPE_CRIS_CPU "cris-cpu"
-OBJECT_DECLARE_TYPE(CRISCPU, CRISCPUClass,
- CRIS_CPU)
+OBJECT_DECLARE_CPU_TYPE(CRISCPU, CRISCPUClass, CRIS_CPU)
/**
* CRISCPUClass:
diff --git a/target/cris/cpu.h b/target/cris/cpu.h
index b445b194ea..e6776f25b1 100644
--- a/target/cris/cpu.h
+++ b/target/cris/cpu.h
@@ -105,7 +105,7 @@ typedef struct {
uint32_t lo;
} TLBSet;
-typedef struct CPUCRISState {
+typedef struct CPUArchState {
uint32_t regs[16];
/* P0 - P15 are referred to as special registers in the docs. */
uint32_t pregs[16];
@@ -173,7 +173,7 @@ typedef struct CPUCRISState {
*
* A CRIS CPU.
*/
-struct CRISCPU {
+struct ArchCPU {
/*< private >*/
CPUState parent_obj;
/*< public >*/
@@ -265,9 +265,6 @@ static inline int cpu_mmu_index (CPUCRISState *env, bool ifetch)
#define SFR_RW_MM_TLB_LO env->pregs[PR_SRS]][5
#define SFR_RW_MM_TLB_HI env->pregs[PR_SRS]][6
-typedef CPUCRISState CPUArchState;
-typedef CRISCPU ArchCPU;
-
#include "exec/cpu-all.h"
static inline void cpu_get_tb_cpu_state(CPUCRISState *env, target_ulong *pc,
diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 58a0d3870b..2a65a57bab 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -1,5 +1,5 @@
/*
- * Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ * Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,14 +18,13 @@
#ifndef HEXAGON_CPU_H
#define HEXAGON_CPU_H
-/* Forward declaration needed by some of the header files */
-typedef struct CPUHexagonState CPUHexagonState;
-
#include "fpu/softfloat-types.h"
#include "exec/cpu-defs.h"
#include "hex_regs.h"
#include "mmvec/mmvec.h"
+#include "qom/object.h"
+#include "hw/core/cpu.h"
#define NUM_PREGS 4
#define TOTAL_PER_THREAD_REGS 64
@@ -75,7 +74,7 @@ typedef struct {
/* Maximum number of vector temps in a packet */
#define VECTOR_TEMPS_MAX 4
-struct CPUHexagonState {
+typedef struct CPUArchState {
target_ulong gpr[TOTAL_PER_THREAD_REGS];
target_ulong pred[NUM_PREGS];
target_ulong branch_taken;
@@ -129,14 +128,9 @@ struct CPUHexagonState {
target_ulong vstore_pending[VSTORES_MAX];
bool vtcm_pending;
VTCMStoreLog vtcm_log;
-};
+} CPUHexagonState;
-#define HEXAGON_CPU_CLASS(klass) \
- OBJECT_CLASS_CHECK(HexagonCPUClass, (klass), TYPE_HEXAGON_CPU)
-#define HEXAGON_CPU(obj) \
- OBJECT_CHECK(HexagonCPU, (obj), TYPE_HEXAGON_CPU)
-#define HEXAGON_CPU_GET_CLASS(obj) \
- OBJECT_GET_CLASS(HexagonCPUClass, (obj), TYPE_HEXAGON_CPU)
+OBJECT_DECLARE_CPU_TYPE(HexagonCPU, HexagonCPUClass, HEXAGON_CPU)
typedef struct HexagonCPUClass {
/*< private >*/
@@ -146,7 +140,7 @@ typedef struct HexagonCPUClass {
DeviceReset parent_reset;
} HexagonCPUClass;
-typedef struct HexagonCPU {
+struct ArchCPU {
/*< private >*/
CPUState parent_obj;
/*< public >*/
@@ -155,7 +149,7 @@ typedef struct HexagonCPU {
bool lldb_compat;
target_ulong lldb_stack_adjust;
-} HexagonCPU;
+};
#include "cpu_bits.h"
@@ -180,7 +174,6 @@ static inline int cpu_mmu_index(CPUHexagonState *env, bool ifetch)
#endif
}
-typedef struct CPUHexagonState CPUArchState;
typedef HexagonCPU ArchCPU;
void hexagon_translate_init(void);
diff --git a/target/hppa/cpu-qom.h b/target/hppa/cpu-qom.h
index d424f88370..b96e0318c7 100644
--- a/target/hppa/cpu-qom.h
+++ b/target/hppa/cpu-qom.h
@@ -25,8 +25,7 @@
#define TYPE_HPPA_CPU "hppa-cpu"
-OBJECT_DECLARE_TYPE(HPPACPU, HPPACPUClass,
- HPPA_CPU)
+OBJECT_DECLARE_CPU_TYPE(HPPACPU, HPPACPUClass, HPPA_CPU)
/**
* HPPACPUClass:
diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h
index 93c119532a..4cc936b6bf 100644
--- a/target/hppa/cpu.h
+++ b/target/hppa/cpu.h
@@ -138,8 +138,6 @@
#define CR_IPSW 22
#define CR_EIRR 23
-typedef struct CPUHPPAState CPUHPPAState;
-
#if TARGET_REGISTER_BITS == 32
typedef uint32_t target_ureg;
typedef int32_t target_sreg;
@@ -168,7 +166,7 @@ typedef struct {
unsigned access_id : 16;
} hppa_tlb_entry;
-struct CPUHPPAState {
+typedef struct CPUArchState {
target_ureg gr[32];
uint64_t fr[32];
uint64_t sr[8]; /* stored shifted into place for gva */
@@ -207,7 +205,7 @@ struct CPUHPPAState {
/* ??? We should use a more intelligent data structure. */
hppa_tlb_entry tlb[HPPA_TLB_ENTRIES];
uint32_t tlb_last;
-};
+} CPUHPPAState;
/**
* HPPACPU:
@@ -215,7 +213,7 @@ struct CPUHPPAState {
*
* An HPPA CPU.
*/
-struct HPPACPU {
+struct ArchCPU {
/*< private >*/
CPUState parent_obj;
/*< public >*/
@@ -225,10 +223,6 @@ struct HPPACPU {
QEMUTimer *alarm_timer;
};
-
-typedef CPUHPPAState CPUArchState;
-typedef HPPACPU ArchCPU;
-
#include "exec/cpu-all.h"
static inline int cpu_mmu_index(CPUHPPAState *env, bool ifetch)
diff --git a/target/i386/cpu-qom.h b/target/i386/cpu-qom.h
index f9923cee04..c557a522e1 100644
--- a/target/i386/cpu-qom.h
+++ b/target/i386/cpu-qom.h
@@ -30,8 +30,7 @@
#define TYPE_X86_CPU "i386-cpu"
#endif
-OBJECT_DECLARE_TYPE(X86CPU, X86CPUClass,
- X86_CPU)
+OBJECT_DECLARE_CPU_TYPE(X86CPU, X86CPUClass, X86_CPU)
typedef struct X86CPUModel X86CPUModel;
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index e69ab5dd78..e11734ba86 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1431,7 +1431,7 @@ typedef struct HVFX86LazyFlags {
target_ulong auxbits;
} HVFX86LazyFlags;
-typedef struct CPUX86State {
+typedef struct CPUArchState {
/* standard registers */
target_ulong regs[CPU_NB_REGS];
target_ulong eip;
@@ -1707,7 +1707,7 @@ struct kvm_msrs;
*
* An x86 CPU.
*/
-struct X86CPU {
+struct ArchCPU {
/*< private >*/
CPUState parent_obj;
/*< public >*/
@@ -2074,9 +2074,6 @@ static inline int cpu_mmu_index_kernel(CPUX86State *env)
#define CC_SRC2 (env->cc_src2)
#define CC_OP (env->cc_op)
-typedef CPUX86State CPUArchState;
-typedef X86CPU ArchCPU;
-
#include "exec/cpu-all.h"
#include "svm.h"
diff --git a/target/i386/hax/hax-all.c b/target/i386/hax/hax-all.c
index bf65ed6fa9..81f665e212 100644
--- a/target/i386/hax/hax-all.c
+++ b/target/i386/hax/hax-all.c
@@ -49,18 +49,13 @@ const uint32_t hax_cur_version = 0x4; /* API v4: unmapping and MMIO moves */
/* Minimum HAX kernel version */
const uint32_t hax_min_version = 0x4; /* API v4: supports unmapping */
-static bool hax_allowed;
+bool hax_allowed;
struct hax_state hax_global;
static void hax_vcpu_sync_state(CPUArchState *env, int modified);
static int hax_arch_get_registers(CPUArchState *env);
-int hax_enabled(void)
-{
- return hax_allowed;
-}
-
int valid_hax_tunnel_size(uint16_t size)
{
return size >= sizeof(struct hax_tunnel);
@@ -227,7 +222,7 @@ int hax_init_vcpu(CPUState *cpu)
cpu->hax_vcpu = hax_global.vm->vcpus[cpu->cpu_index];
cpu->vcpu_dirty = true;
- qemu_register_reset(hax_reset_vcpu_state, (CPUArchState *) (cpu->env_ptr));
+ qemu_register_reset(hax_reset_vcpu_state, cpu->env_ptr);
return ret;
}
@@ -674,7 +669,7 @@ void hax_cpu_synchronize_pre_loadvm(CPUState *cpu)
int hax_smp_cpu_exec(CPUState *cpu)
{
- CPUArchState *env = (CPUArchState *) (cpu->env_ptr);
+ CPUArchState *env = cpu->env_ptr;
int fatal;
int ret;
diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index 4ba6e82fab..fc12c02fb2 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -49,6 +49,7 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/error-report.h"
+#include "qemu/memalign.h"
#include "sysemu/hvf.h"
#include "sysemu/hvf_int.h"
diff --git a/target/i386/hvf/x86_emu.c b/target/i386/hvf/x86_emu.c
index 7c8203b21f..050428795b 100644
--- a/target/i386/hvf/x86_emu.c
+++ b/target/i386/hvf/x86_emu.c
@@ -171,12 +171,12 @@ void write_val_to_reg(target_ulong reg_ptr, target_ulong val, int size)
}
}
-static bool is_host_reg(struct CPUX86State *env, target_ulong ptr)
+static bool is_host_reg(CPUX86State *env, target_ulong ptr)
{
return (ptr - (target_ulong)&env->regs[0]) < sizeof(env->regs);
}
-void write_val_ext(struct CPUX86State *env, target_ulong ptr, target_ulong val, int size)
+void write_val_ext(CPUX86State *env, target_ulong ptr, target_ulong val, int size)
{
if (is_host_reg(env, ptr)) {
write_val_to_reg(ptr, val, size);
@@ -185,14 +185,14 @@ void write_val_ext(struct CPUX86State *env, target_ulong ptr, target_ulong val,
vmx_write_mem(env_cpu(env), ptr, &val, size);
}
-uint8_t *read_mmio(struct CPUX86State *env, target_ulong ptr, int bytes)
+uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes)
{
vmx_read_mem(env_cpu(env), env->hvf_mmio_buf, ptr, bytes);
return env->hvf_mmio_buf;
}
-target_ulong read_val_ext(struct CPUX86State *env, target_ulong ptr, int size)
+target_ulong read_val_ext(CPUX86State *env, target_ulong ptr, int size)
{
target_ulong val;
uint8_t *mmio_ptr;
@@ -222,7 +222,7 @@ target_ulong read_val_ext(struct CPUX86State *env, target_ulong ptr, int size)
return val;
}
-static void fetch_operands(struct CPUX86State *env, struct x86_decode *decode,
+static void fetch_operands(CPUX86State *env, struct x86_decode *decode,
int n, bool val_op0, bool val_op1, bool val_op2)
{
int i;
@@ -261,7 +261,7 @@ static void fetch_operands(struct CPUX86State *env, struct x86_decode *decode,
}
}
-static void exec_mov(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_mov(CPUX86State *env, struct x86_decode *decode)
{
fetch_operands(env, decode, 2, false, true, false);
write_val_ext(env, decode->op[0].ptr, decode->op[1].val,
@@ -270,49 +270,49 @@ static void exec_mov(struct CPUX86State *env, struct x86_decode *decode)
env->eip += decode->len;
}
-static void exec_add(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_add(CPUX86State *env, struct x86_decode *decode)
{
EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true);
env->eip += decode->len;
}
-static void exec_or(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_or(CPUX86State *env, struct x86_decode *decode)
{
EXEC_2OP_FLAGS_CMD(env, decode, |, SET_FLAGS_OSZAPC_LOGIC, true);
env->eip += decode->len;
}
-static void exec_adc(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_adc(CPUX86State *env, struct x86_decode *decode)
{
EXEC_2OP_FLAGS_CMD(env, decode, +get_CF(env)+, SET_FLAGS_OSZAPC_ADD, true);
env->eip += decode->len;
}
-static void exec_sbb(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_sbb(CPUX86State *env, struct x86_decode *decode)
{
EXEC_2OP_FLAGS_CMD(env, decode, -get_CF(env)-, SET_FLAGS_OSZAPC_SUB, true);
env->eip += decode->len;
}
-static void exec_and(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_and(CPUX86State *env, struct x86_decode *decode)
{
EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, true);
env->eip += decode->len;
}
-static void exec_sub(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_sub(CPUX86State *env, struct x86_decode *decode)
{
EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, true);
env->eip += decode->len;
}
-static void exec_xor(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_xor(CPUX86State *env, struct x86_decode *decode)
{
EXEC_2OP_FLAGS_CMD(env, decode, ^, SET_FLAGS_OSZAPC_LOGIC, true);
env->eip += decode->len;
}
-static void exec_neg(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_neg(CPUX86State *env, struct x86_decode *decode)
{
/*EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);*/
int32_t val;
@@ -335,13 +335,13 @@ static void exec_neg(struct CPUX86State *env, struct x86_decode *decode)
env->eip += decode->len;
}
-static void exec_cmp(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_cmp(CPUX86State *env, struct x86_decode *decode)
{
EXEC_2OP_FLAGS_CMD(env, decode, -, SET_FLAGS_OSZAPC_SUB, false);
env->eip += decode->len;
}
-static void exec_inc(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_inc(CPUX86State *env, struct x86_decode *decode)
{
decode->op[1].type = X86_VAR_IMMEDIATE;
decode->op[1].val = 0;
@@ -351,7 +351,7 @@ static void exec_inc(struct CPUX86State *env, struct x86_decode *decode)
env->eip += decode->len;
}
-static void exec_dec(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_dec(CPUX86State *env, struct x86_decode *decode)
{
decode->op[1].type = X86_VAR_IMMEDIATE;
decode->op[1].val = 0;
@@ -360,13 +360,13 @@ static void exec_dec(struct CPUX86State *env, struct x86_decode *decode)
env->eip += decode->len;
}
-static void exec_tst(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_tst(CPUX86State *env, struct x86_decode *decode)
{
EXEC_2OP_FLAGS_CMD(env, decode, &, SET_FLAGS_OSZAPC_LOGIC, false);
env->eip += decode->len;
}
-static void exec_not(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_not(CPUX86State *env, struct x86_decode *decode)
{
fetch_operands(env, decode, 1, true, false, false);
@@ -375,7 +375,7 @@ static void exec_not(struct CPUX86State *env, struct x86_decode *decode)
env->eip += decode->len;
}
-void exec_movzx(struct CPUX86State *env, struct x86_decode *decode)
+void exec_movzx(CPUX86State *env, struct x86_decode *decode)
{
int src_op_size;
int op_size = decode->operand_size;
@@ -395,7 +395,7 @@ void exec_movzx(struct CPUX86State *env, struct x86_decode *decode)
env->eip += decode->len;
}
-static void exec_out(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_out(CPUX86State *env, struct x86_decode *decode)
{
switch (decode->opcode[0]) {
case 0xe6:
@@ -419,7 +419,7 @@ static void exec_out(struct CPUX86State *env, struct x86_decode *decode)
env->eip += decode->len;
}
-static void exec_in(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_in(CPUX86State *env, struct x86_decode *decode)
{
target_ulong val = 0;
switch (decode->opcode[0]) {
@@ -455,7 +455,7 @@ static void exec_in(struct CPUX86State *env, struct x86_decode *decode)
env->eip += decode->len;
}
-static inline void string_increment_reg(struct CPUX86State *env, int reg,
+static inline void string_increment_reg(CPUX86State *env, int reg,
struct x86_decode *decode)
{
target_ulong val = read_reg(env, reg, decode->addressing_size);
@@ -467,8 +467,8 @@ static inline void string_increment_reg(struct CPUX86State *env, int reg,
write_reg(env, reg, val, decode->addressing_size);
}
-static inline void string_rep(struct CPUX86State *env, struct x86_decode *decode,
- void (*func)(struct CPUX86State *env,
+static inline void string_rep(CPUX86State *env, struct x86_decode *decode,
+ void (*func)(CPUX86State *env,
struct x86_decode *ins), int rep)
{
target_ulong rcx = read_reg(env, R_ECX, decode->addressing_size);
@@ -484,7 +484,7 @@ static inline void string_rep(struct CPUX86State *env, struct x86_decode *decode
}
}
-static void exec_ins_single(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_ins_single(CPUX86State *env, struct x86_decode *decode)
{
target_ulong addr = linear_addr_size(env_cpu(env), RDI(env),
decode->addressing_size, R_ES);
@@ -497,7 +497,7 @@ static void exec_ins_single(struct CPUX86State *env, struct x86_decode *decode)
string_increment_reg(env, R_EDI, decode);
}
-static void exec_ins(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_ins(CPUX86State *env, struct x86_decode *decode)
{
if (decode->rep) {
string_rep(env, decode, exec_ins_single, 0);
@@ -508,7 +508,7 @@ static void exec_ins(struct CPUX86State *env, struct x86_decode *decode)
env->eip += decode->len;
}
-static void exec_outs_single(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_outs_single(CPUX86State *env, struct x86_decode *decode)
{
target_ulong addr = decode_linear_addr(env, decode, RSI(env), R_DS);
@@ -520,7 +520,7 @@ static void exec_outs_single(struct CPUX86State *env, struct x86_decode *decode)
string_increment_reg(env, R_ESI, decode);
}
-static void exec_outs(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_outs(CPUX86State *env, struct x86_decode *decode)
{
if (decode->rep) {
string_rep(env, decode, exec_outs_single, 0);
@@ -531,7 +531,7 @@ static void exec_outs(struct CPUX86State *env, struct x86_decode *decode)
env->eip += decode->len;
}
-static void exec_movs_single(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_movs_single(CPUX86State *env, struct x86_decode *decode)
{
target_ulong src_addr;
target_ulong dst_addr;
@@ -548,7 +548,7 @@ static void exec_movs_single(struct CPUX86State *env, struct x86_decode *decode)
string_increment_reg(env, R_EDI, decode);
}
-static void exec_movs(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_movs(CPUX86State *env, struct x86_decode *decode)
{
if (decode->rep) {
string_rep(env, decode, exec_movs_single, 0);
@@ -559,7 +559,7 @@ static void exec_movs(struct CPUX86State *env, struct x86_decode *decode)
env->eip += decode->len;
}
-static void exec_cmps_single(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_cmps_single(CPUX86State *env, struct x86_decode *decode)
{
target_ulong src_addr;
target_ulong dst_addr;
@@ -579,7 +579,7 @@ static void exec_cmps_single(struct CPUX86State *env, struct x86_decode *decode)
string_increment_reg(env, R_EDI, decode);
}
-static void exec_cmps(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_cmps(CPUX86State *env, struct x86_decode *decode)
{
if (decode->rep) {
string_rep(env, decode, exec_cmps_single, decode->rep);
@@ -590,7 +590,7 @@ static void exec_cmps(struct CPUX86State *env, struct x86_decode *decode)
}
-static void exec_stos_single(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_stos_single(CPUX86State *env, struct x86_decode *decode)
{
target_ulong addr;
target_ulong val;
@@ -604,7 +604,7 @@ static void exec_stos_single(struct CPUX86State *env, struct x86_decode *decode)
}
-static void exec_stos(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_stos(CPUX86State *env, struct x86_decode *decode)
{
if (decode->rep) {
string_rep(env, decode, exec_stos_single, 0);
@@ -615,7 +615,7 @@ static void exec_stos(struct CPUX86State *env, struct x86_decode *decode)
env->eip += decode->len;
}
-static void exec_scas_single(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_scas_single(CPUX86State *env, struct x86_decode *decode)
{
target_ulong addr;
@@ -628,7 +628,7 @@ static void exec_scas_single(struct CPUX86State *env, struct x86_decode *decode)
string_increment_reg(env, R_EDI, decode);
}
-static void exec_scas(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_scas(CPUX86State *env, struct x86_decode *decode)
{
decode->op[0].type = X86_VAR_REG;
decode->op[0].reg = R_EAX;
@@ -641,7 +641,7 @@ static void exec_scas(struct CPUX86State *env, struct x86_decode *decode)
env->eip += decode->len;
}
-static void exec_lods_single(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_lods_single(CPUX86State *env, struct x86_decode *decode)
{
target_ulong addr;
target_ulong val = 0;
@@ -653,7 +653,7 @@ static void exec_lods_single(struct CPUX86State *env, struct x86_decode *decode)
string_increment_reg(env, R_ESI, decode);
}
-static void exec_lods(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_lods(CPUX86State *env, struct x86_decode *decode)
{
if (decode->rep) {
string_rep(env, decode, exec_lods_single, 0);
@@ -760,7 +760,7 @@ void simulate_rdmsr(struct CPUState *cpu)
RDX(env) = (uint32_t)(val >> 32);
}
-static void exec_rdmsr(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_rdmsr(CPUX86State *env, struct x86_decode *decode)
{
simulate_rdmsr(env_cpu(env));
env->eip += decode->len;
@@ -855,7 +855,7 @@ void simulate_wrmsr(struct CPUState *cpu)
printf("write msr %llx\n", RCX(cpu));*/
}
-static void exec_wrmsr(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_wrmsr(CPUX86State *env, struct x86_decode *decode)
{
simulate_wrmsr(env_cpu(env));
env->eip += decode->len;
@@ -865,7 +865,7 @@ static void exec_wrmsr(struct CPUX86State *env, struct x86_decode *decode)
* flag:
* 0 - bt, 1 - btc, 2 - bts, 3 - btr
*/
-static void do_bt(struct CPUX86State *env, struct x86_decode *decode, int flag)
+static void do_bt(CPUX86State *env, struct x86_decode *decode, int flag)
{
int32_t displacement;
uint8_t index;
@@ -911,31 +911,31 @@ static void do_bt(struct CPUX86State *env, struct x86_decode *decode, int flag)
set_CF(env, cf);
}
-static void exec_bt(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_bt(CPUX86State *env, struct x86_decode *decode)
{
do_bt(env, decode, 0);
env->eip += decode->len;
}
-static void exec_btc(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_btc(CPUX86State *env, struct x86_decode *decode)
{
do_bt(env, decode, 1);
env->eip += decode->len;
}
-static void exec_btr(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_btr(CPUX86State *env, struct x86_decode *decode)
{
do_bt(env, decode, 3);
env->eip += decode->len;
}
-static void exec_bts(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_bts(CPUX86State *env, struct x86_decode *decode)
{
do_bt(env, decode, 2);
env->eip += decode->len;
}
-void exec_shl(struct CPUX86State *env, struct x86_decode *decode)
+void exec_shl(CPUX86State *env, struct x86_decode *decode)
{
uint8_t count;
int of = 0, cf = 0;
@@ -1022,7 +1022,7 @@ void exec_movsx(CPUX86State *env, struct x86_decode *decode)
env->eip += decode->len;
}
-void exec_ror(struct CPUX86State *env, struct x86_decode *decode)
+void exec_ror(CPUX86State *env, struct x86_decode *decode)
{
uint8_t count;
@@ -1100,7 +1100,7 @@ void exec_ror(struct CPUX86State *env, struct x86_decode *decode)
env->eip += decode->len;
}
-void exec_rol(struct CPUX86State *env, struct x86_decode *decode)
+void exec_rol(CPUX86State *env, struct x86_decode *decode)
{
uint8_t count;
@@ -1182,7 +1182,7 @@ void exec_rol(struct CPUX86State *env, struct x86_decode *decode)
}
-void exec_rcl(struct CPUX86State *env, struct x86_decode *decode)
+void exec_rcl(CPUX86State *env, struct x86_decode *decode)
{
uint8_t count;
int of = 0, cf = 0;
@@ -1267,7 +1267,7 @@ void exec_rcl(struct CPUX86State *env, struct x86_decode *decode)
env->eip += decode->len;
}
-void exec_rcr(struct CPUX86State *env, struct x86_decode *decode)
+void exec_rcr(CPUX86State *env, struct x86_decode *decode)
{
uint8_t count;
int of = 0, cf = 0;
@@ -1342,7 +1342,7 @@ void exec_rcr(struct CPUX86State *env, struct x86_decode *decode)
env->eip += decode->len;
}
-static void exec_xchg(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_xchg(CPUX86State *env, struct x86_decode *decode)
{
fetch_operands(env, decode, 2, true, true, false);
@@ -1354,7 +1354,7 @@ static void exec_xchg(struct CPUX86State *env, struct x86_decode *decode)
env->eip += decode->len;
}
-static void exec_xadd(struct CPUX86State *env, struct x86_decode *decode)
+static void exec_xadd(CPUX86State *env, struct x86_decode *decode)
{
EXEC_2OP_FLAGS_CMD(env, decode, +, SET_FLAGS_OSZAPC_ADD, true);
write_val_ext(env, decode->op[1].ptr, decode->op[0].val,
@@ -1365,7 +1365,7 @@ static void exec_xadd(struct CPUX86State *env, struct x86_decode *decode)
static struct cmd_handler {
enum x86_decode_cmd cmd;
- void (*handler)(struct CPUX86State *env, struct x86_decode *ins);
+ void (*handler)(CPUX86State *env, struct x86_decode *ins);
} handlers[] = {
{X86_DECODE_CMD_INVL, NULL,},
{X86_DECODE_CMD_MOV, exec_mov},
@@ -1465,7 +1465,7 @@ void store_regs(struct CPUState *cpu)
macvm_set_rip(cpu, env->eip);
}
-bool exec_instruction(struct CPUX86State *env, struct x86_decode *ins)
+bool exec_instruction(CPUX86State *env, struct x86_decode *ins)
{
/*if (hvf_vcpu_id(cpu))
printf("%d, %llx: exec_instruction %s\n", hvf_vcpu_id(cpu), env->eip,
diff --git a/target/i386/hvf/x86_emu.h b/target/i386/hvf/x86_emu.h
index 233f7b8daa..640da90b30 100644
--- a/target/i386/hvf/x86_emu.h
+++ b/target/i386/hvf/x86_emu.h
@@ -24,7 +24,7 @@
#include "cpu.h"
void init_emu(void);
-bool exec_instruction(struct CPUX86State *env, struct x86_decode *ins);
+bool exec_instruction(CPUX86State *env, struct x86_decode *ins);
void load_regs(struct CPUState *cpu);
void store_regs(struct CPUState *cpu);
@@ -36,15 +36,15 @@ target_ulong read_reg(CPUX86State *env, int reg, int size);
void write_reg(CPUX86State *env, int reg, target_ulong val, int size);
target_ulong read_val_from_reg(target_ulong reg_ptr, int size);
void write_val_to_reg(target_ulong reg_ptr, target_ulong val, int size);
-void write_val_ext(struct CPUX86State *env, target_ulong ptr, target_ulong val, int size);
-uint8_t *read_mmio(struct CPUX86State *env, target_ulong ptr, int bytes);
-target_ulong read_val_ext(struct CPUX86State *env, target_ulong ptr, int size);
+void write_val_ext(CPUX86State *env, target_ulong ptr, target_ulong val, int size);
+uint8_t *read_mmio(CPUX86State *env, target_ulong ptr, int bytes);
+target_ulong read_val_ext(CPUX86State *env, target_ulong ptr, int size);
-void exec_movzx(struct CPUX86State *env, struct x86_decode *decode);
-void exec_shl(struct CPUX86State *env, struct x86_decode *decode);
-void exec_movsx(struct CPUX86State *env, struct x86_decode *decode);
-void exec_ror(struct CPUX86State *env, struct x86_decode *decode);
-void exec_rol(struct CPUX86State *env, struct x86_decode *decode);
-void exec_rcl(struct CPUX86State *env, struct x86_decode *decode);
-void exec_rcr(struct CPUX86State *env, struct x86_decode *decode);
+void exec_movzx(CPUX86State *env, struct x86_decode *decode);
+void exec_shl(CPUX86State *env, struct x86_decode *decode);
+void exec_movsx(CPUX86State *env, struct x86_decode *decode);
+void exec_ror(CPUX86State *env, struct x86_decode *decode);
+void exec_rol(CPUX86State *env, struct x86_decode *decode);
+void exec_rcl(CPUX86State *env, struct x86_decode *decode);
+void exec_rcr(CPUX86State *env, struct x86_decode *decode);
#endif
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 2c8feb4a6f..83d0988302 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -37,6 +37,7 @@
#include "qemu/main-loop.h"
#include "qemu/config-file.h"
#include "qemu/error-report.h"
+#include "qemu/memalign.h"
#include "hw/i386/x86.h"
#include "hw/i386/apic.h"
#include "hw/i386/apic_internal.h"
diff --git a/target/i386/nvmm/nvmm-all.c b/target/i386/nvmm/nvmm-all.c
index 9af261eea3..b97d091a50 100644
--- a/target/i386/nvmm/nvmm-all.c
+++ b/target/i386/nvmm/nvmm-all.c
@@ -85,7 +85,7 @@ nvmm_set_segment(struct nvmm_x64_state_seg *nseg, const SegmentCache *qseg)
static void
nvmm_set_registers(CPUState *cpu)
{
- struct CPUX86State *env = (CPUArchState *)cpu->env_ptr;
+ CPUX86State *env = cpu->env_ptr;
struct nvmm_machine *mach = get_nvmm_mach();
struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu);
struct nvmm_vcpu *vcpu = &qcpu->vcpu;
@@ -222,7 +222,7 @@ nvmm_get_segment(SegmentCache *qseg, const struct nvmm_x64_state_seg *nseg)
static void
nvmm_get_registers(CPUState *cpu)
{
- struct CPUX86State *env = (CPUArchState *)cpu->env_ptr;
+ CPUX86State *env = cpu->env_ptr;
struct nvmm_machine *mach = get_nvmm_mach();
struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu);
struct nvmm_vcpu *vcpu = &qcpu->vcpu;
@@ -347,7 +347,7 @@ nvmm_get_registers(CPUState *cpu)
static bool
nvmm_can_take_int(CPUState *cpu)
{
- struct CPUX86State *env = (CPUArchState *)cpu->env_ptr;
+ CPUX86State *env = cpu->env_ptr;
struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu);
struct nvmm_vcpu *vcpu = &qcpu->vcpu;
struct nvmm_machine *mach = get_nvmm_mach();
@@ -394,7 +394,7 @@ nvmm_can_take_nmi(CPUState *cpu)
static void
nvmm_vcpu_pre_run(CPUState *cpu)
{
- struct CPUX86State *env = (CPUArchState *)cpu->env_ptr;
+ CPUX86State *env = cpu->env_ptr;
struct nvmm_machine *mach = get_nvmm_mach();
struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu);
struct nvmm_vcpu *vcpu = &qcpu->vcpu;
@@ -480,7 +480,7 @@ static void
nvmm_vcpu_post_run(CPUState *cpu, struct nvmm_vcpu_exit *exit)
{
struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu);
- struct CPUX86State *env = (CPUArchState *)cpu->env_ptr;
+ CPUX86State *env = cpu->env_ptr;
X86CPU *x86_cpu = X86_CPU(cpu);
uint64_t tpr;
@@ -652,7 +652,7 @@ static int
nvmm_handle_halted(struct nvmm_machine *mach, CPUState *cpu,
struct nvmm_vcpu_exit *exit)
{
- struct CPUX86State *env = (CPUArchState *)cpu->env_ptr;
+ CPUX86State *env = cpu->env_ptr;
int ret = 0;
qemu_mutex_lock_iothread();
@@ -685,7 +685,7 @@ nvmm_inject_ud(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu)
static int
nvmm_vcpu_loop(CPUState *cpu)
{
- struct CPUX86State *env = (CPUArchState *)cpu->env_ptr;
+ CPUX86State *env = cpu->env_ptr;
struct nvmm_machine *mach = get_nvmm_mach();
struct qemu_vcpu *qcpu = get_qemu_vcpu(cpu);
struct nvmm_vcpu *vcpu = &qcpu->vcpu;
diff --git a/target/i386/tcg/sysemu/excp_helper.c b/target/i386/tcg/sysemu/excp_helper.c
index 5ba739fbed..5627772e7c 100644
--- a/target/i386/tcg/sysemu/excp_helper.c
+++ b/target/i386/tcg/sysemu/excp_helper.c
@@ -19,6 +19,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
+#include "exec/exec-all.h"
#include "tcg/helper-tcg.h"
int get_pg_mode(CPUX86State *env)
diff --git a/target/i386/tcg/sysemu/misc_helper.c b/target/i386/tcg/sysemu/misc_helper.c
index 9ccaa054c4..3715c1e262 100644
--- a/target/i386/tcg/sysemu/misc_helper.c
+++ b/target/i386/tcg/sysemu/misc_helper.c
@@ -23,6 +23,7 @@
#include "exec/helper-proto.h"
#include "exec/cpu_ldst.h"
#include "exec/address-spaces.h"
+#include "exec/exec-all.h"
#include "tcg/helper-tcg.h"
void helper_outb(CPUX86State *env, uint32_t port, uint32_t data)
diff --git a/target/i386/whpx/whpx-accel-ops.c b/target/i386/whpx/whpx-accel-ops.c
index 6bc47c5309..1d30e4e2ed 100644
--- a/target/i386/whpx/whpx-accel-ops.c
+++ b/target/i386/whpx/whpx-accel-ops.c
@@ -83,12 +83,18 @@ static void whpx_kick_vcpu_thread(CPUState *cpu)
}
}
+static bool whpx_vcpu_thread_is_idle(CPUState *cpu)
+{
+ return !whpx_apic_in_platform();
+}
+
static void whpx_accel_ops_class_init(ObjectClass *oc, void *data)
{
AccelOpsClass *ops = ACCEL_OPS_CLASS(oc);
ops->create_vcpu_thread = whpx_start_vcpu_thread;
ops->kick_vcpu_thread = whpx_kick_vcpu_thread;
+ ops->cpu_thread_is_idle = whpx_vcpu_thread_is_idle;
ops->synchronize_post_reset = whpx_cpu_synchronize_post_reset;
ops->synchronize_post_init = whpx_cpu_synchronize_post_init;
diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c
index ef896da0a2..c7e25abf42 100644
--- a/target/i386/whpx/whpx-all.c
+++ b/target/i386/whpx/whpx-all.c
@@ -221,7 +221,7 @@ static SegmentCache whpx_seg_h2q(const WHV_X64_SEGMENT_REGISTER *hs)
static int whpx_set_tsc(CPUState *cpu)
{
- struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr);
+ CPUX86State *env = cpu->env_ptr;
WHV_REGISTER_NAME tsc_reg = WHvX64RegisterTsc;
WHV_REGISTER_VALUE tsc_val;
HRESULT hr;
@@ -260,7 +260,7 @@ static void whpx_set_registers(CPUState *cpu, int level)
{
struct whpx_state *whpx = &whpx_global;
struct whpx_vcpu *vcpu = get_whpx_vcpu(cpu);
- struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr);
+ CPUX86State *env = cpu->env_ptr;
X86CPU *x86_cpu = X86_CPU(cpu);
struct whpx_register_set vcxt;
HRESULT hr;
@@ -428,7 +428,7 @@ static void whpx_set_registers(CPUState *cpu, int level)
static int whpx_get_tsc(CPUState *cpu)
{
- struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr);
+ CPUX86State *env = cpu->env_ptr;
WHV_REGISTER_NAME tsc_reg = WHvX64RegisterTsc;
WHV_REGISTER_VALUE tsc_val;
HRESULT hr;
@@ -449,7 +449,7 @@ static void whpx_get_registers(CPUState *cpu)
{
struct whpx_state *whpx = &whpx_global;
struct whpx_vcpu *vcpu = get_whpx_vcpu(cpu);
- struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr);
+ CPUX86State *env = cpu->env_ptr;
X86CPU *x86_cpu = X86_CPU(cpu);
struct whpx_register_set vcxt;
uint64_t tpr, apic_base;
@@ -760,7 +760,7 @@ static int whpx_handle_portio(CPUState *cpu,
static int whpx_handle_halt(CPUState *cpu)
{
- struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr);
+ CPUX86State *env = cpu->env_ptr;
int ret = 0;
qemu_mutex_lock_iothread();
@@ -781,7 +781,7 @@ static void whpx_vcpu_pre_run(CPUState *cpu)
HRESULT hr;
struct whpx_state *whpx = &whpx_global;
struct whpx_vcpu *vcpu = get_whpx_vcpu(cpu);
- struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr);
+ CPUX86State *env = cpu->env_ptr;
X86CPU *x86_cpu = X86_CPU(cpu);
int irq;
uint8_t tpr;
@@ -903,7 +903,7 @@ static void whpx_vcpu_pre_run(CPUState *cpu)
static void whpx_vcpu_post_run(CPUState *cpu)
{
struct whpx_vcpu *vcpu = get_whpx_vcpu(cpu);
- struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr);
+ CPUX86State *env = cpu->env_ptr;
X86CPU *x86_cpu = X86_CPU(cpu);
env->eflags = vcpu->exit_ctx.VpContext.Rflags;
@@ -927,7 +927,7 @@ static void whpx_vcpu_post_run(CPUState *cpu)
static void whpx_vcpu_process_async_events(CPUState *cpu)
{
- struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr);
+ CPUX86State *env = cpu->env_ptr;
X86CPU *x86_cpu = X86_CPU(cpu);
struct whpx_vcpu *vcpu = get_whpx_vcpu(cpu);
@@ -1333,7 +1333,7 @@ int whpx_init_vcpu(CPUState *cpu)
struct whpx_state *whpx = &whpx_global;
struct whpx_vcpu *vcpu = NULL;
Error *local_error = NULL;
- struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr);
+ CPUX86State *env = cpu->env_ptr;
X86CPU *x86_cpu = X86_CPU(cpu);
UINT64 freq = 0;
int ret;
diff --git a/target/m68k/cpu-qom.h b/target/m68k/cpu-qom.h
index 1ceb160ecb..cd9687192c 100644
--- a/target/m68k/cpu-qom.h
+++ b/target/m68k/cpu-qom.h
@@ -25,8 +25,7 @@
#define TYPE_M68K_CPU "m68k-cpu"
-OBJECT_DECLARE_TYPE(M68kCPU, M68kCPUClass,
- M68K_CPU)
+OBJECT_DECLARE_CPU_TYPE(M68kCPU, M68kCPUClass, M68K_CPU)
/*
* M68kCPUClass:
diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h
index a3423729ef..872e8ce637 100644
--- a/target/m68k/cpu.h
+++ b/target/m68k/cpu.h
@@ -79,7 +79,7 @@
typedef CPU_LDoubleU FPReg;
-typedef struct CPUM68KState {
+typedef struct CPUArchState {
uint32_t dregs[8];
uint32_t aregs[8];
uint32_t pc;
@@ -156,7 +156,7 @@ typedef struct CPUM68KState {
*
* A Motorola 68k CPU.
*/
-struct M68kCPU {
+struct ArchCPU {
/*< private >*/
CPUState parent_obj;
/*< public >*/
@@ -574,9 +574,6 @@ void m68k_cpu_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr,
int mmu_idx, MemTxAttrs attrs,
MemTxResult response, uintptr_t retaddr);
-typedef CPUM68KState CPUArchState;
-typedef M68kCPU ArchCPU;
-
#include "exec/cpu-all.h"
/* TB flags */
diff --git a/target/microblaze/cpu-qom.h b/target/microblaze/cpu-qom.h
index e520eefb12..255b39a45d 100644
--- a/target/microblaze/cpu-qom.h
+++ b/target/microblaze/cpu-qom.h
@@ -25,8 +25,7 @@
#define TYPE_MICROBLAZE_CPU "microblaze-cpu"
-OBJECT_DECLARE_TYPE(MicroBlazeCPU, MicroBlazeCPUClass,
- MICROBLAZE_CPU)
+OBJECT_DECLARE_CPU_TYPE(MicroBlazeCPU, MicroBlazeCPUClass, MICROBLAZE_CPU)
/**
* MicroBlazeCPUClass:
diff --git a/target/microblaze/cpu.h b/target/microblaze/cpu.h
index e9cd0b88de..0a0ce71b6a 100644
--- a/target/microblaze/cpu.h
+++ b/target/microblaze/cpu.h
@@ -24,7 +24,7 @@
#include "exec/cpu-defs.h"
#include "fpu/softfloat-types.h"
-typedef struct CPUMBState CPUMBState;
+typedef struct CPUArchState CPUMBState;
#if !defined(CONFIG_USER_ONLY)
#include "mmu.h"
#endif
@@ -239,7 +239,7 @@ typedef struct CPUMBState CPUMBState;
#define USE_NON_SECURE_M_AXI_DC_MASK 0x4
#define USE_NON_SECURE_M_AXI_IC_MASK 0x8
-struct CPUMBState {
+struct CPUArchState {
uint32_t bvalue; /* TCG temporary, only valid during a TB */
uint32_t btarget; /* Full resolved branch destination */
@@ -339,7 +339,7 @@ typedef struct {
*
* A MicroBlaze CPU.
*/
-struct MicroBlazeCPU {
+struct ArchCPU {
/*< private >*/
CPUState parent_obj;
@@ -394,9 +394,6 @@ void mb_tcg_init(void);
#define MMU_USER_IDX 2
/* See NB_MMU_MODES further up the file. */
-typedef CPUMBState CPUArchState;
-typedef MicroBlazeCPU ArchCPU;
-
#include "exec/cpu-all.h"
/* Ensure there is no overlap between the two masks. */
diff --git a/target/microblaze/mmu.h b/target/microblaze/mmu.h
index b6b4b9ad60..1068bd2d52 100644
--- a/target/microblaze/mmu.h
+++ b/target/microblaze/mmu.h
@@ -20,6 +20,8 @@
#ifndef TARGET_MICROBLAZE_MMU_H
#define TARGET_MICROBLAZE_MMU_H
+#include "cpu.h"
+
#define MMU_R_PID 0
#define MMU_R_ZPR 1
#define MMU_R_TLBX 2
diff --git a/target/mips/cpu-qom.h b/target/mips/cpu-qom.h
index dda0c911fa..e28b529607 100644
--- a/target/mips/cpu-qom.h
+++ b/target/mips/cpu-qom.h
@@ -29,8 +29,7 @@
#define TYPE_MIPS_CPU "mips-cpu"
#endif
-OBJECT_DECLARE_TYPE(MIPSCPU, MIPSCPUClass,
- MIPS_CPU)
+OBJECT_DECLARE_CPU_TYPE(MIPSCPU, MIPSCPUClass, MIPS_CPU)
/**
* MIPSCPUClass:
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index 4aae23934b..af287177d5 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -434,14 +434,13 @@ static void mips_cpu_disas_set_info(CPUState *s, disassemble_info *info)
* Since commit 6af0bf9c7c3 this model assumes a CPU clocked at 200MHz.
*/
#define CPU_FREQ_HZ_DEFAULT 200000000
-#define CP0_COUNT_RATE_DEFAULT 2
static void mips_cp0_period_set(MIPSCPU *cpu)
{
CPUMIPSState *env = &cpu->env;
env->cp0_count_ns = clock_ticks_to_ns(MIPS_CPU(cpu)->clock,
- cpu->cp0_count_rate);
+ env->cpu_model->CCRes);
assert(env->cp0_count_ns);
}
@@ -514,13 +513,6 @@ static ObjectClass *mips_cpu_class_by_name(const char *cpu_model)
return oc;
}
-static Property mips_cpu_properties[] = {
- /* CP0 timer running at half the clock of the CPU */
- DEFINE_PROP_UINT32("cp0-count-rate", MIPSCPU, cp0_count_rate,
- CP0_COUNT_RATE_DEFAULT),
- DEFINE_PROP_END_OF_LIST()
-};
-
#ifndef CONFIG_USER_ONLY
#include "hw/core/sysemu-cpu-ops.h"
@@ -560,7 +552,6 @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
device_class_set_parent_realize(dc, mips_cpu_realizefn,
&mcc->parent_realize);
device_class_set_parent_reset(dc, mips_cpu_reset, &mcc->parent_reset);
- device_class_set_props(dc, mips_cpu_properties);
cc->class_by_name = mips_cpu_class_by_name;
cc->has_work = mips_cpu_has_work;
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 56b1cbd091..52ce08a94d 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -524,8 +524,7 @@ struct TCState {
};
struct MIPSITUState;
-typedef struct CPUMIPSState CPUMIPSState;
-struct CPUMIPSState {
+typedef struct CPUArchState {
TCState active_tc;
CPUMIPSFPUContext active_fpu;
@@ -1161,18 +1160,17 @@ struct CPUMIPSState {
QEMUTimer *timer; /* Internal timer */
target_ulong exception_base; /* ExceptionBase input to the core */
uint64_t cp0_count_ns; /* CP0_Count clock period (in nanoseconds) */
-};
+} CPUMIPSState;
/**
* MIPSCPU:
* @env: #CPUMIPSState
* @clock: this CPU input clock (may be connected
* to an output clock from another device).
- * @cp0_count_rate: rate at which the coprocessor 0 counter increments
*
* A MIPS CPU.
*/
-struct MIPSCPU {
+struct ArchCPU {
/*< private >*/
CPUState parent_obj;
/*< public >*/
@@ -1180,14 +1178,6 @@ struct MIPSCPU {
Clock *clock;
CPUNegativeOffsetState neg;
CPUMIPSState env;
- /*
- * The Count register acts as a timer, incrementing at a constant rate,
- * whether or not an instruction is executed, retired, or any forward
- * progress is made through the pipeline. The rate at which the counter
- * increments is implementation dependent, and is a function of the
- * pipeline clock of the processor, not the issue width of the processor.
- */
- unsigned cp0_count_rate;
};
@@ -1218,9 +1208,6 @@ static inline int cpu_mmu_index(CPUMIPSState *env, bool ifetch)
return hflags_mmu_index(env->hflags);
}
-typedef CPUMIPSState CPUArchState;
-typedef MIPSCPU ArchCPU;
-
#include "exec/cpu-all.h"
/* Exceptions */
diff --git a/target/mips/internal.h b/target/mips/internal.h
index daddb05fd4..57b312689a 100644
--- a/target/mips/internal.h
+++ b/target/mips/internal.h
@@ -12,6 +12,7 @@
#ifdef CONFIG_TCG
#include "tcg/tcg-internal.h"
#endif
+#include "cpu.h"
/*
* MMU types, the first four entries have the same layout as the
@@ -46,6 +47,15 @@ struct mips_def_t {
target_ulong CP0_LLAddr_rw_bitmask;
int CP0_LLAddr_shift;
int32_t SYNCI_Step;
+ /*
+ * @CCRes: rate at which the coprocessor 0 counter increments
+ *
+ * The Count register acts as a timer, incrementing at a constant rate,
+ * whether or not an instruction is executed, retired, or any forward
+ * progress is made through the pipeline. The rate at which the counter
+ * increments is implementation dependent, and is a function of the
+ * pipeline clock of the processor, not the issue width of the processor.
+ */
int32_t CCRes;
int32_t CP0_Status_rw_bitmask;
int32_t CP0_TCStatus_rw_bitmask;
@@ -133,14 +143,14 @@ struct r4k_tlb_t {
struct CPUMIPSTLBContext {
uint32_t nb_tlb;
uint32_t tlb_in_use;
- int (*map_address)(struct CPUMIPSState *env, hwaddr *physical, int *prot,
+ int (*map_address)(CPUMIPSState *env, hwaddr *physical, int *prot,
target_ulong address, MMUAccessType access_type);
- void (*helper_tlbwi)(struct CPUMIPSState *env);
- void (*helper_tlbwr)(struct CPUMIPSState *env);
- void (*helper_tlbp)(struct CPUMIPSState *env);
- void (*helper_tlbr)(struct CPUMIPSState *env);
- void (*helper_tlbinv)(struct CPUMIPSState *env);
- void (*helper_tlbinvf)(struct CPUMIPSState *env);
+ void (*helper_tlbwi)(CPUMIPSState *env);
+ void (*helper_tlbwr)(CPUMIPSState *env);
+ void (*helper_tlbp)(CPUMIPSState *env);
+ void (*helper_tlbr)(CPUMIPSState *env);
+ void (*helper_tlbinv)(CPUMIPSState *env);
+ void (*helper_tlbinvf)(CPUMIPSState *env);
union {
struct {
r4k_tlb_t tlb[MIPS_TLB_MAX];
diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h
index a00e4229ce..ca0f3420cd 100644
--- a/target/nios2/cpu.h
+++ b/target/nios2/cpu.h
@@ -25,15 +25,14 @@
#include "hw/core/cpu.h"
#include "qom/object.h"
-typedef struct CPUNios2State CPUNios2State;
+typedef struct CPUArchState CPUNios2State;
#if !defined(CONFIG_USER_ONLY)
#include "mmu.h"
#endif
#define TYPE_NIOS2_CPU "nios2-cpu"
-OBJECT_DECLARE_TYPE(Nios2CPU, Nios2CPUClass,
- NIOS2_CPU)
+OBJECT_DECLARE_CPU_TYPE(Nios2CPU, Nios2CPUClass, NIOS2_CPU)
/**
* Nios2CPUClass:
@@ -155,7 +154,7 @@ struct Nios2CPUClass {
#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3
-struct CPUNios2State {
+struct CPUArchState {
uint32_t regs[NUM_CORE_REGS];
#if !defined(CONFIG_USER_ONLY)
@@ -170,7 +169,7 @@ struct CPUNios2State {
*
* A Nios2 CPU.
*/
-struct Nios2CPU {
+struct ArchCPU {
/*< private >*/
CPUState parent_obj;
/*< public >*/
diff --git a/target/nios2/mmu.h b/target/nios2/mmu.h
index b7785b46c0..5b085900fb 100644
--- a/target/nios2/mmu.h
+++ b/target/nios2/mmu.h
@@ -21,6 +21,8 @@
#ifndef NIOS2_MMU_H
#define NIOS2_MMU_H
+#include "cpu.h"
+
typedef struct Nios2TLBEntry {
target_ulong tag;
target_ulong data;
diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h
index ee069b080c..bdf29d2dc4 100644
--- a/target/openrisc/cpu.h
+++ b/target/openrisc/cpu.h
@@ -24,13 +24,9 @@
#include "hw/core/cpu.h"
#include "qom/object.h"
-/* cpu_openrisc_map_address_* in CPUOpenRISCTLBContext need this decl. */
-struct OpenRISCCPU;
-
#define TYPE_OPENRISC_CPU "or1k-cpu"
-OBJECT_DECLARE_TYPE(OpenRISCCPU, OpenRISCCPUClass,
- OPENRISC_CPU)
+OBJECT_DECLARE_CPU_TYPE(OpenRISCCPU, OpenRISCCPUClass, OPENRISC_CPU)
/**
* OpenRISCCPUClass:
@@ -231,18 +227,18 @@ typedef struct CPUOpenRISCTLBContext {
OpenRISCTLBEntry itlb[TLB_SIZE];
OpenRISCTLBEntry dtlb[TLB_SIZE];
- int (*cpu_openrisc_map_address_code)(struct OpenRISCCPU *cpu,
+ int (*cpu_openrisc_map_address_code)(OpenRISCCPU *cpu,
hwaddr *physical,
int *prot,
target_ulong address, int rw);
- int (*cpu_openrisc_map_address_data)(struct OpenRISCCPU *cpu,
+ int (*cpu_openrisc_map_address_data)(OpenRISCCPU *cpu,
hwaddr *physical,
int *prot,
target_ulong address, int rw);
} CPUOpenRISCTLBContext;
#endif
-typedef struct CPUOpenRISCState {
+typedef struct CPUArchState {
target_ulong shadow_gpr[16][32]; /* Shadow registers */
target_ulong pc; /* Program counter */
@@ -301,7 +297,7 @@ typedef struct CPUOpenRISCState {
*
* A OpenRISC CPU.
*/
-struct OpenRISCCPU {
+struct ArchCPU {
/*< private >*/
CPUState parent_obj;
/*< public >*/
@@ -348,9 +344,6 @@ void cpu_openrisc_count_stop(OpenRISCCPU *cpu);
#define OPENRISC_CPU_TYPE_NAME(model) model OPENRISC_CPU_TYPE_SUFFIX
#define CPU_RESOLVING_TYPE TYPE_OPENRISC_CPU
-typedef CPUOpenRISCState CPUArchState;
-typedef OpenRISCCPU ArchCPU;
-
#include "exec/cpu-all.h"
#define TB_FLAGS_SM SR_SM
diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h
index 98facee9fa..ad7e3c3db9 100644
--- a/target/ppc/cpu-qom.h
+++ b/target/ppc/cpu-qom.h
@@ -29,10 +29,9 @@
#define TYPE_POWERPC_CPU "powerpc-cpu"
#endif
-OBJECT_DECLARE_TYPE(PowerPCCPU, PowerPCCPUClass,
- POWERPC_CPU)
+OBJECT_DECLARE_CPU_TYPE(PowerPCCPU, PowerPCCPUClass, POWERPC_CPU)
-typedef struct CPUPPCState CPUPPCState;
+typedef struct CPUArchState CPUPPCState;
typedef struct ppc_tb_t ppc_tb_t;
typedef struct ppc_dcr_t ppc_dcr_t;
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 1b687521c7..047b24ba50 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1077,7 +1077,7 @@ struct ppc_radix_page_info {
#define PPC_CPU_OPCODES_LEN 0x40
#define PPC_CPU_INDIRECT_OPCODES_LEN 0x20
-struct CPUPPCState {
+struct CPUArchState {
/* Most commonly used resources during translated code execution first */
target_ulong gpr[32]; /* general purpose registers */
target_ulong gprh[32]; /* storage for GPR MSB, used by the SPE extension */
@@ -1275,7 +1275,7 @@ typedef struct PPCVirtualHypervisorClass PPCVirtualHypervisorClass;
*
* A PowerPC CPU.
*/
-struct PowerPCCPU {
+struct ArchCPU {
/*< private >*/
CPUState parent_obj;
/*< public >*/
@@ -1477,9 +1477,6 @@ void ppc_compat_add_property(Object *obj, const char *name,
uint32_t *compat_pvr, const char *basedesc);
#endif /* defined(TARGET_PPC64) */
-typedef CPUPPCState CPUArchState;
-typedef PowerPCCPU ArchCPU;
-
#include "exec/cpu-all.h"
/*****************************************************************************/
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 9ba05042ed..c069fe85fa 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -98,7 +98,7 @@ enum {
#define MAX_RISCV_PMPS (16)
-typedef struct CPURISCVState CPURISCVState;
+typedef struct CPUArchState CPURISCVState;
#if !defined(CONFIG_USER_ONLY)
#include "pmp.h"
@@ -113,7 +113,7 @@ FIELD(VTYPE, VMA, 7, 1)
FIELD(VTYPE, VEDIV, 8, 2)
FIELD(VTYPE, RESERVED, 10, sizeof(target_ulong) * 8 - 11)
-struct CPURISCVState {
+struct CPUArchState {
target_ulong gpr[32];
target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */
uint64_t fpr[32]; /* assume both F and D extensions */
@@ -320,8 +320,7 @@ struct CPURISCVState {
uint64_t kvm_timer_frequency;
};
-OBJECT_DECLARE_TYPE(RISCVCPU, RISCVCPUClass,
- RISCV_CPU)
+OBJECT_DECLARE_CPU_TYPE(RISCVCPU, RISCVCPUClass, RISCV_CPU)
/**
* RISCVCPUClass:
@@ -395,7 +394,7 @@ typedef struct RISCVCPUConfig RISCVCPUConfig;
*
* A RISCV CPU.
*/
-struct RISCVCPU {
+struct ArchCPU {
/*< private >*/
CPUState parent_obj;
/*< public >*/
@@ -499,8 +498,6 @@ void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong);
#define TB_FLAGS_MSTATUS_FS MSTATUS_FS
#define TB_FLAGS_MSTATUS_VS MSTATUS_VS
-typedef CPURISCVState CPUArchState;
-typedef RISCVCPU ArchCPU;
#include "exec/cpu-all.h"
FIELD(TB_FLAGS, MEM_IDX, 0, 3)
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index aea82dff4a..0606cd0ea8 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -23,6 +23,7 @@
#include "cpu.h"
#include "qemu/main-loop.h"
#include "exec/exec-all.h"
+#include "sysemu/cpu-timers.h"
/* CSR function table public API */
void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops)
diff --git a/target/riscv/pmp.h b/target/riscv/pmp.h
index a9a0b363a7..fcb6b7c467 100644
--- a/target/riscv/pmp.h
+++ b/target/riscv/pmp.h
@@ -22,6 +22,8 @@
#ifndef RISCV_PMP_H
#define RISCV_PMP_H
+#include "cpu.h"
+
typedef enum {
PMP_READ = 1 << 0,
PMP_WRITE = 1 << 1,
diff --git a/target/rx/cpu-qom.h b/target/rx/cpu-qom.h
index 7310558e0c..4533759d96 100644
--- a/target/rx/cpu-qom.h
+++ b/target/rx/cpu-qom.h
@@ -26,8 +26,7 @@
#define TYPE_RX62N_CPU RX_CPU_TYPE_NAME("rx62n")
-OBJECT_DECLARE_TYPE(RXCPU, RXCPUClass,
- RX_CPU)
+OBJECT_DECLARE_CPU_TYPE(RXCPU, RXCPUClass, RX_CPU)
/*
* RXCPUClass:
@@ -45,6 +44,4 @@ struct RXCPUClass {
DeviceReset parent_reset;
};
-#define CPUArchState struct CPURXState
-
#endif
diff --git a/target/rx/cpu.h b/target/rx/cpu.h
index 58adf9edf6..b4abd90ccd 100644
--- a/target/rx/cpu.h
+++ b/target/rx/cpu.h
@@ -65,7 +65,7 @@ enum {
NUM_REGS = 16,
};
-typedef struct CPURXState {
+typedef struct CPUArchState {
/* CPU registers */
uint32_t regs[NUM_REGS]; /* general registers */
uint32_t psw_o; /* O bit of status register */
@@ -105,7 +105,7 @@ typedef struct CPURXState {
*
* A RX CPU
*/
-struct RXCPU {
+struct ArchCPU {
/*< private >*/
CPUState parent_obj;
/*< public >*/
@@ -114,8 +114,6 @@ struct RXCPU {
CPURXState env;
};
-typedef RXCPU ArchCPU;
-
#define RX_CPU_TYPE_SUFFIX "-" TYPE_RX_CPU
#define RX_CPU_TYPE_NAME(model) model RX_CPU_TYPE_SUFFIX
#define CPU_RESOLVING_TYPE TYPE_RX_CPU
diff --git a/target/s390x/cpu-qom.h b/target/s390x/cpu-qom.h
index 9f3a0d86c5..00cae2b131 100644
--- a/target/s390x/cpu-qom.h
+++ b/target/s390x/cpu-qom.h
@@ -25,12 +25,13 @@
#define TYPE_S390_CPU "s390x-cpu"
-OBJECT_DECLARE_TYPE(S390CPU, S390CPUClass,
- S390_CPU)
+OBJECT_DECLARE_CPU_TYPE(S390CPU, S390CPUClass, S390_CPU)
typedef struct S390CPUModel S390CPUModel;
typedef struct S390CPUDef S390CPUDef;
+typedef struct CPUArchState CPUS390XState;
+
typedef enum cpu_reset_type {
S390_CPU_RESET_NORMAL,
S390_CPU_RESET_INITIAL,
@@ -63,6 +64,4 @@ struct S390CPUClass {
void (*reset)(CPUState *cpu, cpu_reset_type type);
};
-typedef struct CPUS390XState CPUS390XState;
-
#endif
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index a75e559134..c49c8466e7 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -51,7 +51,7 @@ typedef struct PSW {
uint64_t addr;
} PSW;
-struct CPUS390XState {
+struct CPUArchState {
uint64_t regs[16]; /* GP registers */
/*
* The floating point registers are part of the vector registers.
@@ -163,7 +163,7 @@ static inline uint64_t *get_freg(CPUS390XState *cs, int nr)
*
* An S/390 CPU.
*/
-struct S390CPU {
+struct ArchCPU {
/*< private >*/
CPUState parent_obj;
/*< public >*/
@@ -840,9 +840,6 @@ uint64_t s390_cpu_get_psw_mask(CPUS390XState *env);
/* outside of target/s390x/ */
S390CPU *s390_cpu_addr2state(uint16_t cpu_addr);
-typedef CPUS390XState CPUArchState;
-typedef S390CPU ArchCPU;
-
#include "exec/cpu-all.h"
#endif
diff --git a/target/sh4/cpu-qom.h b/target/sh4/cpu-qom.h
index 8903b4b9c7..d4192d1090 100644
--- a/target/sh4/cpu-qom.h
+++ b/target/sh4/cpu-qom.h
@@ -29,8 +29,7 @@
#define TYPE_SH7751R_CPU SUPERH_CPU_TYPE_NAME("sh7751r")
#define TYPE_SH7785_CPU SUPERH_CPU_TYPE_NAME("sh7785")
-OBJECT_DECLARE_TYPE(SuperHCPU, SuperHCPUClass,
- SUPERH_CPU)
+OBJECT_DECLARE_CPU_TYPE(SuperHCPU, SuperHCPUClass, SUPERH_CPU)
/**
* SuperHCPUClass:
diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h
index fb9dd9db2f..c72a30edfd 100644
--- a/target/sh4/cpu.h
+++ b/target/sh4/cpu.h
@@ -130,7 +130,7 @@ typedef struct memory_content {
struct memory_content *next;
} memory_content;
-typedef struct CPUSH4State {
+typedef struct CPUArchState {
uint32_t flags; /* general execution flags */
uint32_t gregs[24]; /* general registers */
float32 fregs[32]; /* floating point registers */
@@ -195,7 +195,7 @@ typedef struct CPUSH4State {
*
* A SuperH CPU.
*/
-struct SuperHCPU {
+struct ArchCPU {
/*< private >*/
CPUState parent_obj;
/*< public >*/
@@ -264,9 +264,6 @@ static inline int cpu_mmu_index (CPUSH4State *env, bool ifetch)
}
}
-typedef CPUSH4State CPUArchState;
-typedef SuperHCPU ArchCPU;
-
#include "exec/cpu-all.h"
/* MMU control register */
diff --git a/target/sparc/cpu-qom.h b/target/sparc/cpu-qom.h
index f33949aaee..86ed37d933 100644
--- a/target/sparc/cpu-qom.h
+++ b/target/sparc/cpu-qom.h
@@ -29,8 +29,7 @@
#define TYPE_SPARC_CPU "sparc-cpu"
#endif
-OBJECT_DECLARE_TYPE(SPARCCPU, SPARCCPUClass,
- SPARC_CPU)
+OBJECT_DECLARE_CPU_TYPE(SPARCCPU, SPARCCPUClass, SPARC_CPU)
typedef struct sparc_def_t sparc_def_t;
/**
diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index 5a7f1ed5d6..abb38db674 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -420,7 +420,7 @@ struct CPUTimer
typedef struct CPUTimer CPUTimer;
-typedef struct CPUSPARCState CPUSPARCState;
+typedef struct CPUArchState CPUSPARCState;
#if defined(TARGET_SPARC64)
typedef union {
uint64_t mmuregs[16];
@@ -439,7 +439,7 @@ typedef union {
};
} SparcV9MMU;
#endif
-struct CPUSPARCState {
+struct CPUArchState {
target_ulong gregs[8]; /* general registers */
target_ulong *regwptr; /* pointer to current register window */
target_ulong pc; /* program counter */
@@ -556,7 +556,7 @@ struct CPUSPARCState {
*
* A SPARC CPU.
*/
-struct SPARCCPU {
+struct ArchCPU {
/*< private >*/
CPUState parent_obj;
/*< public >*/
@@ -743,9 +743,6 @@ static inline int cpu_pil_allowed(CPUSPARCState *env1, int pil)
#endif
}
-typedef CPUSPARCState CPUArchState;
-typedef SPARCCPU ArchCPU;
-
#include "exec/cpu-all.h"
#ifdef TARGET_SPARC64
diff --git a/target/tricore/cpu-qom.h b/target/tricore/cpu-qom.h
index 59bfd01bbc..ee24e9fa76 100644
--- a/target/tricore/cpu-qom.h
+++ b/target/tricore/cpu-qom.h
@@ -24,8 +24,7 @@
#define TYPE_TRICORE_CPU "tricore-cpu"
-OBJECT_DECLARE_TYPE(TriCoreCPU, TriCoreCPUClass,
- TRICORE_CPU)
+OBJECT_DECLARE_CPU_TYPE(TriCoreCPU, TriCoreCPUClass, TRICORE_CPU)
struct TriCoreCPUClass {
/*< private >*/
diff --git a/target/tricore/cpu.h b/target/tricore/cpu.h
index c461387e71..108d6b8288 100644
--- a/target/tricore/cpu.h
+++ b/target/tricore/cpu.h
@@ -28,8 +28,7 @@ struct tricore_boot_info;
typedef struct tricore_def_t tricore_def_t;
-typedef struct CPUTriCoreState CPUTriCoreState;
-struct CPUTriCoreState {
+typedef struct CPUArchState {
/* GPR Register */
uint32_t gpr_a[16];
uint32_t gpr_d[16];
@@ -189,7 +188,7 @@ struct CPUTriCoreState {
const tricore_def_t *cpu_model;
void *irq[8];
struct QEMUTimer *timer; /* Internal timer */
-};
+} CPUTriCoreState;
/**
* TriCoreCPU:
@@ -197,7 +196,7 @@ struct CPUTriCoreState {
*
* A TriCore CPU.
*/
-struct TriCoreCPU {
+struct ArchCPU {
/*< private >*/
CPUState parent_obj;
/*< public >*/
@@ -369,9 +368,6 @@ static inline int cpu_mmu_index(CPUTriCoreState *env, bool ifetch)
return 0;
}
-typedef CPUTriCoreState CPUArchState;
-typedef TriCoreCPU ArchCPU;
-
#include "exec/cpu-all.h"
void cpu_state_reset(CPUTriCoreState *s);
diff --git a/target/xtensa/cpu-qom.h b/target/xtensa/cpu-qom.h
index 41d9859673..4fc35ee49b 100644
--- a/target/xtensa/cpu-qom.h
+++ b/target/xtensa/cpu-qom.h
@@ -34,8 +34,7 @@
#define TYPE_XTENSA_CPU "xtensa-cpu"
-OBJECT_DECLARE_TYPE(XtensaCPU, XtensaCPUClass,
- XTENSA_CPU)
+OBJECT_DECLARE_CPU_TYPE(XtensaCPU, XtensaCPUClass, XTENSA_CPU)
typedef struct XtensaConfig XtensaConfig;
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index 02143f2f77..4515f682aa 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -306,7 +306,7 @@ typedef enum {
INTTYPE_MAX
} interrupt_type;
-struct CPUXtensaState;
+typedef struct CPUArchState CPUXtensaState;
typedef struct xtensa_tlb_entry {
uint32_t vaddr;
@@ -344,7 +344,7 @@ typedef struct XtensaGdbRegmap {
} XtensaGdbRegmap;
typedef struct XtensaCcompareTimer {
- struct CPUXtensaState *env;
+ CPUXtensaState *env;
QEMUTimer *timer;
} XtensaCcompareTimer;
@@ -506,7 +506,7 @@ enum {
};
#endif
-typedef struct CPUXtensaState {
+struct CPUArchState {
const XtensaConfig *config;
uint32_t regs[16];
uint32_t pc;
@@ -545,7 +545,7 @@ typedef struct CPUXtensaState {
/* Watchpoints for DBREAK registers */
struct CPUWatchpoint *cpu_watchpoint[MAX_NDBREAK];
-} CPUXtensaState;
+};
/**
* XtensaCPU:
@@ -553,7 +553,7 @@ typedef struct CPUXtensaState {
*
* An Xtensa CPU.
*/
-struct XtensaCPU {
+struct ArchCPU {
/*< private >*/
CPUState parent_obj;
/*< public >*/
@@ -722,9 +722,6 @@ static inline int cpu_mmu_index(CPUXtensaState *env, bool ifetch)
#define XTENSA_CSBASE_LBEG_OFF_MASK 0x00ff0000
#define XTENSA_CSBASE_LBEG_OFF_SHIFT 16
-typedef CPUXtensaState CPUArchState;
-typedef XtensaCPU ArchCPU;
-
#include "exec/cpu-all.h"
static inline void cpu_get_tb_cpu_state(CPUXtensaState *env, target_ulong *pc,
diff --git a/tcg/region.c b/tcg/region.c
index 72afb35738..97ca5291d5 100644
--- a/tcg/region.c
+++ b/tcg/region.c
@@ -26,6 +26,7 @@
#include "qemu/units.h"
#include "qemu/madvise.h"
#include "qemu/mprotect.h"
+#include "qemu/memalign.h"
#include "qemu/cacheinfo.h"
#include "qapi/error.h"
#include "exec/exec-all.h"
diff --git a/tests/avocado/avocado_qemu/__init__.py b/tests/avocado/avocado_qemu/__init__.py
index 75063c0c30..9b056b5ce5 100644
--- a/tests/avocado/avocado_qemu/__init__.py
+++ b/tests/avocado/avocado_qemu/__init__.py
@@ -603,6 +603,8 @@ class LinuxTest(LinuxSSHMixIn, QemuSystemTest):
try:
cloudinit_iso = os.path.join(self.workdir, 'cloudinit.iso')
self.phone_home_port = network.find_free_port()
+ if not self.phone_home_port:
+ self.cancel('Failed to get a free port')
pubkey_content = None
if ssh_pubkey:
with open(ssh_pubkey) as pubkey:
diff --git a/tests/avocado/boot_linux.py b/tests/avocado/boot_linux.py
index ab19146d1e..ee584d2fdf 100644
--- a/tests/avocado/boot_linux.py
+++ b/tests/avocado/boot_linux.py
@@ -79,6 +79,7 @@ class BootLinuxAarch64(LinuxTest):
"""
self.require_accelerator("tcg")
self.vm.add_args("-accel", "tcg")
+ self.vm.add_args("-cpu", "max,lpa2=off")
self.vm.add_args("-machine", "virt,gic-version=2")
self.add_common_args()
self.launch_and_wait(set_up_ssh_connection=False)
@@ -91,6 +92,7 @@ class BootLinuxAarch64(LinuxTest):
"""
self.require_accelerator("tcg")
self.vm.add_args("-accel", "tcg")
+ self.vm.add_args("-cpu", "max,lpa2=off")
self.vm.add_args("-machine", "virt,gic-version=3")
self.add_common_args()
self.launch_and_wait(set_up_ssh_connection=False)
diff --git a/tests/avocado/linux_ssh_mips_malta.py b/tests/avocado/linux_ssh_mips_malta.py
index c0f0be5ade..0179d8a6ca 100644
--- a/tests/avocado/linux_ssh_mips_malta.py
+++ b/tests/avocado/linux_ssh_mips_malta.py
@@ -23,6 +23,9 @@ from avocado.utils import ssh
@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout')
@skipUnless(ssh.SSH_CLIENT_BINARY, 'No SSH client available')
class LinuxSSH(QemuSystemTest, LinuxSSHMixIn):
+ """
+ :avocado: tags=accel:tcg
+ """
timeout = 150 # Not for 'configure --enable-debug --enable-debug-tcg'
diff --git a/tests/bench/atomic_add-bench.c b/tests/bench/atomic_add-bench.c
index f05471ab45..8a6faad6ec 100644
--- a/tests/bench/atomic_add-bench.c
+++ b/tests/bench/atomic_add-bench.c
@@ -2,6 +2,7 @@
#include "qemu/thread.h"
#include "qemu/host-utils.h"
#include "qemu/processor.h"
+#include "qemu/memalign.h"
struct thread_info {
uint64_t r;
diff --git a/tests/bench/qht-bench.c b/tests/bench/qht-bench.c
index 2e5b70ccd0..8afe161d10 100644
--- a/tests/bench/qht-bench.c
+++ b/tests/bench/qht-bench.c
@@ -10,6 +10,7 @@
#include "qemu/qht.h"
#include "qemu/rcu.h"
#include "qemu/xxhash.h"
+#include "qemu/memalign.h"
struct thread_stats {
size_t rd;
diff --git a/tests/data/acpi/q35/FACP b/tests/data/acpi/q35/FACP
index f6a864cc86..a8f6a89611 100644
--- a/tests/data/acpi/q35/FACP
+++ b/tests/data/acpi/q35/FACP
Binary files differ
diff --git a/tests/data/acpi/q35/FACP.nosmm b/tests/data/acpi/q35/FACP.nosmm
index 6a9aa5f370..c4e6d18ee5 100644
--- a/tests/data/acpi/q35/FACP.nosmm
+++ b/tests/data/acpi/q35/FACP.nosmm
Binary files differ
diff --git a/tests/data/acpi/q35/FACP.slic b/tests/data/acpi/q35/FACP.slic
index 15986e095c..48bbb1cf5a 100644
--- a/tests/data/acpi/q35/FACP.slic
+++ b/tests/data/acpi/q35/FACP.slic
Binary files differ
diff --git a/tests/data/acpi/q35/FACP.xapic b/tests/data/acpi/q35/FACP.xapic
index 2d3659c9c6..31fa5dd19c 100644
--- a/tests/data/acpi/q35/FACP.xapic
+++ b/tests/data/acpi/q35/FACP.xapic
Binary files differ
diff --git a/tests/qemu-iotests/172.out b/tests/qemu-iotests/172.out
index 4cf4d536b4..9479b92185 100644
--- a/tests/qemu-iotests/172.out
+++ b/tests/qemu-iotests/172.out
@@ -15,7 +15,6 @@ Testing:
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -43,7 +42,6 @@ Testing: -fda TEST_DIR/t.qcow2
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -81,7 +79,6 @@ Testing: -fdb TEST_DIR/t.qcow2
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -135,7 +132,6 @@ Testing: -fda TEST_DIR/t.qcow2 -fdb TEST_DIR/t.qcow2.2
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -190,7 +186,6 @@ Testing: -fdb
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -230,7 +225,6 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -268,7 +262,6 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2,index=1
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -322,7 +315,6 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=floppy,file=TEST_DIR/t
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -380,7 +372,6 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -418,7 +409,6 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,unit=1
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -456,7 +446,6 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -520,7 +509,6 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -575,7 +563,6 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -630,7 +617,6 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -685,7 +671,6 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -749,7 +734,6 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -804,7 +788,6 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -865,7 +848,6 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -global floppy.drive=none0 -device
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -933,7 +915,6 @@ Testing: -device floppy
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -958,7 +939,6 @@ Testing: -device floppy,drive-type=120
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -983,7 +963,6 @@ Testing: -device floppy,drive-type=144
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -1008,7 +987,6 @@ Testing: -device floppy,drive-type=288
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -1036,7 +1014,6 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,drive-t
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -1074,7 +1051,6 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,drive-t
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -1115,7 +1091,6 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,logical
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
@@ -1153,7 +1128,6 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,physica
fdtypeA = "auto"
fdtypeB = "auto"
fallback = "288"
- isa irq 6
bus: floppy-bus.0
type floppy-bus
dev: floppy, id ""
diff --git a/tests/qtest/virtio-9p-test.c b/tests/qtest/virtio-9p-test.c
index 502e5ad0c7..01ca076afe 100644
--- a/tests/qtest/virtio-9p-test.c
+++ b/tests/qtest/virtio-9p-test.c
@@ -1253,7 +1253,7 @@ static void fs_unlinkat_dir(void *obj, void *data, QGuestAllocator *t_alloc)
/* ... and is actually a directory */
g_assert((st.st_mode & S_IFMT) == S_IFDIR);
- do_unlinkat(v9p, "/", "02", AT_REMOVEDIR);
+ do_unlinkat(v9p, "/", "02", P9_DOTL_AT_REMOVEDIR);
/* directory should be gone now */
g_assert(stat(new_dir, &st) != 0);
}
diff --git a/tests/qtest/virtio-iommu-test.c b/tests/qtest/virtio-iommu-test.c
index 47e68388a0..068e7a9e6c 100644
--- a/tests/qtest/virtio-iommu-test.c
+++ b/tests/qtest/virtio-iommu-test.c
@@ -31,11 +31,13 @@ static void pci_config(void *obj, void *data, QGuestAllocator *t_alloc)
uint64_t input_range_end = qvirtio_config_readq(dev, 16);
uint32_t domain_range_start = qvirtio_config_readl(dev, 24);
uint32_t domain_range_end = qvirtio_config_readl(dev, 28);
+ uint8_t bypass = qvirtio_config_readb(dev, 36);
g_assert_cmpint(input_range_start, ==, 0);
g_assert_cmphex(input_range_end, ==, UINT64_MAX);
g_assert_cmpint(domain_range_start, ==, 0);
g_assert_cmpint(domain_range_end, ==, UINT32_MAX);
+ g_assert_cmpint(bypass, ==, 1);
}
static int read_tail_status(struct virtio_iommu_req_tail *buffer)
diff --git a/tests/tcg/s390x/exrl-trt.c b/tests/tcg/s390x/exrl-trt.c
index 16711a3181..451f777b9d 100644
--- a/tests/tcg/s390x/exrl-trt.c
+++ b/tests/tcg/s390x/exrl-trt.c
@@ -5,8 +5,8 @@ int main(void)
{
char op1[] = "hello";
char op2[256];
- uint64_t r1 = 0xffffffffffffffffull;
- uint64_t r2 = 0xffffffffffffffffull;
+ register uint64_t r1 asm("r1") = 0xffffffffffffffffull;
+ register uint64_t r2 asm("r2") = 0xffffffffffffffffull;
uint64_t cc;
int i;
@@ -21,8 +21,6 @@ int main(void)
" j 2f\n"
"1: trt 0(1,%[op1]),%[op2]\n"
"2: exrl %[op1_len],1b\n"
- " lgr %[r1],%%r1\n"
- " lgr %[r2],%%r2\n"
" ipm %[cc]\n"
: [r1] "+r" (r1),
[r2] "+r" (r2),
@@ -30,7 +28,7 @@ int main(void)
: [op1] "a" (&op1),
[op1_len] "a" (5),
[op2] "Q" (op2)
- : "r1", "r2", "cc");
+ : "cc");
cc = (cc >> 28) & 3;
if (cc != 2) {
write(1, "bad cc\n", 7);
diff --git a/tests/tcg/s390x/exrl-trtr.c b/tests/tcg/s390x/exrl-trtr.c
index 5f30cda6bd..422f7f385a 100644
--- a/tests/tcg/s390x/exrl-trtr.c
+++ b/tests/tcg/s390x/exrl-trtr.c
@@ -5,8 +5,8 @@ int main(void)
{
char op1[] = {0, 1, 2, 3};
char op2[256];
- uint64_t r1 = 0xffffffffffffffffull;
- uint64_t r2 = 0xffffffffffffffffull;
+ register uint64_t r1 asm("r1") = 0xffffffffffffffffull;
+ register uint64_t r2 asm("r2") = 0xffffffffffffffffull;
uint64_t cc;
int i;
@@ -21,8 +21,6 @@ int main(void)
" j 2f\n"
"1: trtr 3(1,%[op1]),%[op2]\n"
"2: exrl %[op1_len],1b\n"
- " lgr %[r1],%%r1\n"
- " lgr %[r2],%%r2\n"
" ipm %[cc]\n"
: [r1] "+r" (r1),
[r2] "+r" (r2),
@@ -30,7 +28,7 @@ int main(void)
: [op1] "a" (&op1),
[op1_len] "a" (3),
[op2] "Q" (op2)
- : "r1", "r2", "cc");
+ : "cc");
cc = (cc >> 28) & 3;
if (cc != 1) {
write(1, "bad cc\n", 7);
diff --git a/tests/tcg/s390x/mie3-mvcrl.c b/tests/tcg/s390x/mie3-mvcrl.c
index 57b08e48d0..93c7b0a290 100644
--- a/tests/tcg/s390x/mie3-mvcrl.c
+++ b/tests/tcg/s390x/mie3-mvcrl.c
@@ -1,15 +1,17 @@
#include <stdint.h>
#include <string.h>
+
static inline void mvcrl_8(const char *dst, const char *src)
{
asm volatile (
- "llill %%r0, 8\n"
- ".insn sse, 0xE50A00000000, 0(%[dst]), 0(%[src])"
- : : [dst] "d" (dst), [src] "d" (src)
- : "memory");
+ "llill %%r0, 8\n"
+ ".insn sse, 0xE50A00000000, 0(%[dst]), 0(%[src])"
+ : : [dst] "d" (dst), [src] "d" (src)
+ : "r0", "memory");
}
+
int main(int argc, char *argv[])
{
const char *alpha = "abcdefghijklmnop";
diff --git a/tests/tcg/s390x/mie3-sel.c b/tests/tcg/s390x/mie3-sel.c
index b0c5c9857d..0dfd532ed4 100644
--- a/tests/tcg/s390x/mie3-sel.c
+++ b/tests/tcg/s390x/mie3-sel.c
@@ -1,32 +1,27 @@
#include <stdint.h>
+
#define Fi3(S, ASM) uint64_t S(uint64_t a, uint64_t b, uint64_t c) \
-{ \
- uint64_t res = 0; \
- asm ( \
- "lg %%r2, %[a]\n" \
- "lg %%r3, %[b]\n" \
- "lg %%r0, %[c]\n" \
- "ltgr %%r0, %%r0\n" \
- ASM \
- "stg %%r0, %[res] " \
- : [res] "=m" (res) \
- : [a] "m" (a), \
- [b] "m" (b), \
- [c] "m" (c) \
- : "r0", "r2", \
- "r3", "r4" \
- ); \
- return res; \
+{ \
+asm volatile ( \
+ "ltgr %[c], %[c]\n" \
+ ASM \
+ : [c] "+r" (c) \
+ : [a] "r" (a) \
+ , [b] "r" (b) \
+); \
+ return c; \
}
-Fi3 (_selre, ".insn rrf, 0xB9F00000, %%r0, %%r3, %%r2, 8\n")
-Fi3 (_selgrz, ".insn rrf, 0xB9E30000, %%r0, %%r3, %%r2, 8\n")
-Fi3 (_selfhrnz, ".insn rrf, 0xB9C00000, %%r0, %%r3, %%r2, 7\n")
+Fi3 (_selre, ".insn rrf, 0xB9F00000, %[c], %[b], %[a], 8\n")
+Fi3 (_selgrz, ".insn rrf, 0xB9E30000, %[c], %[b], %[a], 8\n")
+Fi3 (_selfhrnz, ".insn rrf, 0xB9C00000, %[c], %[b], %[a], 7\n")
+
int main(int argc, char *argv[])
{
uint64_t a = ~0, b = ~0, c = ~0;
+
a = _selre(0x066600000066ull, 0x066600000006ull, a);
b = _selgrz(0xF00D00000005ull, 0xF00D00000055ull, b);
c = _selfhrnz(0x043200000044ull, 0x065400000004ull, c);
diff --git a/tests/tcg/s390x/mvc.c b/tests/tcg/s390x/mvc.c
index aa552d52e5..7ae4c44550 100644
--- a/tests/tcg/s390x/mvc.c
+++ b/tests/tcg/s390x/mvc.c
@@ -20,8 +20,8 @@ static inline void mvc_256(const char *dst, const char *src)
asm volatile (
" mvc 0(256,%[dst]),0(%[src])\n"
:
- : [dst] "d" (dst),
- [src] "d" (src)
+ : [dst] "a" (dst),
+ [src] "a" (src)
: "memory");
}
diff --git a/tests/tcg/s390x/mvo.c b/tests/tcg/s390x/mvo.c
index 5546fe2a97..0c3ecdde2e 100644
--- a/tests/tcg/s390x/mvo.c
+++ b/tests/tcg/s390x/mvo.c
@@ -11,8 +11,8 @@ int main(void)
asm volatile (
" mvo 0(4,%[dest]),0(3,%[src])\n"
:
- : [dest] "d" (dest + 1),
- [src] "d" (src + 1)
+ : [dest] "a" (dest + 1),
+ [src] "a" (src + 1)
: "memory");
for (i = 0; i < sizeof(expected); i++) {
diff --git a/tests/tcg/s390x/pack.c b/tests/tcg/s390x/pack.c
index 4be36f29a7..55e7e214e8 100644
--- a/tests/tcg/s390x/pack.c
+++ b/tests/tcg/s390x/pack.c
@@ -9,7 +9,7 @@ int main(void)
asm volatile(
" pack 2(4,%[data]),2(4,%[data])\n"
:
- : [data] "r" (&data[0])
+ : [data] "a" (&data[0])
: "memory");
for (i = 0; i < 8; i++) {
if (data[i] != exp[i]) {
diff --git a/tests/unit/ptimer-test-stubs.c b/tests/unit/ptimer-test-stubs.c
index 2a3ef58799..f5e75a96b6 100644
--- a/tests/unit/ptimer-test-stubs.c
+++ b/tests/unit/ptimer-test-stubs.c
@@ -12,7 +12,6 @@
#include "qemu/main-loop.h"
#include "sysemu/replay.h"
#include "migration/vmstate.h"
-#include "sysemu/cpu-timers.h"
#include "ptimer-test.h"
diff --git a/tests/vm/haiku.x86_64 b/tests/vm/haiku.x86_64
index 2eb736dae1..936f7d2ae2 100755
--- a/tests/vm/haiku.x86_64
+++ b/tests/vm/haiku.x86_64
@@ -2,7 +2,7 @@
#
# Haiku VM image
#
-# Copyright 2020 Haiku, Inc.
+# Copyright 2020-2022 Haiku, Inc.
#
# Authors:
# Alexander von Gluck IV <kallisti5@unixzen.com>
@@ -48,8 +48,8 @@ class HaikuVM(basevm.BaseVM):
name = "haiku"
arch = "x86_64"
- link = "https://app.vagrantup.com/haiku-os/boxes/r1beta2-x86_64/versions/20200702/providers/libvirt.box"
- csum = "41c38b316e0cbdbc66b5dbaf3612b866700a4f35807cb1eb266a5bf83e9e68d5"
+ link = "https://app.vagrantup.com/haiku-os/boxes/r1beta3-x86_64/versions/20220216/providers/libvirt.box"
+ csum = "e67d4aacbcc687013d5cc91990ddd86cc5d70a5d28432ae2691944f8ce5d5041"
poweroff = "shutdown"
@@ -99,7 +99,7 @@ class HaikuVM(basevm.BaseVM):
self.print_step("Extracting disk image")
- subprocess.check_call(["tar", "xzf", tarball, "./box.img", "-O"],
+ subprocess.check_call(["tar", "xzf", tarball, "box.img", "-O"],
stdout=open(img, 'wb'))
self.print_step("Preparing disk image")
diff --git a/ui/cocoa.m b/ui/cocoa.m
index 8ab9ab5e84..c88149852b 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -83,7 +83,7 @@ static void cocoa_switch(DisplayChangeListener *dcl,
static void cocoa_refresh(DisplayChangeListener *dcl);
-static NSWindow *normalWindow, *about_window;
+static NSWindow *normalWindow;
static const DisplayChangeListenerOps dcl_ops = {
.dpy_name = "cocoa",
.dpy_gfx_update = cocoa_update,
@@ -1140,7 +1140,6 @@ QemuCocoaView *cocoaView;
- (BOOL)verifyQuit;
- (void)openDocumentation:(NSString *)filename;
- (IBAction) do_about_menu_item: (id) sender;
-- (void)make_about_window;
- (void)adjustSpeed:(id)sender;
@end
@@ -1186,8 +1185,6 @@ QemuCocoaView *cocoaView;
[pauseLabel setFont: [NSFont fontWithName: @"Helvetica" size: 90]];
[pauseLabel setTextColor: [NSColor blackColor]];
[pauseLabel sizeToFit];
-
- [self make_about_window];
}
return self;
}
@@ -1471,92 +1468,29 @@ QemuCocoaView *cocoaView;
/* The action method for the About menu item */
- (IBAction) do_about_menu_item: (id) sender
{
- [about_window makeKeyAndOrderFront: nil];
-}
-
-/* Create and display the about dialog */
-- (void)make_about_window
-{
- /* Make the window */
- int x = 0, y = 0, about_width = 400, about_height = 200;
- NSRect window_rect = NSMakeRect(x, y, about_width, about_height);
- about_window = [[NSWindow alloc] initWithContentRect:window_rect
- styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable |
- NSWindowStyleMaskMiniaturizable
- backing:NSBackingStoreBuffered
- defer:NO];
- [about_window setTitle: @"About"];
- [about_window setReleasedWhenClosed: NO];
- [about_window center];
- NSView *superView = [about_window contentView];
-
- /* Create the dimensions of the picture */
- int picture_width = 80, picture_height = 80;
- x = (about_width - picture_width)/2;
- y = about_height - picture_height - 10;
- NSRect picture_rect = NSMakeRect(x, y, picture_width, picture_height);
-
- /* Make the picture of QEMU */
- NSImageView *picture_view = [[NSImageView alloc] initWithFrame:
- picture_rect];
- char *qemu_image_path_c = get_relocated_path(CONFIG_QEMU_ICONDIR "/hicolor/512x512/apps/qemu.png");
- NSString *qemu_image_path = [NSString stringWithUTF8String:qemu_image_path_c];
- g_free(qemu_image_path_c);
- NSImage *qemu_image = [[NSImage alloc] initWithContentsOfFile:qemu_image_path];
- [picture_view setImage: qemu_image];
- [picture_view setImageScaling: NSImageScaleProportionallyUpOrDown];
- [superView addSubview: picture_view];
-
- /* Make the name label */
- NSBundle *bundle = [NSBundle mainBundle];
- if (bundle) {
- x = 0;
- y = y - 25;
- int name_width = about_width, name_height = 20;
- NSRect name_rect = NSMakeRect(x, y, name_width, name_height);
- NSTextField *name_label = [[NSTextField alloc] initWithFrame: name_rect];
- [name_label setEditable: NO];
- [name_label setBezeled: NO];
- [name_label setDrawsBackground: NO];
- [name_label setAlignment: NSTextAlignmentCenter];
- NSString *qemu_name = [[bundle executablePath] lastPathComponent];
- [name_label setStringValue: qemu_name];
- [superView addSubview: name_label];
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ char *icon_path_c = get_relocated_path(CONFIG_QEMU_ICONDIR "/hicolor/512x512/apps/qemu.png");
+ NSString *icon_path = [NSString stringWithUTF8String:icon_path_c];
+ g_free(icon_path_c);
+ NSImage *icon = [[NSImage alloc] initWithContentsOfFile:icon_path];
+ NSString *version = @"QEMU emulator version " QEMU_FULL_VERSION;
+ NSString *copyright = @QEMU_COPYRIGHT;
+ NSDictionary *options;
+ if (icon) {
+ options = @{
+ NSAboutPanelOptionApplicationIcon : icon,
+ NSAboutPanelOptionApplicationVersion : version,
+ @"Copyright" : copyright,
+ };
+ [icon release];
+ } else {
+ options = @{
+ NSAboutPanelOptionApplicationVersion : version,
+ @"Copyright" : copyright,
+ };
}
-
- /* Set the version label's attributes */
- x = 0;
- y = 50;
- int version_width = about_width, version_height = 20;
- NSRect version_rect = NSMakeRect(x, y, version_width, version_height);
- NSTextField *version_label = [[NSTextField alloc] initWithFrame:
- version_rect];
- [version_label setEditable: NO];
- [version_label setBezeled: NO];
- [version_label setAlignment: NSTextAlignmentCenter];
- [version_label setDrawsBackground: NO];
-
- /* Create the version string*/
- NSString *version_string;
- version_string = [[NSString alloc] initWithFormat:
- @"QEMU emulator version %s", QEMU_FULL_VERSION];
- [version_label setStringValue: version_string];
- [superView addSubview: version_label];
-
- /* Make copyright label */
- x = 0;
- y = 35;
- int copyright_width = about_width, copyright_height = 20;
- NSRect copyright_rect = NSMakeRect(x, y, copyright_width, copyright_height);
- NSTextField *copyright_label = [[NSTextField alloc] initWithFrame:
- copyright_rect];
- [copyright_label setEditable: NO];
- [copyright_label setBezeled: NO];
- [copyright_label setDrawsBackground: NO];
- [copyright_label setAlignment: NSTextAlignmentCenter];
- [copyright_label setStringValue: [NSString stringWithFormat: @"%s",
- QEMU_COPYRIGHT]];
- [superView addSubview: copyright_label];
+ [NSApp orderFrontStandardAboutPanelWithOptions:options];
+ [pool release];
}
/* Used by the Speed menu items */
diff --git a/util/atomic64.c b/util/atomic64.c
index 22983a970f..c20d071d8e 100644
--- a/util/atomic64.c
+++ b/util/atomic64.c
@@ -8,6 +8,7 @@
#include "qemu/atomic.h"
#include "qemu/thread.h"
#include "qemu/cacheinfo.h"
+#include "qemu/memalign.h"
#ifdef CONFIG_ATOMIC64
#error This file must only be compiled if !CONFIG_ATOMIC64
diff --git a/util/event_notifier-posix.c b/util/event_notifier-posix.c
index 8307013c5d..16294e98d4 100644
--- a/util/event_notifier-posix.c
+++ b/util/event_notifier-posix.c
@@ -99,6 +99,11 @@ int event_notifier_get_fd(const EventNotifier *e)
return e->rfd;
}
+int event_notifier_get_wfd(const EventNotifier *e)
+{
+ return e->wfd;
+}
+
int event_notifier_set(EventNotifier *e)
{
static const uint64_t value = 1;
diff --git a/util/memalign.c b/util/memalign.c
new file mode 100644
index 0000000000..c199ae7073
--- /dev/null
+++ b/util/memalign.c
@@ -0,0 +1,92 @@
+/*
+ * memalign.c: Allocate an aligned memory region
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (c) 2010-2016 Red Hat, Inc.
+ * Copyright (c) 2022 Linaro Ltd
+ *
+ * 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 "qemu/host-utils.h"
+#include "qemu/memalign.h"
+#include "trace.h"
+
+void *qemu_try_memalign(size_t alignment, size_t size)
+{
+ void *ptr;
+
+ if (alignment < sizeof(void*)) {
+ alignment = sizeof(void*);
+ } else {
+ g_assert(is_power_of_2(alignment));
+ }
+
+ /*
+ * Handling of 0 allocations varies among the different
+ * platform APIs (for instance _aligned_malloc() will
+ * fail) -- ensure that we always return a valid non-NULL
+ * pointer that can be freed by qemu_vfree().
+ */
+ if (size == 0) {
+ size++;
+ }
+#if defined(CONFIG_POSIX_MEMALIGN)
+ int ret;
+ ret = posix_memalign(&ptr, alignment, size);
+ if (ret != 0) {
+ errno = ret;
+ ptr = NULL;
+ }
+#elif defined(CONFIG_ALIGNED_MALLOC)
+ ptr = _aligned_malloc(size, alignment);
+#elif defined(CONFIG_VALLOC)
+ ptr = valloc(size);
+#elif defined(CONFIG_MEMALIGN)
+ ptr = memalign(alignment, size);
+#else
+ #error No function to allocate aligned memory available
+#endif
+ trace_qemu_memalign(alignment, size, ptr);
+ return ptr;
+}
+
+void *qemu_memalign(size_t alignment, size_t size)
+{
+ void *p = qemu_try_memalign(alignment, size);
+ if (p) {
+ return p;
+ }
+ fprintf(stderr,
+ "qemu_memalign: failed to allocate %zu bytes at alignment %zu: %s\n",
+ size, alignment, strerror(errno));
+ abort();
+}
+
+void qemu_vfree(void *ptr)
+{
+ trace_qemu_vfree(ptr);
+#if !defined(CONFIG_POSIX_MEMALIGN) && defined(CONFIG_ALIGNED_MALLOC)
+ /* Only Windows _aligned_malloc needs a special free function */
+ _aligned_free(ptr);
+#else
+ free(ptr);
+#endif
+}
diff --git a/util/meson.build b/util/meson.build
index 3736988b9f..f6ee74ad0c 100644
--- a/util/meson.build
+++ b/util/meson.build
@@ -51,6 +51,7 @@ util_ss.add(when: 'CONFIG_POSIX', if_true: files('drm.c'))
util_ss.add(files('guest-random.c'))
util_ss.add(files('yank.c'))
util_ss.add(files('int128.c'))
+util_ss.add(files('memalign.c'))
if have_user
util_ss.add(files('selfmap.c'))
diff --git a/util/osdep.c b/util/osdep.c
index 723cdcb004..7c4deda6fe 100644
--- a/util/osdep.c
+++ b/util/osdep.c
@@ -33,7 +33,6 @@
extern int madvise(char *, size_t, int);
#endif
-#include <dirent.h>
#include "qemu-common.h"
#include "qemu/cutils.h"
#include "qemu/sockets.h"
@@ -619,23 +618,3 @@ writev(int fd, const struct iovec *iov, int iov_cnt)
return readv_writev(fd, iov, iov_cnt, true);
}
#endif
-
-struct dirent *
-qemu_dirent_dup(struct dirent *dent)
-{
- size_t sz = 0;
-#if defined _DIRENT_HAVE_D_RECLEN
- /* Avoid use of strlen() if platform supports d_reclen. */
- sz = dent->d_reclen;
-#endif
- /*
- * Test sz for zero even if d_reclen is available
- * because some drivers may set d_reclen to zero.
- */
- if (sz == 0) {
- /* Fallback to the most portable way. */
- sz = offsetof(struct dirent, d_name) +
- strlen(dent->d_name) + 1;
- }
- return g_memdup(dent, sz);
-}
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
index f2be7321c5..2ebfb75057 100644
--- a/util/oslib-posix.c
+++ b/util/oslib-posix.c
@@ -199,46 +199,6 @@ fail_close:
return false;
}
-void *qemu_oom_check(void *ptr)
-{
- if (ptr == NULL) {
- fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno));
- abort();
- }
- return ptr;
-}
-
-void *qemu_try_memalign(size_t alignment, size_t size)
-{
- void *ptr;
-
- if (alignment < sizeof(void*)) {
- alignment = sizeof(void*);
- } else {
- g_assert(is_power_of_2(alignment));
- }
-
-#if defined(CONFIG_POSIX_MEMALIGN)
- int ret;
- ret = posix_memalign(&ptr, alignment, size);
- if (ret != 0) {
- errno = ret;
- ptr = NULL;
- }
-#elif defined(CONFIG_BSD)
- ptr = valloc(size);
-#else
- ptr = memalign(alignment, size);
-#endif
- trace_qemu_memalign(alignment, size, ptr);
- return ptr;
-}
-
-void *qemu_memalign(size_t alignment, size_t size)
-{
- return qemu_oom_check(qemu_try_memalign(alignment, size));
-}
-
/* alloc shared memory pages */
void *qemu_anon_ram_alloc(size_t size, uint64_t *alignment, bool shared,
bool noreserve)
@@ -260,12 +220,6 @@ void *qemu_anon_ram_alloc(size_t size, uint64_t *alignment, bool shared,
return ptr;
}
-void qemu_vfree(void *ptr)
-{
- trace_qemu_vfree(ptr);
- free(ptr);
-}
-
void qemu_anon_ram_free(void *ptr, size_t size)
{
trace_qemu_anon_ram_free(ptr, size);
diff --git a/util/oslib-win32.c b/util/oslib-win32.c
index af559ef339..4b1ce0be4b 100644
--- a/util/oslib-win32.c
+++ b/util/oslib-win32.c
@@ -44,35 +44,6 @@
/* this must come after including "trace.h" */
#include <shlobj.h>
-void *qemu_oom_check(void *ptr)
-{
- if (ptr == NULL) {
- fprintf(stderr, "Failed to allocate memory: %lu\n", GetLastError());
- abort();
- }
- return ptr;
-}
-
-void *qemu_try_memalign(size_t alignment, size_t size)
-{
- void *ptr;
-
- g_assert(size != 0);
- if (alignment < sizeof(void *)) {
- alignment = sizeof(void *);
- } else {
- g_assert(is_power_of_2(alignment));
- }
- ptr = _aligned_malloc(size, alignment);
- trace_qemu_memalign(alignment, size, ptr);
- return ptr;
-}
-
-void *qemu_memalign(size_t alignment, size_t size)
-{
- return qemu_oom_check(qemu_try_memalign(alignment, size));
-}
-
static int get_allocation_granularity(void)
{
SYSTEM_INFO system_info;
@@ -104,12 +75,6 @@ void *qemu_anon_ram_alloc(size_t size, uint64_t *align, bool shared,
return ptr;
}
-void qemu_vfree(void *ptr)
-{
- trace_qemu_vfree(ptr);
- _aligned_free(ptr);
-}
-
void qemu_anon_ram_free(void *ptr, size_t size)
{
trace_qemu_anon_ram_free(ptr, size);
diff --git a/util/qht.c b/util/qht.c
index 079605121b..065fc501f4 100644
--- a/util/qht.c
+++ b/util/qht.c
@@ -69,6 +69,7 @@
#include "qemu/qht.h"
#include "qemu/atomic.h"
#include "qemu/rcu.h"
+#include "qemu/memalign.h"
//#define QHT_DEBUG