diff options
-rw-r--r-- | backends/hostmem-shm.c | 123 | ||||
-rw-r--r-- | backends/meson.build | 1 | ||||
-rw-r--r-- | block.c | 90 | ||||
-rw-r--r-- | block/qcow2.c | 17 | ||||
-rw-r--r-- | contrib/vhost-user-blk/vhost-user-blk.c | 13 | ||||
-rw-r--r-- | contrib/vhost-user-input/main.c | 16 | ||||
-rw-r--r-- | docs/pcie_sriov.txt | 8 | ||||
-rw-r--r-- | docs/specs/pvpanic.rst | 2 | ||||
-rw-r--r-- | docs/system/devices/vhost-user.rst | 5 | ||||
-rw-r--r-- | host/include/riscv/host/cpuinfo.h | 23 | ||||
-rw-r--r-- | hw/arm/virt-acpi-build.c | 22 | ||||
-rw-r--r-- | hw/block/vhost-user-blk.c | 6 | ||||
-rw-r--r-- | hw/core/machine.c | 1 | ||||
-rw-r--r-- | hw/cxl/cxl-mailbox-utils.c | 658 | ||||
-rw-r--r-- | hw/display/vhost-user-gpu.c | 5 | ||||
-rw-r--r-- | hw/i386/e820_memory_layout.c | 17 | ||||
-rw-r--r-- | hw/i386/e820_memory_layout.h | 8 | ||||
-rw-r--r-- | hw/i386/fw_cfg.c | 18 | ||||
-rw-r--r-- | hw/i386/fw_cfg.h | 1 | ||||
-rw-r--r-- | hw/i386/microvm.c | 4 | ||||
-rw-r--r-- | hw/i386/pc.c | 1 | ||||
-rw-r--r-- | hw/intc/apic_common.c | 7 | ||||
-rw-r--r-- | hw/mem/cxl_type3.c | 637 | ||||
-rw-r--r-- | hw/mem/cxl_type3_stubs.c | 25 | ||||
-rw-r--r-- | hw/misc/pvpanic-isa.c | 3 | ||||
-rw-r--r-- | hw/misc/pvpanic-pci.c | 2 | ||||
-rw-r--r-- | hw/misc/pvpanic.c | 7 | ||||
-rw-r--r-- | hw/net/igb.c | 13 | ||||
-rw-r--r-- | hw/net/vhost_net.c | 2 | ||||
-rw-r--r-- | hw/net/virtio-net.c | 4 | ||||
-rw-r--r-- | hw/nvme/ctrl.c | 24 | ||||
-rw-r--r-- | hw/pci/pci.c | 29 | ||||
-rw-r--r-- | hw/pci/pci_host.c | 4 | ||||
-rw-r--r-- | hw/pci/pcie_sriov.c | 149 | ||||
-rw-r--r-- | hw/pci/trace-events | 2 | ||||
-rw-r--r-- | hw/ppc/spapr_pci.c | 8 | ||||
-rw-r--r-- | hw/s390x/s390-virtio-ccw.c | 17 | ||||
-rw-r--r-- | hw/scsi/vhost-scsi.c | 1 | ||||
-rw-r--r-- | hw/scsi/vhost-user-scsi.c | 7 | ||||
-rw-r--r-- | hw/virtio/vhost-user-base.c | 7 | ||||
-rw-r--r-- | hw/virtio/vhost-user-fs.c | 2 | ||||
-rw-r--r-- | hw/virtio/vhost-user-vsock.c | 1 | ||||
-rw-r--r-- | hw/virtio/vhost-user.c | 19 | ||||
-rw-r--r-- | hw/virtio/vhost-vsock-common.c | 1 | ||||
-rw-r--r-- | hw/virtio/vhost.c | 112 | ||||
-rw-r--r-- | hw/virtio/virtio-iommu.c | 43 | ||||
-rw-r--r-- | hw/virtio/virtio-mmio.c | 11 | ||||
-rw-r--r-- | hw/virtio/virtio-pci.c | 67 | ||||
-rw-r--r-- | hw/virtio/virtio.c | 46 | ||||
-rw-r--r-- | hw/xen/xen_pt_load_rom.c | 2 | ||||
-rw-r--r-- | include/hw/cxl/cxl_device.h | 85 | ||||
-rw-r--r-- | include/hw/cxl/cxl_events.h | 18 | ||||
-rw-r--r-- | include/hw/misc/pvpanic.h | 6 | ||||
-rw-r--r-- | include/hw/pci/pci.h | 2 | ||||
-rw-r--r-- | include/hw/pci/pci_device.h | 17 | ||||
-rw-r--r-- | include/hw/pci/pcie_sriov.h | 9 | ||||
-rw-r--r-- | include/hw/virtio/vhost-user.h | 3 | ||||
-rw-r--r-- | include/hw/virtio/vhost.h | 1 | ||||
-rw-r--r-- | include/hw/virtio/virtio-pci.h | 5 | ||||
-rw-r--r-- | include/hw/virtio/virtio.h | 10 | ||||
-rw-r--r-- | include/standard-headers/linux/ethtool.h | 55 | ||||
-rw-r--r-- | include/standard-headers/linux/pci_regs.h | 6 | ||||
-rw-r--r-- | include/standard-headers/linux/virtio_bt.h | 1 | ||||
-rw-r--r-- | include/standard-headers/linux/virtio_mem.h | 2 | ||||
-rw-r--r-- | include/standard-headers/linux/virtio_net.h | 143 | ||||
-rw-r--r-- | include/standard-headers/misc/pvpanic.h | 7 | ||||
-rw-r--r-- | include/sysemu/runstate.h | 1 | ||||
-rw-r--r-- | linux-headers/asm-generic/unistd.h | 5 | ||||
-rw-r--r-- | linux-headers/asm-mips/unistd_n32.h | 1 | ||||
-rw-r--r-- | linux-headers/asm-mips/unistd_n64.h | 1 | ||||
-rw-r--r-- | linux-headers/asm-mips/unistd_o32.h | 1 | ||||
-rw-r--r-- | linux-headers/asm-powerpc/unistd_32.h | 1 | ||||
-rw-r--r-- | linux-headers/asm-powerpc/unistd_64.h | 1 | ||||
-rw-r--r-- | linux-headers/asm-s390/unistd_32.h | 1 | ||||
-rw-r--r-- | linux-headers/asm-s390/unistd_64.h | 1 | ||||
-rw-r--r-- | linux-headers/asm-x86/unistd_32.h | 1 | ||||
-rw-r--r-- | linux-headers/asm-x86/unistd_64.h | 1 | ||||
-rw-r--r-- | linux-headers/asm-x86/unistd_x32.h | 2 | ||||
-rw-r--r-- | linux-headers/linux/kvm.h | 4 | ||||
-rw-r--r-- | linux-headers/linux/stddef.h | 8 | ||||
-rw-r--r-- | meson.build | 8 | ||||
-rw-r--r-- | net/vhost-vdpa.c | 16 | ||||
-rw-r--r-- | pc-bios/meson.build | 2 | ||||
-rw-r--r-- | qapi/cxl.json | 189 | ||||
-rw-r--r-- | qapi/qom.json | 27 | ||||
-rw-r--r-- | qapi/run-state.json | 14 | ||||
-rw-r--r-- | qemu-options.hx | 16 | ||||
-rw-r--r-- | subprojects/libvhost-user/libvhost-user.c | 19 | ||||
-rw-r--r-- | system/runstate.c | 6 | ||||
-rw-r--r-- | target/i386/kvm/kvm.c | 6 | ||||
-rw-r--r-- | target/i386/kvm/xen-emu.c | 7 | ||||
-rw-r--r-- | tcg/optimize.c | 2 | ||||
-rw-r--r-- | tcg/riscv/tcg-target.c.inc | 84 | ||||
-rw-r--r-- | tcg/riscv/tcg-target.h | 46 | ||||
-rw-r--r-- | tests/data/acpi/aarch64/virt/APIC (renamed from tests/data/acpi/virt/APIC) | bin | 172 -> 172 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/APIC.acpihmatvirt (renamed from tests/data/acpi/virt/APIC.acpihmatvirt) | bin | 412 -> 412 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/APIC.topology (renamed from tests/data/acpi/virt/APIC.topology) | bin | 732 -> 732 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/DBG2 (renamed from tests/data/acpi/virt/DBG2) | bin | 87 -> 87 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/DSDT (renamed from tests/data/acpi/virt/DSDT) | bin | 5196 -> 5196 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/DSDT.acpihmatvirt (renamed from tests/data/acpi/virt/DSDT.acpihmatvirt) | bin | 5282 -> 5282 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/DSDT.memhp (renamed from tests/data/acpi/virt/DSDT.memhp) | bin | 6557 -> 6557 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/DSDT.pxb (renamed from tests/data/acpi/virt/DSDT.pxb) | bin | 7679 -> 7679 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/DSDT.topology (renamed from tests/data/acpi/virt/DSDT.topology) | bin | 5398 -> 5398 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/FACP (renamed from tests/data/acpi/virt/FACP) | bin | 276 -> 276 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/GTDT (renamed from tests/data/acpi/virt/GTDT) | bin | 104 -> 104 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/HMAT.acpihmatvirt (renamed from tests/data/acpi/virt/HMAT.acpihmatvirt) | bin | 288 -> 288 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/IORT (renamed from tests/data/acpi/virt/IORT) | bin | 128 -> 128 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/MCFG (renamed from tests/data/acpi/virt/MCFG) | bin | 60 -> 60 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/NFIT.memhp (renamed from tests/data/acpi/virt/NFIT.memhp) | bin | 224 -> 224 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/PPTT (renamed from tests/data/acpi/virt/PPTT) | bin | 76 -> 76 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/PPTT.acpihmatvirt (renamed from tests/data/acpi/virt/PPTT.acpihmatvirt) | bin | 156 -> 156 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/PPTT.topology (renamed from tests/data/acpi/virt/PPTT.topology) | bin | 336 -> 336 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/SLIT.memhp (renamed from tests/data/acpi/pc/SLIT.memhp) | bin | 48 -> 48 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/SPCR (renamed from tests/data/acpi/virt/SPCR) | bin | 80 -> 80 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/SRAT.acpihmatvirt (renamed from tests/data/acpi/virt/SRAT.acpihmatvirt) | bin | 240 -> 240 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/SRAT.memhp (renamed from tests/data/acpi/virt/SRAT.memhp) | bin | 226 -> 226 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/SRAT.numamem (renamed from tests/data/acpi/virt/SRAT.numamem) | bin | 106 -> 106 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/SSDT.memhp (renamed from tests/data/acpi/virt/SSDT.memhp) | bin | 1817 -> 1817 bytes | |||
-rw-r--r-- | tests/data/acpi/aarch64/virt/VIOT (renamed from tests/data/acpi/virt/VIOT) | bin | 88 -> 88 bytes | |||
-rwxr-xr-x | tests/data/acpi/rebuild-expected-aml.sh | 5 | ||||
-rw-r--r-- | tests/data/acpi/x86/microvm/APIC (renamed from tests/data/acpi/microvm/APIC) | bin | 70 -> 70 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/microvm/APIC.ioapic2 (renamed from tests/data/acpi/microvm/APIC.ioapic2) | bin | 82 -> 82 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/microvm/APIC.pcie (renamed from tests/data/acpi/microvm/APIC.pcie) | bin | 110 -> 110 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/microvm/DSDT (renamed from tests/data/acpi/microvm/DSDT) | bin | 365 -> 365 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/microvm/DSDT.ioapic2 (renamed from tests/data/acpi/microvm/DSDT.ioapic2) | bin | 365 -> 365 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/microvm/DSDT.pcie (renamed from tests/data/acpi/microvm/DSDT.pcie) | bin | 3023 -> 3023 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/microvm/DSDT.rtc (renamed from tests/data/acpi/microvm/DSDT.rtc) | bin | 404 -> 404 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/microvm/DSDT.usb (renamed from tests/data/acpi/microvm/DSDT.usb) | bin | 414 -> 414 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/microvm/ERST.pcie (renamed from tests/data/acpi/microvm/ERST.pcie) | bin | 912 -> 912 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/microvm/FACP (renamed from tests/data/acpi/microvm/FACP) | bin | 268 -> 268 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/APIC (renamed from tests/data/acpi/pc/APIC) | bin | 120 -> 120 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/APIC.acpihmat (renamed from tests/data/acpi/pc/APIC.acpihmat) | bin | 128 -> 128 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/APIC.cphp (renamed from tests/data/acpi/pc/APIC.cphp) | bin | 160 -> 160 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/APIC.dimmpxm (renamed from tests/data/acpi/pc/APIC.dimmpxm) | bin | 144 -> 144 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/DSDT (renamed from tests/data/acpi/pc/DSDT) | bin | 6830 -> 6830 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/DSDT.acpierst (renamed from tests/data/acpi/pc/DSDT.acpierst) | bin | 6741 -> 6741 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/DSDT.acpihmat (renamed from tests/data/acpi/pc/DSDT.acpihmat) | bin | 8155 -> 8155 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/DSDT.bridge (renamed from tests/data/acpi/pc/DSDT.bridge) | bin | 13701 -> 13701 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/DSDT.cphp (renamed from tests/data/acpi/pc/DSDT.cphp) | bin | 7294 -> 7294 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/DSDT.dimmpxm (renamed from tests/data/acpi/pc/DSDT.dimmpxm) | bin | 8484 -> 8484 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/DSDT.hpbridge (renamed from tests/data/acpi/pc/DSDT.hpbridge) | bin | 6781 -> 6781 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/DSDT.hpbrroot (renamed from tests/data/acpi/pc/DSDT.hpbrroot) | bin | 3337 -> 3337 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/DSDT.ipmikcs (renamed from tests/data/acpi/pc/DSDT.ipmikcs) | bin | 6902 -> 6902 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/DSDT.memhp (renamed from tests/data/acpi/pc/DSDT.memhp) | bin | 8189 -> 8189 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/DSDT.nohpet (renamed from tests/data/acpi/pc/DSDT.nohpet) | bin | 6688 -> 6688 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/DSDT.numamem (renamed from tests/data/acpi/pc/DSDT.numamem) | bin | 6836 -> 6836 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/DSDT.roothp (renamed from tests/data/acpi/pc/DSDT.roothp) | bin | 10623 -> 10623 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/ERST.acpierst (renamed from tests/data/acpi/pc/ERST.acpierst) | bin | 912 -> 912 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/FACP (renamed from tests/data/acpi/pc/FACP) | bin | 116 -> 116 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/FACP.nosmm (renamed from tests/data/acpi/pc/FACP.nosmm) | bin | 116 -> 116 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/FACS (renamed from tests/data/acpi/pc/FACS) | bin | 64 -> 64 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/HMAT.acpihmat (renamed from tests/data/acpi/pc/HMAT.acpihmat) | bin | 280 -> 280 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/HPET (renamed from tests/data/acpi/pc/HPET) | bin | 56 -> 56 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/NFIT.dimmpxm (renamed from tests/data/acpi/pc/NFIT.dimmpxm) | bin | 240 -> 240 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/SLIT.cphp (renamed from tests/data/acpi/pc/SLIT.cphp) | bin | 48 -> 48 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/SLIT.memhp (renamed from tests/data/acpi/q35/SLIT.memhp) | bin | 48 -> 48 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/SRAT.acpihmat (renamed from tests/data/acpi/pc/SRAT.acpihmat) | bin | 280 -> 280 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/SRAT.cphp (renamed from tests/data/acpi/pc/SRAT.cphp) | bin | 304 -> 304 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/SRAT.dimmpxm (renamed from tests/data/acpi/pc/SRAT.dimmpxm) | bin | 392 -> 392 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/SRAT.memhp (renamed from tests/data/acpi/pc/SRAT.memhp) | bin | 264 -> 264 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/SRAT.numamem (renamed from tests/data/acpi/pc/SRAT.numamem) | bin | 224 -> 224 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/SSDT.dimmpxm (renamed from tests/data/acpi/pc/SSDT.dimmpxm) | bin | 1815 -> 1815 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/pc/WAET (renamed from tests/data/acpi/pc/WAET) | bin | 40 -> 40 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/APIC (renamed from tests/data/acpi/q35/APIC) | bin | 120 -> 120 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/APIC.acpihmat (renamed from tests/data/acpi/q35/APIC.acpihmat) | bin | 128 -> 128 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/APIC.acpihmat-noinitiator (renamed from tests/data/acpi/q35/APIC.acpihmat-noinitiator) | bin | 144 -> 144 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/APIC.core-count (renamed from tests/data/acpi/q35/APIC.core-count) | bin | 544 -> 544 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/APIC.core-count2 (renamed from tests/data/acpi/q35/APIC.core-count2) | bin | 3238 -> 3238 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/APIC.cphp (renamed from tests/data/acpi/q35/APIC.cphp) | bin | 160 -> 160 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/APIC.dimmpxm (renamed from tests/data/acpi/q35/APIC.dimmpxm) | bin | 144 -> 144 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/APIC.thread-count (renamed from tests/data/acpi/q35/APIC.thread-count) | bin | 544 -> 544 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/APIC.thread-count2 (renamed from tests/data/acpi/q35/APIC.thread-count2) | bin | 3238 -> 3238 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/APIC.type4-count (renamed from tests/data/acpi/q35/APIC.type4-count) | bin | 1072 -> 1072 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/APIC.xapic (renamed from tests/data/acpi/q35/APIC.xapic) | bin | 2686 -> 2686 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/CEDT.cxl (renamed from tests/data/acpi/q35/CEDT.cxl) | bin | 184 -> 184 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DMAR.dmar (renamed from tests/data/acpi/q35/DMAR.dmar) | bin | 120 -> 120 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT (renamed from tests/data/acpi/q35/DSDT) | bin | 8355 -> 8355 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.acpierst (renamed from tests/data/acpi/q35/DSDT.acpierst) | bin | 8372 -> 8372 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.acpihmat (renamed from tests/data/acpi/q35/DSDT.acpihmat) | bin | 9680 -> 9680 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.acpihmat-noinitiator (renamed from tests/data/acpi/q35/DSDT.acpihmat-noinitiator) | bin | 8634 -> 8634 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.applesmc (renamed from tests/data/acpi/q35/DSDT.applesmc) | bin | 8401 -> 8401 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.bridge (renamed from tests/data/acpi/q35/DSDT.bridge) | bin | 11968 -> 11968 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.core-count (renamed from tests/data/acpi/q35/DSDT.core-count) | bin | 12913 -> 12913 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.core-count2 (renamed from tests/data/acpi/q35/DSDT.core-count2) | bin | 33770 -> 33770 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.cphp (renamed from tests/data/acpi/q35/DSDT.cphp) | bin | 8819 -> 8819 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.cxl (renamed from tests/data/acpi/q35/DSDT.cxl) | bin | 9714 -> 9714 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.dimmpxm (renamed from tests/data/acpi/q35/DSDT.dimmpxm) | bin | 10009 -> 10009 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.ipmibt (renamed from tests/data/acpi/q35/DSDT.ipmibt) | bin | 8430 -> 8430 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.ipmismbus (renamed from tests/data/acpi/q35/DSDT.ipmismbus) | bin | 8443 -> 8443 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.ivrs (renamed from tests/data/acpi/q35/DSDT.ivrs) | bin | 8372 -> 8372 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.memhp (renamed from tests/data/acpi/q35/DSDT.memhp) | bin | 9714 -> 9714 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.mmio64 (renamed from tests/data/acpi/q35/DSDT.mmio64) | bin | 9485 -> 9485 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.multi-bridge (renamed from tests/data/acpi/q35/DSDT.multi-bridge) | bin | 13208 -> 13208 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.noacpihp (renamed from tests/data/acpi/q35/DSDT.noacpihp) | bin | 8235 -> 8235 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.nohpet (renamed from tests/data/acpi/q35/DSDT.nohpet) | bin | 8213 -> 8213 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.numamem (renamed from tests/data/acpi/q35/DSDT.numamem) | bin | 8361 -> 8361 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.pvpanic-isa (renamed from tests/data/acpi/q35/DSDT.pvpanic-isa) | bin | 8456 -> 8456 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.thread-count (renamed from tests/data/acpi/q35/DSDT.thread-count) | bin | 12913 -> 12913 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.thread-count2 (renamed from tests/data/acpi/q35/DSDT.thread-count2) | bin | 33770 -> 33770 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.tis.tpm12 (renamed from tests/data/acpi/q35/DSDT.tis.tpm12) | bin | 8961 -> 8961 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.tis.tpm2 (renamed from tests/data/acpi/q35/DSDT.tis.tpm2) | bin | 8987 -> 8987 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.type4-count (renamed from tests/data/acpi/q35/DSDT.type4-count) | bin | 18589 -> 18589 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.viot (renamed from tests/data/acpi/q35/DSDT.viot) | bin | 9464 -> 9464 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/DSDT.xapic (renamed from tests/data/acpi/q35/DSDT.xapic) | bin | 35718 -> 35718 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/ERST.acpierst (renamed from tests/data/acpi/q35/ERST.acpierst) | bin | 912 -> 912 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/FACP (renamed from tests/data/acpi/q35/FACP) | bin | 244 -> 244 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/FACP.core-count (renamed from tests/data/acpi/q35/FACP.core-count) | bin | 244 -> 244 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/FACP.core-count2 (renamed from tests/data/acpi/q35/FACP.core-count2) | bin | 244 -> 244 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/FACP.nosmm (renamed from tests/data/acpi/q35/FACP.nosmm) | bin | 244 -> 244 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/FACP.slic (renamed from tests/data/acpi/q35/FACP.slic) | bin | 244 -> 244 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/FACP.thread-count (renamed from tests/data/acpi/q35/FACP.thread-count) | bin | 244 -> 244 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/FACP.thread-count2 (renamed from tests/data/acpi/q35/FACP.thread-count2) | bin | 244 -> 244 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/FACP.type4-count (renamed from tests/data/acpi/q35/FACP.type4-count) | bin | 244 -> 244 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/FACP.xapic (renamed from tests/data/acpi/q35/FACP.xapic) | bin | 244 -> 244 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/FACS (renamed from tests/data/acpi/q35/FACS) | bin | 64 -> 64 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/HMAT.acpihmat (renamed from tests/data/acpi/q35/HMAT.acpihmat) | bin | 280 -> 280 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/HMAT.acpihmat-noinitiator (renamed from tests/data/acpi/q35/HMAT.acpihmat-noinitiator) | bin | 288 -> 288 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/HPET (renamed from tests/data/acpi/q35/HPET) | bin | 56 -> 56 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/IVRS.ivrs (renamed from tests/data/acpi/q35/IVRS.ivrs) | bin | 176 -> 176 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/MCFG (renamed from tests/data/acpi/q35/MCFG) | bin | 60 -> 60 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/NFIT.dimmpxm (renamed from tests/data/acpi/q35/NFIT.dimmpxm) | bin | 240 -> 240 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/SLIC.slic (renamed from tests/data/acpi/q35/SLIC.slic) | bin | 36 -> 36 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/SLIT.cphp (renamed from tests/data/acpi/q35/SLIT.cphp) | bin | 48 -> 48 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/SLIT.memhp (renamed from tests/data/acpi/virt/SLIT.memhp) | bin | 48 -> 48 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/SRAT.acpihmat (renamed from tests/data/acpi/q35/SRAT.acpihmat) | bin | 280 -> 280 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/SRAT.acpihmat-noinitiator (renamed from tests/data/acpi/q35/SRAT.acpihmat-noinitiator) | bin | 312 -> 312 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/SRAT.cphp (renamed from tests/data/acpi/q35/SRAT.cphp) | bin | 304 -> 304 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/SRAT.dimmpxm (renamed from tests/data/acpi/q35/SRAT.dimmpxm) | bin | 392 -> 392 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/SRAT.memhp (renamed from tests/data/acpi/q35/SRAT.memhp) | bin | 264 -> 264 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/SRAT.mmio64 (renamed from tests/data/acpi/q35/SRAT.mmio64) | bin | 224 -> 224 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/SRAT.numamem (renamed from tests/data/acpi/q35/SRAT.numamem) | bin | 224 -> 224 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/SRAT.xapic (renamed from tests/data/acpi/q35/SRAT.xapic) | bin | 5080 -> 5080 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/SSDT.dimmpxm (renamed from tests/data/acpi/q35/SSDT.dimmpxm) | bin | 1815 -> 1815 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/TCPA.tis.tpm12 (renamed from tests/data/acpi/q35/TCPA.tis.tpm12) | bin | 50 -> 50 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/TPM2.tis.tpm2 (renamed from tests/data/acpi/q35/TPM2.tis.tpm2) | bin | 76 -> 76 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/VIOT.viot (renamed from tests/data/acpi/q35/VIOT.viot) | bin | 112 -> 112 bytes | |||
-rw-r--r-- | tests/data/acpi/x86/q35/WAET (renamed from tests/data/acpi/q35/WAET) | bin | 40 -> 40 bytes | |||
-rw-r--r-- | tests/data/uefi-boot-images/bios-tables-test.riscv64.iso.qcow2 | bin | 0 -> 16896 bytes | |||
-rwxr-xr-x | tests/qemu-iotests/061 | 6 | ||||
-rw-r--r-- | tests/qemu-iotests/061.out | 8 | ||||
-rwxr-xr-x | tests/qemu-iotests/244 | 19 | ||||
-rwxr-xr-x | tests/qemu-iotests/270 | 14 | ||||
-rw-r--r-- | tests/qtest/bios-tables-test.c | 143 | ||||
-rw-r--r-- | tests/qtest/meson.build | 3 | ||||
-rw-r--r-- | tests/qtest/pvpanic-pci-test.c | 44 | ||||
-rw-r--r-- | tests/qtest/pvpanic-test.c | 34 | ||||
-rw-r--r-- | tests/qtest/vhost-user-blk-test.c | 2 | ||||
-rw-r--r-- | tests/qtest/vhost-user-test.c | 28 | ||||
-rw-r--r-- | tests/tcg/x86_64/Makefile.target | 2 | ||||
-rw-r--r-- | tests/tcg/x86_64/test-2413.c | 30 | ||||
-rw-r--r-- | tests/uefi-test-tools/Makefile | 19 | ||||
-rw-r--r-- | tests/uefi-test-tools/UefiTestToolsPkg/UefiTestToolsPkg.dsc | 6 | ||||
-rw-r--r-- | tests/uefi-test-tools/uefi-test-build.config | 52 | ||||
-rw-r--r-- | util/cpuinfo-aarch64.c | 36 | ||||
-rw-r--r-- | util/cpuinfo-ppc.c | 27 | ||||
-rw-r--r-- | util/cpuinfo-riscv.c | 118 | ||||
-rw-r--r-- | util/meson.build | 2 | ||||
-rw-r--r-- | util/vhost-user-server.c | 12 |
258 files changed, 3227 insertions, 515 deletions
diff --git a/backends/hostmem-shm.c b/backends/hostmem-shm.c new file mode 100644 index 0000000000..374edc3db8 --- /dev/null +++ b/backends/hostmem-shm.c @@ -0,0 +1,123 @@ +/* + * QEMU host POSIX shared memory object backend + * + * Copyright (C) 2024 Red Hat Inc + * + * Authors: + * Stefano Garzarella <sgarzare@redhat.com> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "sysemu/hostmem.h" +#include "qapi/error.h" + +#define TYPE_MEMORY_BACKEND_SHM "memory-backend-shm" + +OBJECT_DECLARE_SIMPLE_TYPE(HostMemoryBackendShm, MEMORY_BACKEND_SHM) + +struct HostMemoryBackendShm { + HostMemoryBackend parent_obj; +}; + +static bool +shm_backend_memory_alloc(HostMemoryBackend *backend, Error **errp) +{ + g_autoptr(GString) shm_name = g_string_new(NULL); + g_autofree char *backend_name = NULL; + uint32_t ram_flags; + int fd, oflag; + mode_t mode; + + if (!backend->size) { + error_setg(errp, "can't create shm backend with size 0"); + return false; + } + + if (!backend->share) { + error_setg(errp, "can't create shm backend with `share=off`"); + return false; + } + + /* + * Let's use `mode = 0` because we don't want other processes to open our + * memory unless we share the file descriptor with them. + */ + mode = 0; + oflag = O_RDWR | O_CREAT | O_EXCL; + backend_name = host_memory_backend_get_name(backend); + + /* + * Some operating systems allow creating anonymous POSIX shared memory + * objects (e.g. FreeBSD provides the SHM_ANON constant), but this is not + * defined by POSIX, so let's create a unique name. + * + * From Linux's shm_open(3) man-page: + * For portable use, a shared memory object should be identified + * by a name of the form /somename;" + */ + g_string_printf(shm_name, "/qemu-" FMT_pid "-shm-%s", getpid(), + backend_name); + + fd = shm_open(shm_name->str, oflag, mode); + if (fd < 0) { + error_setg_errno(errp, errno, + "failed to create POSIX shared memory"); + return false; + } + + /* + * We have the file descriptor, so we no longer need to expose the + * POSIX shared memory object. However it will remain allocated as long as + * there are file descriptors pointing to it. + */ + shm_unlink(shm_name->str); + + if (ftruncate(fd, backend->size) == -1) { + error_setg_errno(errp, errno, + "failed to resize POSIX shared memory to %" PRIu64, + backend->size); + close(fd); + return false; + } + + ram_flags = RAM_SHARED; + ram_flags |= backend->reserve ? 0 : RAM_NORESERVE; + + return memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend), + backend_name, backend->size, + ram_flags, fd, 0, errp); +} + +static void +shm_backend_instance_init(Object *obj) +{ + HostMemoryBackendShm *m = MEMORY_BACKEND_SHM(obj); + + MEMORY_BACKEND(m)->share = true; +} + +static void +shm_backend_class_init(ObjectClass *oc, void *data) +{ + HostMemoryBackendClass *bc = MEMORY_BACKEND_CLASS(oc); + + bc->alloc = shm_backend_memory_alloc; +} + +static const TypeInfo shm_backend_info = { + .name = TYPE_MEMORY_BACKEND_SHM, + .parent = TYPE_MEMORY_BACKEND, + .instance_init = shm_backend_instance_init, + .class_init = shm_backend_class_init, + .instance_size = sizeof(HostMemoryBackendShm), +}; + +static void register_types(void) +{ + type_register_static(&shm_backend_info); +} + +type_init(register_types); diff --git a/backends/meson.build b/backends/meson.build index 106312f0c8..749b491f12 100644 --- a/backends/meson.build +++ b/backends/meson.build @@ -13,6 +13,7 @@ system_ss.add([files( if host_os != 'windows' system_ss.add(files('rng-random.c')) system_ss.add(files('hostmem-file.c')) + system_ss.add([files('hostmem-shm.c'), rt]) endif if host_os == 'linux' system_ss.add(files('hostmem-memfd.c')) @@ -86,6 +86,7 @@ static BlockDriverState *bdrv_open_inherit(const char *filename, BlockDriverState *parent, const BdrvChildClass *child_class, BdrvChildRole child_role, + bool parse_filename, Error **errp); static bool bdrv_recurse_has_child(BlockDriverState *bs, @@ -2055,7 +2056,8 @@ static void parse_json_protocol(QDict *options, const char **pfilename, * block driver has been specified explicitly. */ static int bdrv_fill_options(QDict **options, const char *filename, - int *flags, Error **errp) + int *flags, bool allow_parse_filename, + Error **errp) { const char *drvname; bool protocol = *flags & BDRV_O_PROTOCOL; @@ -2097,7 +2099,7 @@ static int bdrv_fill_options(QDict **options, const char *filename, if (protocol && filename) { if (!qdict_haskey(*options, "filename")) { qdict_put_str(*options, "filename", filename); - parse_filename = true; + parse_filename = allow_parse_filename; } else { error_setg(errp, "Can't specify 'file' and 'filename' options at " "the same time"); @@ -3660,7 +3662,8 @@ int bdrv_open_backing_file(BlockDriverState *bs, QDict *parent_options, } backing_hd = bdrv_open_inherit(backing_filename, reference, options, 0, bs, - &child_of_bds, bdrv_backing_role(bs), errp); + &child_of_bds, bdrv_backing_role(bs), true, + errp); if (!backing_hd) { bs->open_flags |= BDRV_O_NO_BACKING; error_prepend(errp, "Could not open backing file: "); @@ -3694,7 +3697,8 @@ free_exit: static BlockDriverState * bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key, BlockDriverState *parent, const BdrvChildClass *child_class, - BdrvChildRole child_role, bool allow_none, Error **errp) + BdrvChildRole child_role, bool allow_none, + bool parse_filename, Error **errp) { BlockDriverState *bs = NULL; QDict *image_options; @@ -3725,7 +3729,8 @@ bdrv_open_child_bs(const char *filename, QDict *options, const char *bdref_key, } bs = bdrv_open_inherit(filename, reference, image_options, 0, - parent, child_class, child_role, errp); + parent, child_class, child_role, parse_filename, + errp); if (!bs) { goto done; } @@ -3735,6 +3740,33 @@ done: return bs; } +static BdrvChild *bdrv_open_child_common(const char *filename, + QDict *options, const char *bdref_key, + BlockDriverState *parent, + const BdrvChildClass *child_class, + BdrvChildRole child_role, + bool allow_none, bool parse_filename, + Error **errp) +{ + BlockDriverState *bs; + BdrvChild *child; + + GLOBAL_STATE_CODE(); + + bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class, + child_role, allow_none, parse_filename, errp); + if (bs == NULL) { + return NULL; + } + + bdrv_graph_wrlock(); + child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role, + errp); + bdrv_graph_wrunlock(); + + return child; +} + /* * Opens a disk image whose options are given as BlockdevRef in another block * device's options. @@ -3758,27 +3790,15 @@ BdrvChild *bdrv_open_child(const char *filename, BdrvChildRole child_role, bool allow_none, Error **errp) { - BlockDriverState *bs; - BdrvChild *child; - - GLOBAL_STATE_CODE(); - - bs = bdrv_open_child_bs(filename, options, bdref_key, parent, child_class, - child_role, allow_none, errp); - if (bs == NULL) { - return NULL; - } - - bdrv_graph_wrlock(); - child = bdrv_attach_child(parent, bs, bdref_key, child_class, child_role, - errp); - bdrv_graph_wrunlock(); - - return child; + return bdrv_open_child_common(filename, options, bdref_key, parent, + child_class, child_role, allow_none, false, + errp); } /* - * Wrapper on bdrv_open_child() for most popular case: open primary child of bs. + * This does mostly the same as bdrv_open_child(), but for opening the primary + * child of a node. A notable difference from bdrv_open_child() is that it + * enables filename parsing for protocol names (including json:). * * @parent can move to a different AioContext in this function. */ @@ -3793,8 +3813,8 @@ int bdrv_open_file_child(const char *filename, role = parent->drv->is_filter ? (BDRV_CHILD_FILTERED | BDRV_CHILD_PRIMARY) : BDRV_CHILD_IMAGE; - if (!bdrv_open_child(filename, options, bdref_key, parent, - &child_of_bds, role, false, errp)) + if (!bdrv_open_child_common(filename, options, bdref_key, parent, + &child_of_bds, role, false, true, errp)) { return -EINVAL; } @@ -3839,7 +3859,8 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp) } - bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, errp); + bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, 0, false, + errp); obj = NULL; qobject_unref(obj); visit_free(v); @@ -3929,7 +3950,7 @@ static BlockDriverState * no_coroutine_fn bdrv_open_inherit(const char *filename, const char *reference, QDict *options, int flags, BlockDriverState *parent, const BdrvChildClass *child_class, BdrvChildRole child_role, - Error **errp) + bool parse_filename, Error **errp) { int ret; BlockBackend *file = NULL; @@ -3977,9 +3998,11 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options, } /* json: syntax counts as explicit options, as if in the QDict */ - parse_json_protocol(options, &filename, &local_err); - if (local_err) { - goto fail; + if (parse_filename) { + parse_json_protocol(options, &filename, &local_err); + if (local_err) { + goto fail; + } } bs->explicit_options = qdict_clone_shallow(options); @@ -4004,7 +4027,8 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options, parent->open_flags, parent->options); } - ret = bdrv_fill_options(&options, filename, &flags, &local_err); + ret = bdrv_fill_options(&options, filename, &flags, parse_filename, + &local_err); if (ret < 0) { goto fail; } @@ -4073,7 +4097,7 @@ bdrv_open_inherit(const char *filename, const char *reference, QDict *options, file_bs = bdrv_open_child_bs(filename, options, "file", bs, &child_of_bds, BDRV_CHILD_IMAGE, - true, &local_err); + true, true, &local_err); if (local_err) { goto fail; } @@ -4222,7 +4246,7 @@ BlockDriverState *bdrv_open(const char *filename, const char *reference, GLOBAL_STATE_CODE(); return bdrv_open_inherit(filename, reference, options, flags, NULL, - NULL, 0, errp); + NULL, 0, true, errp); } /* Return true if the NULL-terminated @list contains @str */ diff --git a/block/qcow2.c b/block/qcow2.c index 10883a2494..70b19730a3 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1636,7 +1636,22 @@ qcow2_do_open(BlockDriverState *bs, QDict *options, int flags, goto fail; } - if (open_data_file) { + if (open_data_file && (flags & BDRV_O_NO_IO)) { + /* + * Don't open the data file for 'qemu-img info' so that it can be used + * to verify that an untrusted qcow2 image doesn't refer to external + * files. + * + * Note: This still makes has_data_file() return true. + */ + if (s->incompatible_features & QCOW2_INCOMPAT_DATA_FILE) { + s->data_file = NULL; + } else { + s->data_file = bs->file; + } + qdict_extract_subqdict(options, NULL, "data-file."); + qdict_del(options, "data-file"); + } else if (open_data_file) { /* Open external data file */ bdrv_graph_co_rdunlock(); s->data_file = bdrv_co_open_child(NULL, options, "data-file", bs, diff --git a/contrib/vhost-user-blk/vhost-user-blk.c b/contrib/vhost-user-blk/vhost-user-blk.c index 89e5f11a64..9492146855 100644 --- a/contrib/vhost-user-blk/vhost-user-blk.c +++ b/contrib/vhost-user-blk/vhost-user-blk.c @@ -16,6 +16,7 @@ */ #include "qemu/osdep.h" +#include "qemu/bswap.h" #include "standard-headers/linux/virtio_blk.h" #include "libvhost-user-glib.h" @@ -194,8 +195,8 @@ vub_discard_write_zeroes(VubReq *req, struct iovec *iov, uint32_t iovcnt, #if defined(__linux__) && defined(BLKDISCARD) && defined(BLKZEROOUT) VubDev *vdev_blk = req->vdev_blk; desc = buf; - uint64_t range[2] = { le64toh(desc->sector) << 9, - le32toh(desc->num_sectors) << 9 }; + uint64_t range[2] = { le64_to_cpu(desc->sector) << 9, + le32_to_cpu(desc->num_sectors) << 9 }; if (type == VIRTIO_BLK_T_DISCARD) { if (ioctl(vdev_blk->blk_fd, BLKDISCARD, range) == 0) { g_free(buf); @@ -267,13 +268,13 @@ static int vub_virtio_process_req(VubDev *vdev_blk, req->in = (struct virtio_blk_inhdr *)elem->in_sg[in_num - 1].iov_base; in_num--; - type = le32toh(req->out->type); + type = le32_to_cpu(req->out->type); switch (type & ~VIRTIO_BLK_T_BARRIER) { case VIRTIO_BLK_T_IN: case VIRTIO_BLK_T_OUT: { ssize_t ret = 0; bool is_write = type & VIRTIO_BLK_T_OUT; - req->sector_num = le64toh(req->out->sector); + req->sector_num = le64_to_cpu(req->out->sector); if (is_write) { ret = vub_writev(req, &elem->out_sg[1], out_num); } else { @@ -469,7 +470,6 @@ static int unix_sock_new(char *unix_fn) { int sock; struct sockaddr_un un; - size_t len; assert(unix_fn); @@ -481,10 +481,9 @@ static int unix_sock_new(char *unix_fn) un.sun_family = AF_UNIX; (void)snprintf(un.sun_path, sizeof(un.sun_path), "%s", unix_fn); - len = sizeof(un.sun_family) + strlen(un.sun_path); (void)unlink(unix_fn); - if (bind(sock, (struct sockaddr *)&un, len) < 0) { + if (bind(sock, (struct sockaddr *)&un, sizeof(un)) < 0) { perror("bind"); goto fail; } diff --git a/contrib/vhost-user-input/main.c b/contrib/vhost-user-input/main.c index 081230da54..f3362d41ac 100644 --- a/contrib/vhost-user-input/main.c +++ b/contrib/vhost-user-input/main.c @@ -51,8 +51,8 @@ static void vi_input_send(VuInput *vi, struct virtio_input_event *event) vi->queue[vi->qindex++].event = *event; /* ... until we see a report sync ... */ - if (event->type != htole16(EV_SYN) || - event->code != htole16(SYN_REPORT)) { + if (event->type != cpu_to_le16(EV_SYN) || + event->code != cpu_to_le16(SYN_REPORT)) { return; } @@ -103,9 +103,9 @@ vi_evdev_watch(VuDev *dev, int condition, void *data) g_debug("input %d %d %d", evdev.type, evdev.code, evdev.value); - virtio.type = htole16(evdev.type); - virtio.code = htole16(evdev.code); - virtio.value = htole32(evdev.value); + virtio.type = cpu_to_le16(evdev.type); + virtio.code = cpu_to_le16(evdev.code); + virtio.value = cpu_to_le32(evdev.value); vi_input_send(vi, &virtio); } } @@ -124,9 +124,9 @@ static void vi_handle_status(VuInput *vi, virtio_input_event *event) evdev.input_event_sec = tval.tv_sec; evdev.input_event_usec = tval.tv_usec; - evdev.type = le16toh(event->type); - evdev.code = le16toh(event->code); - evdev.value = le32toh(event->value); + evdev.type = le16_to_cpu(event->type); + evdev.code = le16_to_cpu(event->code); + evdev.value = le32_to_cpu(event->value); rc = write(vi->evdevfd, &evdev, sizeof(evdev)); if (rc == -1) { diff --git a/docs/pcie_sriov.txt b/docs/pcie_sriov.txt index a47aad0bfa..ab2142807f 100644 --- a/docs/pcie_sriov.txt +++ b/docs/pcie_sriov.txt @@ -52,9 +52,11 @@ setting up a BAR for a VF. ... /* 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); + if (!pcie_sriov_pf_init(d, 0x200, "your_virtual_dev", + vf_devid, initial_vfs, total_vfs, + fun_offset, stride, errp)) { + return; + } /* Set up individual VF BARs (parameters as for normal BARs) */ pcie_sriov_pf_init_vf_bar( ... ) diff --git a/docs/specs/pvpanic.rst b/docs/specs/pvpanic.rst index b0f27860ec..61a80480ed 100644 --- a/docs/specs/pvpanic.rst +++ b/docs/specs/pvpanic.rst @@ -29,7 +29,7 @@ bit 1 a guest panic has happened and will be handled by the guest; the host should record it or report it, but should not affect the execution of the guest. -bit 2 (to be implemented) +bit 2 a regular guest shutdown has happened and should be processed by the host PCI Interface diff --git a/docs/system/devices/vhost-user.rst b/docs/system/devices/vhost-user.rst index 9b2da106ce..35259d8ec7 100644 --- a/docs/system/devices/vhost-user.rst +++ b/docs/system/devices/vhost-user.rst @@ -98,8 +98,9 @@ Shared memory object In order for the daemon to access the VirtIO queues to process the requests it needs access to the guest's address space. This is -achieved via the ``memory-backend-file`` or ``memory-backend-memfd`` -objects. A reference to a file-descriptor which can access this object +achieved via the ``memory-backend-file``, ``memory-backend-memfd``, or +``memory-backend-shm`` objects. +A reference to a file-descriptor which can access this object will be passed via the socket as part of the protocol negotiation. Currently the shared memory object needs to match the size of the main diff --git a/host/include/riscv/host/cpuinfo.h b/host/include/riscv/host/cpuinfo.h new file mode 100644 index 0000000000..2b00660e36 --- /dev/null +++ b/host/include/riscv/host/cpuinfo.h @@ -0,0 +1,23 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * Host specific cpu identification for RISC-V. + */ + +#ifndef HOST_CPUINFO_H +#define HOST_CPUINFO_H + +#define CPUINFO_ALWAYS (1u << 0) /* so cpuinfo is nonzero */ +#define CPUINFO_ZBA (1u << 1) +#define CPUINFO_ZBB (1u << 2) +#define CPUINFO_ZICOND (1u << 3) + +/* Initialized with a constructor. */ +extern unsigned cpuinfo; + +/* + * We cannot rely on constructor ordering, so other constructors must + * use the function interface rather than the variable above. + */ +unsigned cpuinfo_init(void); + +#endif /* HOST_CPUINFO_H */ diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index b2366f24f9..e10cad86dd 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -209,12 +209,19 @@ static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState *vms) #define ROOT_COMPLEX_ENTRY_SIZE 36 #define IORT_NODE_OFFSET 48 +/* + * Append an ID mapping entry as described by "Table 4 ID mapping format" in + * "IO Remapping Table System Software on ARM Platforms", Chapter 3. + * Document number: ARM DEN 0049E.f, Apr 2024 + * + * Note that @id_count gets internally subtracted by one, following the spec. + */ static void build_iort_id_mapping(GArray *table_data, uint32_t input_base, uint32_t id_count, uint32_t out_ref) { - /* Table 4 ID mapping format */ build_append_int_noprefix(table_data, input_base, 4); /* Input base */ - build_append_int_noprefix(table_data, id_count, 4); /* Number of IDs */ + /* Number of IDs - The number of IDs in the range minus one */ + build_append_int_noprefix(table_data, id_count - 1, 4); build_append_int_noprefix(table_data, input_base, 4); /* Output base */ build_append_int_noprefix(table_data, out_ref, 4); /* Output Reference */ /* Flags */ @@ -269,7 +276,6 @@ static void build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) { int i, nb_nodes, rc_mapping_count; - const uint32_t iort_node_offset = IORT_NODE_OFFSET; size_t node_size, smmu_offset = 0; AcpiIortIdMapping *idmap; uint32_t id = 0; @@ -306,8 +312,8 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) } /* Append the last RC -> ITS ID mapping */ - if (next_range.input_base < 0xFFFF) { - next_range.id_count = 0xFFFF - next_range.input_base; + if (next_range.input_base < 0x10000) { + next_range.id_count = 0x10000 - next_range.input_base; g_array_append_val(its_idmaps, next_range); } @@ -366,7 +372,7 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) build_append_int_noprefix(table_data, 0, 4); /* output IORT node is the ITS group node (the first node) */ - build_iort_id_mapping(table_data, 0, 0xFFFF, IORT_NODE_OFFSET); + build_iort_id_mapping(table_data, 0, 0x10000, IORT_NODE_OFFSET); } /* Table 17 Root Complex Node */ @@ -415,11 +421,11 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) range = &g_array_index(its_idmaps, AcpiIortIdMapping, i); /* output IORT node is the ITS group node (the first node) */ build_iort_id_mapping(table_data, range->input_base, - range->id_count, iort_node_offset); + range->id_count, IORT_NODE_OFFSET); } } else { /* output IORT node is the ITS group node (the first node) */ - build_iort_id_mapping(table_data, 0, 0xFFFF, IORT_NODE_OFFSET); + build_iort_id_mapping(table_data, 0, 0x10000, IORT_NODE_OFFSET); } acpi_table_end(linker, &table); diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c index 9e6bbc6950..fdbc30b9ce 100644 --- a/hw/block/vhost-user-blk.c +++ b/hw/block/vhost-user-blk.c @@ -51,6 +51,7 @@ static const int user_feature_bits[] = { VIRTIO_F_RING_PACKED, VIRTIO_F_IOMMU_PLATFORM, VIRTIO_F_RING_RESET, + VIRTIO_F_NOTIFICATION_DATA, VHOST_INVALID_FEATURE_BIT }; @@ -353,7 +354,7 @@ static void vhost_user_blk_disconnect(DeviceState *dev) VHostUserBlk *s = VHOST_USER_BLK(vdev); if (!s->connected) { - return; + goto done; } s->connected = false; @@ -361,6 +362,7 @@ static void vhost_user_blk_disconnect(DeviceState *dev) vhost_dev_cleanup(&s->dev); +done: /* Re-instate the event handler for new connections */ qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, vhost_user_blk_event, NULL, dev, NULL, true); @@ -384,7 +386,7 @@ static void vhost_user_blk_event(void *opaque, QEMUChrEvent event) case CHR_EVENT_CLOSED: /* defer close until later to avoid circular close */ vhost_user_async_close(dev, &s->chardev, &s->dev, - vhost_user_blk_disconnect, vhost_user_blk_event); + vhost_user_blk_disconnect); break; case CHR_EVENT_BREAK: case CHR_EVENT_MUX_IN: diff --git a/hw/core/machine.c b/hw/core/machine.c index 655d75c21f..f4cba6496c 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -38,6 +38,7 @@ GlobalProperty hw_compat_9_0[] = { {"arm-cpu", "backcompat-cntfrq", "true" }, {"scsi-disk-base", "migrate-emulated-scsi-request", "false" }, {"vfio-pci", "skip-vsc-check", "false" }, + { "virtio-pci", "x-pcie-pm-no-soft-reset", "off" }, }; const size_t hw_compat_9_0_len = G_N_ELEMENTS(hw_compat_9_0); diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c index e5eb97cb91..74eeb6fde7 100644 --- a/hw/cxl/cxl-mailbox-utils.c +++ b/hw/cxl/cxl-mailbox-utils.c @@ -19,8 +19,12 @@ #include "qemu/units.h" #include "qemu/uuid.h" #include "sysemu/hostmem.h" +#include "qemu/range.h" #define CXL_CAPACITY_MULTIPLIER (256 * MiB) +#define CXL_DC_EVENT_LOG_SIZE 8 +#define CXL_NUM_EXTENTS_SUPPORTED 512 +#define CXL_NUM_TAGS_SUPPORTED 0 /* * How to add a new command, example. The command set FOO, with cmd BAR. @@ -79,6 +83,11 @@ enum { #define GET_POISON_LIST 0x0 #define INJECT_POISON 0x1 #define CLEAR_POISON 0x2 + DCD_CONFIG = 0x48, + #define GET_DC_CONFIG 0x0 + #define GET_DYN_CAP_EXT_LIST 0x1 + #define ADD_DYN_CAP_RSP 0x2 + #define RELEASE_DYN_CAP 0x3 PHYSICAL_SWITCH = 0x51, #define IDENTIFY_SWITCH_DEVICE 0x0 #define GET_PHYSICAL_PORT_STATE 0x1 @@ -617,7 +626,8 @@ static CXLRetCode cmd_firmware_update_get_info(const struct cxl_cmd *cmd, size_t *len_out, CXLCCI *cci) { - CXLDeviceState *cxl_dstate = &CXL_TYPE3(cci->d)->cxl_dstate; + CXLType3Dev *ct3d = CXL_TYPE3(cci->d); + CXLDeviceState *cxl_dstate = &ct3d->cxl_dstate; struct { uint8_t slots_supported; uint8_t slot_info; @@ -631,7 +641,8 @@ static CXLRetCode cmd_firmware_update_get_info(const struct cxl_cmd *cmd, QEMU_BUILD_BUG_ON(sizeof(*fw_info) != 0x50); if ((cxl_dstate->vmem_size < CXL_CAPACITY_MULTIPLIER) || - (cxl_dstate->pmem_size < CXL_CAPACITY_MULTIPLIER)) { + (cxl_dstate->pmem_size < CXL_CAPACITY_MULTIPLIER) || + (ct3d->dc.total_capacity < CXL_CAPACITY_MULTIPLIER)) { return CXL_MBOX_INTERNAL_ERROR; } @@ -780,14 +791,16 @@ static CXLRetCode cmd_identify_memory_device(const struct cxl_cmd *cmd, uint16_t inject_poison_limit; uint8_t poison_caps; uint8_t qos_telemetry_caps; + uint16_t dc_event_log_size; } QEMU_PACKED *id; - QEMU_BUILD_BUG_ON(sizeof(*id) != 0x43); + QEMU_BUILD_BUG_ON(sizeof(*id) != 0x45); CXLType3Dev *ct3d = CXL_TYPE3(cci->d); CXLType3Class *cvc = CXL_TYPE3_GET_CLASS(ct3d); CXLDeviceState *cxl_dstate = &ct3d->cxl_dstate; if ((!QEMU_IS_ALIGNED(cxl_dstate->vmem_size, CXL_CAPACITY_MULTIPLIER)) || - (!QEMU_IS_ALIGNED(cxl_dstate->pmem_size, CXL_CAPACITY_MULTIPLIER))) { + (!QEMU_IS_ALIGNED(cxl_dstate->pmem_size, CXL_CAPACITY_MULTIPLIER)) || + (!QEMU_IS_ALIGNED(ct3d->dc.total_capacity, CXL_CAPACITY_MULTIPLIER))) { return CXL_MBOX_INTERNAL_ERROR; } @@ -797,7 +810,7 @@ static CXLRetCode cmd_identify_memory_device(const struct cxl_cmd *cmd, snprintf(id->fw_revision, 0x10, "BWFW VERSION %02d", 0); stq_le_p(&id->total_capacity, - cxl_dstate->mem_size / CXL_CAPACITY_MULTIPLIER); + cxl_dstate->static_mem_size / CXL_CAPACITY_MULTIPLIER); stq_le_p(&id->persistent_capacity, cxl_dstate->pmem_size / CXL_CAPACITY_MULTIPLIER); stq_le_p(&id->volatile_capacity, @@ -807,6 +820,7 @@ static CXLRetCode cmd_identify_memory_device(const struct cxl_cmd *cmd, st24_le_p(id->poison_list_max_mer, 256); /* No limit - so limited by main poison record limit */ stw_le_p(&id->inject_poison_limit, 0); + stw_le_p(&id->dc_event_log_size, CXL_DC_EVENT_LOG_SIZE); *len_out = sizeof(*id); return CXL_MBOX_SUCCESS; @@ -828,9 +842,11 @@ static CXLRetCode cmd_ccls_get_partition_info(const struct cxl_cmd *cmd, uint64_t next_pmem; } QEMU_PACKED *part_info = (void *)payload_out; QEMU_BUILD_BUG_ON(sizeof(*part_info) != 0x20); + CXLType3Dev *ct3d = container_of(cxl_dstate, CXLType3Dev, cxl_dstate); if ((!QEMU_IS_ALIGNED(cxl_dstate->vmem_size, CXL_CAPACITY_MULTIPLIER)) || - (!QEMU_IS_ALIGNED(cxl_dstate->pmem_size, CXL_CAPACITY_MULTIPLIER))) { + (!QEMU_IS_ALIGNED(cxl_dstate->pmem_size, CXL_CAPACITY_MULTIPLIER)) || + (!QEMU_IS_ALIGNED(ct3d->dc.total_capacity, CXL_CAPACITY_MULTIPLIER))) { return CXL_MBOX_INTERNAL_ERROR; } @@ -1172,7 +1188,8 @@ static CXLRetCode cmd_media_clear_poison(const struct cxl_cmd *cmd, struct clear_poison_pl *in = (void *)payload_in; dpa = ldq_le_p(&in->dpa); - if (dpa + CXL_CACHE_LINE_SIZE > cxl_dstate->mem_size) { + if (dpa + CXL_CACHE_LINE_SIZE > cxl_dstate->static_mem_size + + ct3d->dc.total_capacity) { return CXL_MBOX_INVALID_PA; } @@ -1235,6 +1252,576 @@ static CXLRetCode cmd_media_clear_poison(const struct cxl_cmd *cmd, return CXL_MBOX_SUCCESS; } +/* + * CXL r3.1 section 8.2.9.9.9.1: Get Dynamic Capacity Configuration + * (Opcode: 4800h) + */ +static CXLRetCode cmd_dcd_get_dyn_cap_config(const struct cxl_cmd *cmd, + uint8_t *payload_in, + size_t len_in, + uint8_t *payload_out, + size_t *len_out, + CXLCCI *cci) +{ + CXLType3Dev *ct3d = CXL_TYPE3(cci->d); + struct { + uint8_t region_cnt; + uint8_t start_rid; + } QEMU_PACKED *in = (void *)payload_in; + struct { + uint8_t num_regions; + uint8_t regions_returned; + uint8_t rsvd1[6]; + struct { + uint64_t base; + uint64_t decode_len; + uint64_t region_len; + uint64_t block_size; + uint32_t dsmadhandle; + uint8_t flags; + uint8_t rsvd2[3]; + } QEMU_PACKED records[]; + } QEMU_PACKED *out = (void *)payload_out; + struct { + uint32_t num_extents_supported; + uint32_t num_extents_available; + uint32_t num_tags_supported; + uint32_t num_tags_available; + } QEMU_PACKED *extra_out; + uint16_t record_count; + uint16_t i; + uint16_t out_pl_len; + uint8_t start_rid; + + start_rid = in->start_rid; + if (start_rid >= ct3d->dc.num_regions) { + return CXL_MBOX_INVALID_INPUT; + } + + record_count = MIN(ct3d->dc.num_regions - in->start_rid, in->region_cnt); + + out_pl_len = sizeof(*out) + record_count * sizeof(out->records[0]); + extra_out = (void *)(payload_out + out_pl_len); + out_pl_len += sizeof(*extra_out); + assert(out_pl_len <= CXL_MAILBOX_MAX_PAYLOAD_SIZE); + + out->num_regions = ct3d->dc.num_regions; + out->regions_returned = record_count; + for (i = 0; i < record_count; i++) { + stq_le_p(&out->records[i].base, + ct3d->dc.regions[start_rid + i].base); + stq_le_p(&out->records[i].decode_len, + ct3d->dc.regions[start_rid + i].decode_len / + CXL_CAPACITY_MULTIPLIER); + stq_le_p(&out->records[i].region_len, + ct3d->dc.regions[start_rid + i].len); + stq_le_p(&out->records[i].block_size, + ct3d->dc.regions[start_rid + i].block_size); + stl_le_p(&out->records[i].dsmadhandle, + ct3d->dc.regions[start_rid + i].dsmadhandle); + out->records[i].flags = ct3d->dc.regions[start_rid + i].flags; + } + /* + * TODO: Assign values once extents and tags are introduced + * to use. + */ + stl_le_p(&extra_out->num_extents_supported, CXL_NUM_EXTENTS_SUPPORTED); + stl_le_p(&extra_out->num_extents_available, CXL_NUM_EXTENTS_SUPPORTED - + ct3d->dc.total_extent_count); + stl_le_p(&extra_out->num_tags_supported, CXL_NUM_TAGS_SUPPORTED); + stl_le_p(&extra_out->num_tags_available, CXL_NUM_TAGS_SUPPORTED); + + *len_out = out_pl_len; + return CXL_MBOX_SUCCESS; +} + +/* + * CXL r3.1 section 8.2.9.9.9.2: + * Get Dynamic Capacity Extent List (Opcode 4801h) + */ +static CXLRetCode cmd_dcd_get_dyn_cap_ext_list(const struct cxl_cmd *cmd, + uint8_t *payload_in, + size_t len_in, + uint8_t *payload_out, + size_t *len_out, + CXLCCI *cci) +{ + CXLType3Dev *ct3d = CXL_TYPE3(cci->d); + struct { + uint32_t extent_cnt; + uint32_t start_extent_id; + } QEMU_PACKED *in = (void *)payload_in; + struct { + uint32_t count; + uint32_t total_extents; + uint32_t generation_num; + uint8_t rsvd[4]; + CXLDCExtentRaw records[]; + } QEMU_PACKED *out = (void *)payload_out; + uint32_t start_extent_id = in->start_extent_id; + CXLDCExtentList *extent_list = &ct3d->dc.extents; + uint16_t record_count = 0, i = 0, record_done = 0; + uint16_t out_pl_len, size; + CXLDCExtent *ent; + + if (start_extent_id > ct3d->dc.total_extent_count) { + return CXL_MBOX_INVALID_INPUT; + } + + record_count = MIN(in->extent_cnt, + ct3d->dc.total_extent_count - start_extent_id); + size = CXL_MAILBOX_MAX_PAYLOAD_SIZE - sizeof(*out); + record_count = MIN(record_count, size / sizeof(out->records[0])); + out_pl_len = sizeof(*out) + record_count * sizeof(out->records[0]); + + stl_le_p(&out->count, record_count); + stl_le_p(&out->total_extents, ct3d->dc.total_extent_count); + stl_le_p(&out->generation_num, ct3d->dc.ext_list_gen_seq); + + if (record_count > 0) { + CXLDCExtentRaw *out_rec = &out->records[record_done]; + + QTAILQ_FOREACH(ent, extent_list, node) { + if (i++ < start_extent_id) { + continue; + } + stq_le_p(&out_rec->start_dpa, ent->start_dpa); + stq_le_p(&out_rec->len, ent->len); + memcpy(&out_rec->tag, ent->tag, 0x10); + stw_le_p(&out_rec->shared_seq, ent->shared_seq); + + record_done++; + if (record_done == record_count) { + break; + } + } + } + + *len_out = out_pl_len; + return CXL_MBOX_SUCCESS; +} + +/* + * Check whether any bit between addr[nr, nr+size) is set, + * return true if any bit is set, otherwise return false + */ +bool test_any_bits_set(const unsigned long *addr, unsigned long nr, + unsigned long size) +{ + unsigned long res = find_next_bit(addr, size + nr, nr); + + return res < nr + size; +} + +CXLDCRegion *cxl_find_dc_region(CXLType3Dev *ct3d, uint64_t dpa, uint64_t len) +{ + int i; + CXLDCRegion *region = &ct3d->dc.regions[0]; + + if (dpa < region->base || + dpa >= region->base + ct3d->dc.total_capacity) { + return NULL; + } + + /* + * CXL r3.1 section 9.13.3: Dynamic Capacity Device (DCD) + * + * Regions are used in increasing-DPA order, with Region 0 being used for + * the lowest DPA of Dynamic Capacity and Region 7 for the highest DPA. + * So check from the last region to find where the dpa belongs. Extents that + * cross multiple regions are not allowed. + */ + for (i = ct3d->dc.num_regions - 1; i >= 0; i--) { + region = &ct3d->dc.regions[i]; + if (dpa >= region->base) { + if (dpa + len > region->base + region->len) { + return NULL; + } + return region; + } + } + + return NULL; +} + +void cxl_insert_extent_to_extent_list(CXLDCExtentList *list, + uint64_t dpa, + uint64_t len, + uint8_t *tag, + uint16_t shared_seq) +{ + CXLDCExtent *extent; + + extent = g_new0(CXLDCExtent, 1); + extent->start_dpa = dpa; + extent->len = len; + if (tag) { + memcpy(extent->tag, tag, 0x10); + } + extent->shared_seq = shared_seq; + + QTAILQ_INSERT_TAIL(list, extent, node); +} + +void cxl_remove_extent_from_extent_list(CXLDCExtentList *list, + CXLDCExtent *extent) +{ + QTAILQ_REMOVE(list, extent, node); + g_free(extent); +} + +/* + * Add a new extent to the extent "group" if group exists; + * otherwise, create a new group + * Return value: the extent group where the extent is inserted. + */ +CXLDCExtentGroup *cxl_insert_extent_to_extent_group(CXLDCExtentGroup *group, + uint64_t dpa, + uint64_t len, + uint8_t *tag, + uint16_t shared_seq) +{ + if (!group) { + group = g_new0(CXLDCExtentGroup, 1); + QTAILQ_INIT(&group->list); + } + cxl_insert_extent_to_extent_list(&group->list, dpa, len, + tag, shared_seq); + return group; +} + +void cxl_extent_group_list_insert_tail(CXLDCExtentGroupList *list, + CXLDCExtentGroup *group) +{ + QTAILQ_INSERT_TAIL(list, group, node); +} + +void cxl_extent_group_list_delete_front(CXLDCExtentGroupList *list) +{ + CXLDCExtent *ent, *ent_next; + CXLDCExtentGroup *group = QTAILQ_FIRST(list); + + QTAILQ_REMOVE(list, group, node); + QTAILQ_FOREACH_SAFE(ent, &group->list, node, ent_next) { + cxl_remove_extent_from_extent_list(&group->list, ent); + } + g_free(group); +} + +/* + * CXL r3.1 Table 8-168: Add Dynamic Capacity Response Input Payload + * CXL r3.1 Table 8-170: Release Dynamic Capacity Input Payload + */ +typedef struct CXLUpdateDCExtentListInPl { + uint32_t num_entries_updated; + uint8_t flags; + uint8_t rsvd[3]; + /* CXL r3.1 Table 8-169: Updated Extent */ + struct { + uint64_t start_dpa; + uint64_t len; + uint8_t rsvd[8]; + } QEMU_PACKED updated_entries[]; +} QEMU_PACKED CXLUpdateDCExtentListInPl; + +/* + * For the extents in the extent list to operate, check whether they are valid + * 1. The extent should be in the range of a valid DC region; + * 2. The extent should not cross multiple regions; + * 3. The start DPA and the length of the extent should align with the block + * size of the region; + * 4. The address range of multiple extents in the list should not overlap. + */ +static CXLRetCode cxl_detect_malformed_extent_list(CXLType3Dev *ct3d, + const CXLUpdateDCExtentListInPl *in) +{ + uint64_t min_block_size = UINT64_MAX; + CXLDCRegion *region; + CXLDCRegion *lastregion = &ct3d->dc.regions[ct3d->dc.num_regions - 1]; + g_autofree unsigned long *blk_bitmap = NULL; + uint64_t dpa, len; + uint32_t i; + + for (i = 0; i < ct3d->dc.num_regions; i++) { + region = &ct3d->dc.regions[i]; + min_block_size = MIN(min_block_size, region->block_size); + } + + blk_bitmap = bitmap_new((lastregion->base + lastregion->len - + ct3d->dc.regions[0].base) / min_block_size); + + for (i = 0; i < in->num_entries_updated; i++) { + dpa = in->updated_entries[i].start_dpa; + len = in->updated_entries[i].len; + + region = cxl_find_dc_region(ct3d, dpa, len); + if (!region) { + return CXL_MBOX_INVALID_PA; + } + + dpa -= ct3d->dc.regions[0].base; + if (dpa % region->block_size || len % region->block_size) { + return CXL_MBOX_INVALID_EXTENT_LIST; + } + /* the dpa range already covered by some other extents in the list */ + if (test_any_bits_set(blk_bitmap, dpa / min_block_size, + len / min_block_size)) { + return CXL_MBOX_INVALID_EXTENT_LIST; + } + bitmap_set(blk_bitmap, dpa / min_block_size, len / min_block_size); + } + + return CXL_MBOX_SUCCESS; +} + +static CXLRetCode cxl_dcd_add_dyn_cap_rsp_dry_run(CXLType3Dev *ct3d, + const CXLUpdateDCExtentListInPl *in) +{ + uint32_t i; + CXLDCExtent *ent; + CXLDCExtentGroup *ext_group; + uint64_t dpa, len; + Range range1, range2; + + for (i = 0; i < in->num_entries_updated; i++) { + dpa = in->updated_entries[i].start_dpa; + len = in->updated_entries[i].len; + + range_init_nofail(&range1, dpa, len); + + /* + * The host-accepted DPA range must be contained by the first extent + * group in the pending list + */ + ext_group = QTAILQ_FIRST(&ct3d->dc.extents_pending); + if (!cxl_extents_contains_dpa_range(&ext_group->list, dpa, len)) { + return CXL_MBOX_INVALID_PA; + } + + /* to-be-added range should not overlap with range already accepted */ + QTAILQ_FOREACH(ent, &ct3d->dc.extents, node) { + range_init_nofail(&range2, ent->start_dpa, ent->len); + if (range_overlaps_range(&range1, &range2)) { + return CXL_MBOX_INVALID_PA; + } + } + } + return CXL_MBOX_SUCCESS; +} + +/* + * CXL r3.1 section 8.2.9.9.9.3: Add Dynamic Capacity Response (Opcode 4802h) + * An extent is added to the extent list and becomes usable only after the + * response is processed successfully. + */ +static CXLRetCode cmd_dcd_add_dyn_cap_rsp(const struct cxl_cmd *cmd, + uint8_t *payload_in, + size_t len_in, + uint8_t *payload_out, + size_t *len_out, + CXLCCI *cci) +{ + CXLUpdateDCExtentListInPl *in = (void *)payload_in; + CXLType3Dev *ct3d = CXL_TYPE3(cci->d); + CXLDCExtentList *extent_list = &ct3d->dc.extents; + uint32_t i; + uint64_t dpa, len; + CXLRetCode ret; + + if (in->num_entries_updated == 0) { + cxl_extent_group_list_delete_front(&ct3d->dc.extents_pending); + return CXL_MBOX_SUCCESS; + } + + /* Adding extents causes exceeding device's extent tracking ability. */ + if (in->num_entries_updated + ct3d->dc.total_extent_count > + CXL_NUM_EXTENTS_SUPPORTED) { + return CXL_MBOX_RESOURCES_EXHAUSTED; + } + + ret = cxl_detect_malformed_extent_list(ct3d, in); + if (ret != CXL_MBOX_SUCCESS) { + return ret; + } + + ret = cxl_dcd_add_dyn_cap_rsp_dry_run(ct3d, in); + if (ret != CXL_MBOX_SUCCESS) { + return ret; + } + + for (i = 0; i < in->num_entries_updated; i++) { + dpa = in->updated_entries[i].start_dpa; + len = in->updated_entries[i].len; + + cxl_insert_extent_to_extent_list(extent_list, dpa, len, NULL, 0); + ct3d->dc.total_extent_count += 1; + ct3_set_region_block_backed(ct3d, dpa, len); + } + /* Remove the first extent group in the pending list */ + cxl_extent_group_list_delete_front(&ct3d->dc.extents_pending); + + return CXL_MBOX_SUCCESS; +} + +/* + * Copy extent list from src to dst + * Return value: number of extents copied + */ +static uint32_t copy_extent_list(CXLDCExtentList *dst, + const CXLDCExtentList *src) +{ + uint32_t cnt = 0; + CXLDCExtent *ent; + + if (!dst || !src) { + return 0; + } + + QTAILQ_FOREACH(ent, src, node) { + cxl_insert_extent_to_extent_list(dst, ent->start_dpa, ent->len, + ent->tag, ent->shared_seq); + cnt++; + } + return cnt; +} + +static CXLRetCode cxl_dc_extent_release_dry_run(CXLType3Dev *ct3d, + const CXLUpdateDCExtentListInPl *in, CXLDCExtentList *updated_list, + uint32_t *updated_list_size) +{ + CXLDCExtent *ent, *ent_next; + uint64_t dpa, len; + uint32_t i; + int cnt_delta = 0; + CXLRetCode ret = CXL_MBOX_SUCCESS; + + QTAILQ_INIT(updated_list); + copy_extent_list(updated_list, &ct3d->dc.extents); + + for (i = 0; i < in->num_entries_updated; i++) { + Range range; + + dpa = in->updated_entries[i].start_dpa; + len = in->updated_entries[i].len; + + /* Check if the DPA range is not fully backed with valid extents */ + if (!ct3_test_region_block_backed(ct3d, dpa, len)) { + ret = CXL_MBOX_INVALID_PA; + goto free_and_exit; + } + + /* After this point, extent overflow is the only error can happen */ + while (len > 0) { + QTAILQ_FOREACH(ent, updated_list, node) { + range_init_nofail(&range, ent->start_dpa, ent->len); + + if (range_contains(&range, dpa)) { + uint64_t len1, len2 = 0, len_done = 0; + uint64_t ent_start_dpa = ent->start_dpa; + uint64_t ent_len = ent->len; + + len1 = dpa - ent->start_dpa; + /* Found the extent or the subset of an existing extent */ + if (range_contains(&range, dpa + len - 1)) { + len2 = ent_start_dpa + ent_len - dpa - len; + } else { + dpa = ent_start_dpa + ent_len; + } + len_done = ent_len - len1 - len2; + + cxl_remove_extent_from_extent_list(updated_list, ent); + cnt_delta--; + + if (len1) { + cxl_insert_extent_to_extent_list(updated_list, + ent_start_dpa, + len1, NULL, 0); + cnt_delta++; + } + if (len2) { + cxl_insert_extent_to_extent_list(updated_list, + dpa + len, + len2, NULL, 0); + cnt_delta++; + } + + if (cnt_delta + ct3d->dc.total_extent_count > + CXL_NUM_EXTENTS_SUPPORTED) { + ret = CXL_MBOX_RESOURCES_EXHAUSTED; + goto free_and_exit; + } + + len -= len_done; + break; + } + } + } + } +free_and_exit: + if (ret != CXL_MBOX_SUCCESS) { + QTAILQ_FOREACH_SAFE(ent, updated_list, node, ent_next) { + cxl_remove_extent_from_extent_list(updated_list, ent); + } + *updated_list_size = 0; + } else { + *updated_list_size = ct3d->dc.total_extent_count + cnt_delta; + } + + return ret; +} + +/* + * CXL r3.1 section 8.2.9.9.9.4: Release Dynamic Capacity (Opcode 4803h) + */ +static CXLRetCode cmd_dcd_release_dyn_cap(const struct cxl_cmd *cmd, + uint8_t *payload_in, + size_t len_in, + uint8_t *payload_out, + size_t *len_out, + CXLCCI *cci) +{ + CXLUpdateDCExtentListInPl *in = (void *)payload_in; + CXLType3Dev *ct3d = CXL_TYPE3(cci->d); + CXLDCExtentList updated_list; + CXLDCExtent *ent, *ent_next; + uint32_t updated_list_size; + CXLRetCode ret; + + if (in->num_entries_updated == 0) { + return CXL_MBOX_INVALID_INPUT; + } + + ret = cxl_detect_malformed_extent_list(ct3d, in); + if (ret != CXL_MBOX_SUCCESS) { + return ret; + } + + ret = cxl_dc_extent_release_dry_run(ct3d, in, &updated_list, + &updated_list_size); + if (ret != CXL_MBOX_SUCCESS) { + return ret; + } + + /* + * If the dry run release passes, the returned updated_list will + * be the updated extent list and we just need to clear the extents + * in the accepted list and copy extents in the updated_list to accepted + * list and update the extent count; + */ + QTAILQ_FOREACH_SAFE(ent, &ct3d->dc.extents, node, ent_next) { + ct3_clear_region_block_backed(ct3d, ent->start_dpa, ent->len); + cxl_remove_extent_from_extent_list(&ct3d->dc.extents, ent); + } + copy_extent_list(&ct3d->dc.extents, &updated_list); + QTAILQ_FOREACH_SAFE(ent, &updated_list, node, ent_next) { + ct3_set_region_block_backed(ct3d, ent->start_dpa, ent->len); + cxl_remove_extent_from_extent_list(&updated_list, ent); + } + ct3d->dc.total_extent_count = updated_list_size; + + return CXL_MBOX_SUCCESS; +} + #define IMMEDIATE_CONFIG_CHANGE (1 << 1) #define IMMEDIATE_DATA_CHANGE (1 << 2) #define IMMEDIATE_POLICY_CHANGE (1 << 3) @@ -1279,6 +1866,20 @@ static const struct cxl_cmd cxl_cmd_set[256][256] = { cmd_media_clear_poison, 72, 0 }, }; +static const struct cxl_cmd cxl_cmd_set_dcd[256][256] = { + [DCD_CONFIG][GET_DC_CONFIG] = { "DCD_GET_DC_CONFIG", + cmd_dcd_get_dyn_cap_config, 2, 0 }, + [DCD_CONFIG][GET_DYN_CAP_EXT_LIST] = { + "DCD_GET_DYNAMIC_CAPACITY_EXTENT_LIST", cmd_dcd_get_dyn_cap_ext_list, + 8, 0 }, + [DCD_CONFIG][ADD_DYN_CAP_RSP] = { + "DCD_ADD_DYNAMIC_CAPACITY_RESPONSE", cmd_dcd_add_dyn_cap_rsp, + ~0, IMMEDIATE_DATA_CHANGE }, + [DCD_CONFIG][RELEASE_DYN_CAP] = { + "DCD_RELEASE_DYNAMIC_CAPACITY", cmd_dcd_release_dyn_cap, + ~0, IMMEDIATE_DATA_CHANGE }, +}; + static const struct cxl_cmd cxl_cmd_set_sw[256][256] = { [INFOSTAT][IS_IDENTIFY] = { "IDENTIFY", cmd_infostat_identify, 0, 0 }, [INFOSTAT][BACKGROUND_OPERATION_STATUS] = { "BACKGROUND_OPERATION_STATUS", @@ -1424,9 +2025,9 @@ static void bg_timercb(void *opaque) } } -void cxl_init_cci(CXLCCI *cci, size_t payload_max) +static void cxl_rebuild_cel(CXLCCI *cci) { - cci->payload_max = payload_max; + cci->cel_size = 0; /* Reset for a fresh build */ for (int set = 0; set < 256; set++) { for (int cmd = 0; cmd < 256; cmd++) { if (cci->cxl_cmd_set[set][cmd].handler) { @@ -1440,6 +2041,13 @@ void cxl_init_cci(CXLCCI *cci, size_t payload_max) } } } +} + +void cxl_init_cci(CXLCCI *cci, size_t payload_max) +{ + cci->payload_max = payload_max; + cxl_rebuild_cel(cci); + cci->bg.complete_pct = 0; cci->bg.starttime = 0; cci->bg.runtime = 0; @@ -1447,10 +2055,29 @@ void cxl_init_cci(CXLCCI *cci, size_t payload_max) bg_timercb, cci); } +static void cxl_copy_cci_commands(CXLCCI *cci, const struct cxl_cmd (*cxl_cmds)[256]) +{ + for (int set = 0; set < 256; set++) { + for (int cmd = 0; cmd < 256; cmd++) { + if (cxl_cmds[set][cmd].handler) { + cci->cxl_cmd_set[set][cmd] = cxl_cmds[set][cmd]; + } + } + } +} + +void cxl_add_cci_commands(CXLCCI *cci, const struct cxl_cmd (*cxl_cmd_set)[256], + size_t payload_max) +{ + cci->payload_max = MAX(payload_max, cci->payload_max); + cxl_copy_cci_commands(cci, cxl_cmd_set); + cxl_rebuild_cel(cci); +} + void cxl_initialize_mailbox_swcci(CXLCCI *cci, DeviceState *intf, DeviceState *d, size_t payload_max) { - cci->cxl_cmd_set = cxl_cmd_set_sw; + cxl_copy_cci_commands(cci, cxl_cmd_set_sw); cci->d = d; cci->intf = intf; cxl_init_cci(cci, payload_max); @@ -1458,7 +2085,12 @@ void cxl_initialize_mailbox_swcci(CXLCCI *cci, DeviceState *intf, void cxl_initialize_mailbox_t3(CXLCCI *cci, DeviceState *d, size_t payload_max) { - cci->cxl_cmd_set = cxl_cmd_set; + CXLType3Dev *ct3d = CXL_TYPE3(d); + + cxl_copy_cci_commands(cci, cxl_cmd_set); + if (ct3d->dc.num_regions) { + cxl_copy_cci_commands(cci, cxl_cmd_set_dcd); + } cci->d = d; /* No separation for PCI MB as protocol handled in PCI device */ @@ -1476,7 +2108,7 @@ static const struct cxl_cmd cxl_cmd_set_t3_ld[256][256] = { void cxl_initialize_t3_ld_cci(CXLCCI *cci, DeviceState *d, DeviceState *intf, size_t payload_max) { - cci->cxl_cmd_set = cxl_cmd_set_t3_ld; + cxl_copy_cci_commands(cci, cxl_cmd_set_t3_ld); cci->d = d; cci->intf = intf; cxl_init_cci(cci, payload_max); @@ -1496,7 +2128,7 @@ void cxl_initialize_t3_fm_owned_ld_mctpcci(CXLCCI *cci, DeviceState *d, DeviceState *intf, size_t payload_max) { - cci->cxl_cmd_set = cxl_cmd_set_t3_fm_owned_ld_mctp; + cxl_copy_cci_commands(cci, cxl_cmd_set_t3_fm_owned_ld_mctp); cci->d = d; cci->intf = intf; cxl_init_cci(cci, payload_max); diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index e4b398d26c..63c64ddde6 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -281,8 +281,9 @@ vhost_user_gpu_handle_display(VhostUserGPU *g, VhostUserGpuMsg *msg) modifier = m2->modifier; } - dmabuf = qemu_dmabuf_new(m->fd_width, m->fd_height, - m->fd_stride, 0, 0, 0, 0, + dmabuf = qemu_dmabuf_new(m->width, m->height, + m->fd_stride, 0, 0, + m->fd_width, m->fd_height, m->fd_drm_fourcc, modifier, fd, false, m->fd_flags & VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP); diff --git a/hw/i386/e820_memory_layout.c b/hw/i386/e820_memory_layout.c index 06970ac44a..3e848fb69c 100644 --- a/hw/i386/e820_memory_layout.c +++ b/hw/i386/e820_memory_layout.c @@ -11,22 +11,29 @@ #include "e820_memory_layout.h" static size_t e820_entries; -struct e820_entry *e820_table; +static struct e820_entry *e820_table; +static gboolean e820_done; -int e820_add_entry(uint64_t address, uint64_t length, uint32_t type) +void e820_add_entry(uint64_t address, uint64_t length, uint32_t type) { + assert(!e820_done); + /* new "etc/e820" file -- include ram and reserved entries */ e820_table = g_renew(struct e820_entry, e820_table, e820_entries + 1); e820_table[e820_entries].address = cpu_to_le64(address); e820_table[e820_entries].length = cpu_to_le64(length); e820_table[e820_entries].type = cpu_to_le32(type); e820_entries++; - - return e820_entries; } -int e820_get_num_entries(void) +int e820_get_table(struct e820_entry **table) { + e820_done = true; + + if (table) { + *table = e820_table; + } + return e820_entries; } diff --git a/hw/i386/e820_memory_layout.h b/hw/i386/e820_memory_layout.h index 7c239aa033..b50acfa201 100644 --- a/hw/i386/e820_memory_layout.h +++ b/hw/i386/e820_memory_layout.h @@ -22,13 +22,9 @@ struct e820_entry { uint32_t type; } QEMU_PACKED __attribute((__aligned__(4))); -extern struct e820_entry *e820_table; - -int e820_add_entry(uint64_t address, uint64_t length, uint32_t type); -int e820_get_num_entries(void); +void e820_add_entry(uint64_t address, uint64_t length, uint32_t type); bool e820_get_entry(int index, uint32_t type, uint64_t *address, uint64_t *length); - - +int e820_get_table(struct e820_entry **table); #endif diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c index 7c43c325ef..0e4494627c 100644 --- a/hw/i386/fw_cfg.c +++ b/hw/i386/fw_cfg.c @@ -48,6 +48,15 @@ const char *fw_cfg_arch_key_name(uint16_t key) return NULL; } +/* Add etc/e820 late, once all regions should be present */ +void fw_cfg_add_e820(FWCfgState *fw_cfg) +{ + struct e820_entry *table; + int nr_e820 = e820_get_table(&table); + + fw_cfg_add_file(fw_cfg, "etc/e820", table, nr_e820 * sizeof(*table)); +} + void fw_cfg_build_smbios(PCMachineState *pcms, FWCfgState *fw_cfg, SmbiosEntryPointType ep_type) { @@ -60,6 +69,7 @@ void fw_cfg_build_smbios(PCMachineState *pcms, FWCfgState *fw_cfg, PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); MachineClass *mc = MACHINE_GET_CLASS(pcms); X86CPU *cpu = X86_CPU(ms->possible_cpus->cpus[0].cpu); + int nr_e820; if (pcmc->smbios_defaults) { /* These values are guest ABI, do not change */ @@ -78,8 +88,9 @@ void fw_cfg_build_smbios(PCMachineState *pcms, FWCfgState *fw_cfg, } /* build the array of physical mem area from e820 table */ - mem_array = g_malloc0(sizeof(*mem_array) * e820_get_num_entries()); - for (i = 0, array_count = 0; i < e820_get_num_entries(); i++) { + nr_e820 = e820_get_table(NULL); + mem_array = g_malloc0(sizeof(*mem_array) * nr_e820); + for (i = 0, array_count = 0; i < nr_e820; i++) { uint64_t addr, len; if (e820_get_entry(i, E820_RAM, &addr, &len)) { @@ -138,9 +149,6 @@ FWCfgState *fw_cfg_arch_create(MachineState *ms, #endif fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, 1); - fw_cfg_add_file(fw_cfg, "etc/e820", e820_table, - sizeof(struct e820_entry) * e820_get_num_entries()); - fw_cfg_add_bytes(fw_cfg, FW_CFG_HPET, &hpet_cfg, sizeof(hpet_cfg)); /* allocate memory for the NUMA channel: one (64bit) word for the number * of nodes, one word for each VCPU->node and one word for each node to diff --git a/hw/i386/fw_cfg.h b/hw/i386/fw_cfg.h index 92e310f5fd..e560fd7be8 100644 --- a/hw/i386/fw_cfg.h +++ b/hw/i386/fw_cfg.h @@ -27,5 +27,6 @@ void fw_cfg_build_smbios(PCMachineState *pcms, FWCfgState *fw_cfg, SmbiosEntryPointType ep_type); void fw_cfg_build_feature_control(MachineState *ms, FWCfgState *fw_cfg); void fw_cfg_add_acpi_dsdt(Aml *scope, FWCfgState *fw_cfg); +void fw_cfg_add_e820(FWCfgState *fw_cfg); #endif diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index fec63cacfa..40edcee7af 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -324,8 +324,6 @@ static void microvm_memory_init(MicrovmMachineState *mms) fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, machine->smp.max_cpus); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)machine->ram_size); fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, 1); - fw_cfg_add_file(fw_cfg, "etc/e820", e820_table, - sizeof(struct e820_entry) * e820_get_num_entries()); rom_set_fw(fw_cfg); @@ -586,9 +584,11 @@ static void microvm_machine_done(Notifier *notifier, void *data) { MicrovmMachineState *mms = container_of(notifier, MicrovmMachineState, machine_done); + X86MachineState *x86ms = X86_MACHINE(mms); acpi_setup_microvm(mms); dt_setup_microvm(mms); + fw_cfg_add_e820(x86ms->fw_cfg); } static void microvm_powerdown_req(Notifier *notifier, void *data) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 5dff91422f..4fbc577470 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -626,6 +626,7 @@ void pc_machine_done(Notifier *notifier, void *data) acpi_setup(); if (x86ms->fw_cfg) { fw_cfg_build_smbios(pcms, x86ms->fw_cfg, pcms->smbios_entry_point_type); + fw_cfg_add_e820(x86ms->fw_cfg); fw_cfg_build_feature_control(MACHINE(pcms), x86ms->fw_cfg); /* update FW_CFG_NB_CPUS to account for -device added CPUs */ fw_cfg_modify_i16(x86ms->fw_cfg, FW_CFG_NB_CPUS, x86ms->boot_cpus); diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c index d8fc1e2815..c13cdd7994 100644 --- a/hw/intc/apic_common.c +++ b/hw/intc/apic_common.c @@ -433,6 +433,7 @@ static void apic_common_set_id(Object *obj, Visitor *v, const char *name, APICCommonState *s = APIC_COMMON(obj); DeviceState *dev = DEVICE(obj); uint32_t value; + Error *local_err = NULL; if (dev->realized) { qdev_prop_set_after_realize(dev, name, errp); @@ -444,7 +445,11 @@ static void apic_common_set_id(Object *obj, Visitor *v, const char *name, } if (value >= 255 && !cpu_has_x2apic_feature(&s->cpu->env)) { - error_setg(errp, "APIC ID %d requires x2APIC feature in CPU", value); + error_setg(&local_err, + "APIC ID %d requires x2APIC feature in CPU", + value); + error_append_hint(&local_err, "Try x2apic=on in -cpu.\n"); + error_propagate(errp, local_err); return; } diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c index 3e42490b6c..35ac59883a 100644 --- a/hw/mem/cxl_type3.c +++ b/hw/mem/cxl_type3.c @@ -30,6 +30,7 @@ #include "hw/pci/msix.h" #define DWORD_BYTE 4 +#define CXL_CAPACITY_MULTIPLIER (256 * MiB) /* Default CDAT entries for a memory region */ enum { @@ -43,8 +44,9 @@ enum { }; static void ct3_build_cdat_entries_for_mr(CDATSubHeader **cdat_table, - int dsmad_handle, MemoryRegion *mr, - bool is_pmem, uint64_t dpa_base) + int dsmad_handle, uint64_t size, + bool is_pmem, bool is_dynamic, + uint64_t dpa_base) { CDATDsmas *dsmas; CDATDslbis *dslbis0; @@ -60,9 +62,10 @@ static void ct3_build_cdat_entries_for_mr(CDATSubHeader **cdat_table, .length = sizeof(*dsmas), }, .DSMADhandle = dsmad_handle, - .flags = is_pmem ? CDAT_DSMAS_FLAG_NV : 0, + .flags = (is_pmem ? CDAT_DSMAS_FLAG_NV : 0) | + (is_dynamic ? CDAT_DSMAS_FLAG_DYNAMIC_CAP : 0), .DPA_base = dpa_base, - .DPA_length = memory_region_size(mr), + .DPA_length = size, }; /* For now, no memory side cache, plausiblish numbers */ @@ -131,7 +134,7 @@ static void ct3_build_cdat_entries_for_mr(CDATSubHeader **cdat_table, */ .EFI_memory_type_attr = is_pmem ? 2 : 1, .DPA_offset = 0, - .DPA_length = memory_region_size(mr), + .DPA_length = size, }; /* Header always at start of structure */ @@ -148,11 +151,13 @@ static int ct3_build_cdat_table(CDATSubHeader ***cdat_table, void *priv) g_autofree CDATSubHeader **table = NULL; CXLType3Dev *ct3d = priv; MemoryRegion *volatile_mr = NULL, *nonvolatile_mr = NULL; + MemoryRegion *dc_mr = NULL; + uint64_t vmr_size = 0, pmr_size = 0; int dsmad_handle = 0; int cur_ent = 0; int len = 0; - if (!ct3d->hostpmem && !ct3d->hostvmem) { + if (!ct3d->hostpmem && !ct3d->hostvmem && !ct3d->dc.num_regions) { return 0; } @@ -162,6 +167,7 @@ static int ct3_build_cdat_table(CDATSubHeader ***cdat_table, void *priv) return -EINVAL; } len += CT3_CDAT_NUM_ENTRIES; + vmr_size = memory_region_size(volatile_mr); } if (ct3d->hostpmem) { @@ -170,23 +176,57 @@ static int ct3_build_cdat_table(CDATSubHeader ***cdat_table, void *priv) return -EINVAL; } len += CT3_CDAT_NUM_ENTRIES; + pmr_size = memory_region_size(nonvolatile_mr); + } + + if (ct3d->dc.num_regions) { + if (!ct3d->dc.host_dc) { + return -EINVAL; + } + dc_mr = host_memory_backend_get_memory(ct3d->dc.host_dc); + if (!dc_mr) { + return -EINVAL; + } + len += CT3_CDAT_NUM_ENTRIES * ct3d->dc.num_regions; } table = g_malloc0(len * sizeof(*table)); /* Now fill them in */ if (volatile_mr) { - ct3_build_cdat_entries_for_mr(table, dsmad_handle++, volatile_mr, - false, 0); + ct3_build_cdat_entries_for_mr(table, dsmad_handle++, vmr_size, + false, false, 0); cur_ent = CT3_CDAT_NUM_ENTRIES; } if (nonvolatile_mr) { - uint64_t base = volatile_mr ? memory_region_size(volatile_mr) : 0; + uint64_t base = vmr_size; ct3_build_cdat_entries_for_mr(&(table[cur_ent]), dsmad_handle++, - nonvolatile_mr, true, base); + pmr_size, true, false, base); cur_ent += CT3_CDAT_NUM_ENTRIES; } + + if (dc_mr) { + int i; + uint64_t region_base = vmr_size + pmr_size; + + /* + * We assume the dynamic capacity to be volatile for now. + * Non-volatile dynamic capacity will be added if needed in the + * future. + */ + for (i = 0; i < ct3d->dc.num_regions; i++) { + ct3_build_cdat_entries_for_mr(&(table[cur_ent]), + dsmad_handle++, + ct3d->dc.regions[i].len, + false, true, region_base); + ct3d->dc.regions[i].dsmadhandle = dsmad_handle - 1; + + cur_ent += CT3_CDAT_NUM_ENTRIES; + region_base += ct3d->dc.regions[i].len; + } + } + assert(len == cur_ent); *cdat_table = g_steal_pointer(&table); @@ -297,10 +337,17 @@ static void build_dvsecs(CXLType3Dev *ct3d) range2_size_lo = (2 << 5) | (2 << 2) | 0x3 | (ct3d->hostpmem->size & 0xF0000000); } - } else { + } else if (ct3d->hostpmem) { range1_size_hi = ct3d->hostpmem->size >> 32; range1_size_lo = (2 << 5) | (2 << 2) | 0x3 | (ct3d->hostpmem->size & 0xF0000000); + } else { + /* + * For DCD with no static memory, set memory active, memory class bits. + * No range is set. + */ + range1_size_hi = 0; + range1_size_lo = (2 << 5) | (2 << 2) | 0x3; } dvsec = (uint8_t *)&(CXLDVSECDevice){ @@ -567,11 +614,103 @@ static void ct3d_reg_write(void *opaque, hwaddr offset, uint64_t value, } } +/* + * TODO: dc region configuration will be updated once host backend and address + * space support is added for DCD. + */ +static bool cxl_create_dc_regions(CXLType3Dev *ct3d, Error **errp) +{ + int i; + uint64_t region_base = 0; + uint64_t region_len; + uint64_t decode_len; + uint64_t blk_size = 2 * MiB; + CXLDCRegion *region; + MemoryRegion *mr; + uint64_t dc_size; + + mr = host_memory_backend_get_memory(ct3d->dc.host_dc); + dc_size = memory_region_size(mr); + region_len = DIV_ROUND_UP(dc_size, ct3d->dc.num_regions); + + if (dc_size % (ct3d->dc.num_regions * CXL_CAPACITY_MULTIPLIER) != 0) { + error_setg(errp, + "backend size is not multiple of region len: 0x%" PRIx64, + region_len); + return false; + } + if (region_len % CXL_CAPACITY_MULTIPLIER != 0) { + error_setg(errp, "DC region size is unaligned to 0x%" PRIx64, + CXL_CAPACITY_MULTIPLIER); + return false; + } + decode_len = region_len; + + if (ct3d->hostvmem) { + mr = host_memory_backend_get_memory(ct3d->hostvmem); + region_base += memory_region_size(mr); + } + if (ct3d->hostpmem) { + mr = host_memory_backend_get_memory(ct3d->hostpmem); + region_base += memory_region_size(mr); + } + if (region_base % CXL_CAPACITY_MULTIPLIER != 0) { + error_setg(errp, "DC region base not aligned to 0x%" PRIx64, + CXL_CAPACITY_MULTIPLIER); + return false; + } + + for (i = 0, region = &ct3d->dc.regions[0]; + i < ct3d->dc.num_regions; + i++, region++, region_base += region_len) { + *region = (CXLDCRegion) { + .base = region_base, + .decode_len = decode_len, + .len = region_len, + .block_size = blk_size, + /* dsmad_handle set when creating CDAT table entries */ + .flags = 0, + }; + ct3d->dc.total_capacity += region->len; + region->blk_bitmap = bitmap_new(region->len / region->block_size); + } + QTAILQ_INIT(&ct3d->dc.extents); + QTAILQ_INIT(&ct3d->dc.extents_pending); + + return true; +} + +static void cxl_destroy_dc_regions(CXLType3Dev *ct3d) +{ + CXLDCExtent *ent, *ent_next; + CXLDCExtentGroup *group, *group_next; + int i; + CXLDCRegion *region; + + QTAILQ_FOREACH_SAFE(ent, &ct3d->dc.extents, node, ent_next) { + cxl_remove_extent_from_extent_list(&ct3d->dc.extents, ent); + } + + QTAILQ_FOREACH_SAFE(group, &ct3d->dc.extents_pending, node, group_next) { + QTAILQ_REMOVE(&ct3d->dc.extents_pending, group, node); + QTAILQ_FOREACH_SAFE(ent, &group->list, node, ent_next) { + cxl_remove_extent_from_extent_list(&group->list, ent); + } + g_free(group); + } + + for (i = 0; i < ct3d->dc.num_regions; i++) { + region = &ct3d->dc.regions[i]; + g_free(region->blk_bitmap); + } +} + static bool cxl_setup_memory(CXLType3Dev *ct3d, Error **errp) { DeviceState *ds = DEVICE(ct3d); - if (!ct3d->hostmem && !ct3d->hostvmem && !ct3d->hostpmem) { + if (!ct3d->hostmem && !ct3d->hostvmem && !ct3d->hostpmem + && !ct3d->dc.num_regions) { error_setg(errp, "at least one memdev property must be set"); return false; } else if (ct3d->hostmem && ct3d->hostpmem) { @@ -608,7 +747,7 @@ static bool cxl_setup_memory(CXLType3Dev *ct3d, Error **errp) } address_space_init(&ct3d->hostvmem_as, vmr, v_name); ct3d->cxl_dstate.vmem_size = memory_region_size(vmr); - ct3d->cxl_dstate.mem_size += memory_region_size(vmr); + ct3d->cxl_dstate.static_mem_size += memory_region_size(vmr); g_free(v_name); } @@ -631,10 +770,47 @@ static bool cxl_setup_memory(CXLType3Dev *ct3d, Error **errp) } address_space_init(&ct3d->hostpmem_as, pmr, p_name); ct3d->cxl_dstate.pmem_size = memory_region_size(pmr); - ct3d->cxl_dstate.mem_size += memory_region_size(pmr); + ct3d->cxl_dstate.static_mem_size += memory_region_size(pmr); g_free(p_name); } + ct3d->dc.total_capacity = 0; + if (ct3d->dc.num_regions > 0) { + MemoryRegion *dc_mr; + char *dc_name; + + if (!ct3d->dc.host_dc) { + error_setg(errp, "dynamic capacity must have a backing device"); + return false; + } + + dc_mr = host_memory_backend_get_memory(ct3d->dc.host_dc); + if (!dc_mr) { + error_setg(errp, "dynamic capacity must have a backing device"); + return false; + } + + /* + * Set DC regions as volatile for now, non-volatile support can + * be added in the future if needed. + */ + memory_region_set_nonvolatile(dc_mr, false); + memory_region_set_enabled(dc_mr, true); + host_memory_backend_set_mapped(ct3d->dc.host_dc, true); + if (ds->id) { + dc_name = g_strdup_printf("cxl-dcd-dpa-dc-space:%s", ds->id); + } else { + dc_name = g_strdup("cxl-dcd-dpa-dc-space"); + } + address_space_init(&ct3d->dc.host_dc_as, dc_mr, dc_name); + g_free(dc_name); + + if (!cxl_create_dc_regions(ct3d, errp)) { + error_append_hint(errp, "setup DC regions failed"); + return false; + } + } + return true; } @@ -724,6 +900,10 @@ err_release_cdat: err_free_special_ops: g_free(regs->special_ops); err_address_space_free: + if (ct3d->dc.host_dc) { + cxl_destroy_dc_regions(ct3d); + address_space_destroy(&ct3d->dc.host_dc_as); + } if (ct3d->hostpmem) { address_space_destroy(&ct3d->hostpmem_as); } @@ -742,6 +922,10 @@ static void ct3_exit(PCIDevice *pci_dev) pcie_aer_exit(pci_dev); cxl_doe_cdat_release(cxl_cstate); g_free(regs->special_ops); + if (ct3d->dc.host_dc) { + cxl_destroy_dc_regions(ct3d); + address_space_destroy(&ct3d->dc.host_dc_as); + } if (ct3d->hostpmem) { address_space_destroy(&ct3d->hostpmem_as); } @@ -750,6 +934,70 @@ static void ct3_exit(PCIDevice *pci_dev) } } +/* + * Mark the DPA range [dpa, dap + len - 1] to be backed and accessible. This + * happens when a DC extent is added and accepted by the host. + */ +void ct3_set_region_block_backed(CXLType3Dev *ct3d, uint64_t dpa, + uint64_t len) +{ + CXLDCRegion *region; + + region = cxl_find_dc_region(ct3d, dpa, len); + if (!region) { + return; + } + + bitmap_set(region->blk_bitmap, (dpa - region->base) / region->block_size, + len / region->block_size); +} + +/* + * Check whether the DPA range [dpa, dpa + len - 1] is backed with DC extents. + * Used when validating read/write to dc regions + */ +bool ct3_test_region_block_backed(CXLType3Dev *ct3d, uint64_t dpa, + uint64_t len) +{ + CXLDCRegion *region; + uint64_t nbits; + long nr; + + region = cxl_find_dc_region(ct3d, dpa, len); + if (!region) { + return false; + } + + nr = (dpa - region->base) / region->block_size; + nbits = DIV_ROUND_UP(len, region->block_size); + /* + * if bits between [dpa, dpa + len) are all 1s, meaning the DPA range is + * backed with DC extents, return true; else return false. + */ + return find_next_zero_bit(region->blk_bitmap, nr + nbits, nr) == nr + nbits; +} + +/* + * Mark the DPA range [dpa, dap + len - 1] to be unbacked and inaccessible. + * This happens when a dc extent is released by the host. + */ +void ct3_clear_region_block_backed(CXLType3Dev *ct3d, uint64_t dpa, + uint64_t len) +{ + CXLDCRegion *region; + uint64_t nbits; + long nr; + + region = cxl_find_dc_region(ct3d, dpa, len); + if (!region) { + return; + } + + nr = (dpa - region->base) / region->block_size; + nbits = len / region->block_size; + bitmap_clear(region->blk_bitmap, nr, nbits); +} + static bool cxl_type3_dpa(CXLType3Dev *ct3d, hwaddr host_addr, uint64_t *dpa) { int hdm_inc = R_CXL_HDM_DECODER1_BASE_LO - R_CXL_HDM_DECODER0_BASE_LO; @@ -820,16 +1068,23 @@ static int cxl_type3_hpa_to_as_and_dpa(CXLType3Dev *ct3d, AddressSpace **as, uint64_t *dpa_offset) { - MemoryRegion *vmr = NULL, *pmr = NULL; + MemoryRegion *vmr = NULL, *pmr = NULL, *dc_mr = NULL; + uint64_t vmr_size = 0, pmr_size = 0, dc_size = 0; if (ct3d->hostvmem) { vmr = host_memory_backend_get_memory(ct3d->hostvmem); + vmr_size = memory_region_size(vmr); } if (ct3d->hostpmem) { pmr = host_memory_backend_get_memory(ct3d->hostpmem); + pmr_size = memory_region_size(pmr); + } + if (ct3d->dc.host_dc) { + dc_mr = host_memory_backend_get_memory(ct3d->dc.host_dc); + dc_size = memory_region_size(dc_mr); } - if (!vmr && !pmr) { + if (!vmr && !pmr && !dc_mr) { return -ENODEV; } @@ -837,19 +1092,22 @@ static int cxl_type3_hpa_to_as_and_dpa(CXLType3Dev *ct3d, return -EINVAL; } - if (*dpa_offset > ct3d->cxl_dstate.mem_size) { + if (*dpa_offset >= vmr_size + pmr_size + dc_size) { return -EINVAL; } - if (vmr) { - if (*dpa_offset < memory_region_size(vmr)) { - *as = &ct3d->hostvmem_as; - } else { - *as = &ct3d->hostpmem_as; - *dpa_offset -= memory_region_size(vmr); - } - } else { + if (*dpa_offset < vmr_size) { + *as = &ct3d->hostvmem_as; + } else if (*dpa_offset < vmr_size + pmr_size) { *as = &ct3d->hostpmem_as; + *dpa_offset -= vmr_size; + } else { + if (!ct3_test_region_block_backed(ct3d, *dpa_offset, size)) { + return -ENODEV; + } + + *as = &ct3d->dc.host_dc_as; + *dpa_offset -= (vmr_size + pmr_size); } return 0; @@ -930,6 +1188,9 @@ static Property ct3_props[] = { HostMemoryBackend *), DEFINE_PROP_UINT64("sn", CXLType3Dev, sn, UI64_NULL), DEFINE_PROP_STRING("cdat", CXLType3Dev, cxl_cstate.cdat.filename), + DEFINE_PROP_UINT8("num-dc-regions", CXLType3Dev, dc.num_regions, 0), + DEFINE_PROP_LINK("volatile-dc-memdev", CXLType3Dev, dc.host_dc, + TYPE_MEMORY_BACKEND, HostMemoryBackend *), DEFINE_PROP_END_OF_LIST(), }; @@ -996,36 +1257,42 @@ static void set_lsa(CXLType3Dev *ct3d, const void *buf, uint64_t size, static bool set_cacheline(CXLType3Dev *ct3d, uint64_t dpa_offset, uint8_t *data) { - MemoryRegion *vmr = NULL, *pmr = NULL; + MemoryRegion *vmr = NULL, *pmr = NULL, *dc_mr = NULL; AddressSpace *as; + uint64_t vmr_size = 0, pmr_size = 0, dc_size = 0; if (ct3d->hostvmem) { vmr = host_memory_backend_get_memory(ct3d->hostvmem); + vmr_size = memory_region_size(vmr); } if (ct3d->hostpmem) { pmr = host_memory_backend_get_memory(ct3d->hostpmem); + pmr_size = memory_region_size(pmr); } + if (ct3d->dc.host_dc) { + dc_mr = host_memory_backend_get_memory(ct3d->dc.host_dc); + dc_size = memory_region_size(dc_mr); + } - if (!vmr && !pmr) { + if (!vmr && !pmr && !dc_mr) { return false; } - if (dpa_offset + CXL_CACHE_LINE_SIZE > ct3d->cxl_dstate.mem_size) { + if (dpa_offset + CXL_CACHE_LINE_SIZE > vmr_size + pmr_size + dc_size) { return false; } - if (vmr) { - if (dpa_offset < memory_region_size(vmr)) { - as = &ct3d->hostvmem_as; - } else { - as = &ct3d->hostpmem_as; - dpa_offset -= memory_region_size(vmr); - } - } else { + if (dpa_offset < vmr_size) { + as = &ct3d->hostvmem_as; + } else if (dpa_offset < vmr_size + pmr_size) { as = &ct3d->hostpmem_as; + dpa_offset -= vmr_size; + } else { + as = &ct3d->dc.host_dc_as; + dpa_offset -= (vmr_size + pmr_size); } - address_space_write(as, dpa_offset, MEMTXATTRS_UNSPECIFIED, &data, + address_space_write(as, dpa_offset, MEMTXATTRS_UNSPECIFIED, data, CXL_CACHE_LINE_SIZE); return true; } @@ -1268,7 +1535,6 @@ static int ct3d_qmp_cxl_event_log_enc(CxlEventLog log) return CXL_EVENT_TYPE_FAIL; case CXL_EVENT_LOG_FATAL: return CXL_EVENT_TYPE_FATAL; -/* DCD not yet supported */ default: return -EINVAL; } @@ -1519,6 +1785,301 @@ void qmp_cxl_inject_memory_module_event(const char *path, CxlEventLog log, } } +/* CXL r3.1 Table 8-50: Dynamic Capacity Event Record */ +static const QemuUUID dynamic_capacity_uuid = { + .data = UUID(0xca95afa7, 0xf183, 0x4018, 0x8c, 0x2f, + 0x95, 0x26, 0x8e, 0x10, 0x1a, 0x2a), +}; + +typedef enum CXLDCEventType { + DC_EVENT_ADD_CAPACITY = 0x0, + DC_EVENT_RELEASE_CAPACITY = 0x1, + DC_EVENT_FORCED_RELEASE_CAPACITY = 0x2, + DC_EVENT_REGION_CONFIG_UPDATED = 0x3, + DC_EVENT_ADD_CAPACITY_RSP = 0x4, + DC_EVENT_CAPACITY_RELEASED = 0x5, +} CXLDCEventType; + +/* + * Check whether the range [dpa, dpa + len - 1] has overlaps with extents in + * the list. + * Return value: return true if has overlaps; otherwise, return false + */ +static bool cxl_extents_overlaps_dpa_range(CXLDCExtentList *list, + uint64_t dpa, uint64_t len) +{ + CXLDCExtent *ent; + Range range1, range2; + + if (!list) { + return false; + } + + range_init_nofail(&range1, dpa, len); + QTAILQ_FOREACH(ent, list, node) { + range_init_nofail(&range2, ent->start_dpa, ent->len); + if (range_overlaps_range(&range1, &range2)) { + return true; + } + } + return false; +} + +/* + * Check whether the range [dpa, dpa + len - 1] is contained by extents in + * the list. + * Will check multiple extents containment once superset release is added. + * Return value: return true if range is contained; otherwise, return false + */ +bool cxl_extents_contains_dpa_range(CXLDCExtentList *list, + uint64_t dpa, uint64_t len) +{ + CXLDCExtent *ent; + Range range1, range2; + + if (!list) { + return false; + } + + range_init_nofail(&range1, dpa, len); + QTAILQ_FOREACH(ent, list, node) { + range_init_nofail(&range2, ent->start_dpa, ent->len); + if (range_contains_range(&range2, &range1)) { + return true; + } + } + return false; +} + +static bool cxl_extent_groups_overlaps_dpa_range(CXLDCExtentGroupList *list, + uint64_t dpa, uint64_t len) +{ + CXLDCExtentGroup *group; + + if (!list) { + return false; + } + + QTAILQ_FOREACH(group, list, node) { + if (cxl_extents_overlaps_dpa_range(&group->list, dpa, len)) { + return true; + } + } + return false; +} + +/* + * The main function to process dynamic capacity event with extent list. + * Currently DC extents add/release requests are processed. + */ +static void qmp_cxl_process_dynamic_capacity_prescriptive(const char *path, + uint16_t hid, CXLDCEventType type, uint8_t rid, + CxlDynamicCapacityExtentList *records, Error **errp) +{ + Object *obj; + CXLEventDynamicCapacity dCap = {}; + CXLEventRecordHdr *hdr = &dCap.hdr; + CXLType3Dev *dcd; + uint8_t flags = 1 << CXL_EVENT_TYPE_INFO; + uint32_t num_extents = 0; + CxlDynamicCapacityExtentList *list; + CXLDCExtentGroup *group = NULL; + g_autofree CXLDCExtentRaw *extents = NULL; + uint8_t enc_log = CXL_EVENT_TYPE_DYNAMIC_CAP; + uint64_t dpa, offset, len, block_size; + g_autofree unsigned long *blk_bitmap = NULL; + int i; + + obj = object_resolve_path_type(path, TYPE_CXL_TYPE3, NULL); + if (!obj) { + error_setg(errp, "Unable to resolve CXL type 3 device"); + return; + } + + dcd = CXL_TYPE3(obj); + if (!dcd->dc.num_regions) { + error_setg(errp, "No dynamic capacity support from the device"); + return; + } + + + if (rid >= dcd->dc.num_regions) { + error_setg(errp, "region id is too large"); + return; + } + block_size = dcd->dc.regions[rid].block_size; + blk_bitmap = bitmap_new(dcd->dc.regions[rid].len / block_size); + + /* Sanity check and count the extents */ + list = records; + while (list) { + offset = list->value->offset; + len = list->value->len; + dpa = offset + dcd->dc.regions[rid].base; + + if (len == 0) { + error_setg(errp, "extent with 0 length is not allowed"); + return; + } + + if (offset % block_size || len % block_size) { + error_setg(errp, "dpa or len is not aligned to region block size"); + return; + } + + if (offset + len > dcd->dc.regions[rid].len) { + error_setg(errp, "extent range is beyond the region end"); + return; + } + + /* No duplicate or overlapped extents are allowed */ + if (test_any_bits_set(blk_bitmap, offset / block_size, + len / block_size)) { + error_setg(errp, "duplicate or overlapped extents are detected"); + return; + } + bitmap_set(blk_bitmap, offset / block_size, len / block_size); + + if (type == DC_EVENT_RELEASE_CAPACITY) { + if (cxl_extent_groups_overlaps_dpa_range(&dcd->dc.extents_pending, + dpa, len)) { + error_setg(errp, + "cannot release extent with pending DPA range"); + return; + } + if (!ct3_test_region_block_backed(dcd, dpa, len)) { + error_setg(errp, + "cannot release extent with non-existing DPA range"); + return; + } + } else if (type == DC_EVENT_ADD_CAPACITY) { + if (cxl_extents_overlaps_dpa_range(&dcd->dc.extents, dpa, len)) { + error_setg(errp, + "cannot add DPA already accessible to the same LD"); + return; + } + if (cxl_extent_groups_overlaps_dpa_range(&dcd->dc.extents_pending, + dpa, len)) { + error_setg(errp, + "cannot add DPA again while still pending"); + return; + } + } + list = list->next; + num_extents++; + } + + /* Create extent list for event being passed to host */ + i = 0; + list = records; + extents = g_new0(CXLDCExtentRaw, num_extents); + while (list) { + offset = list->value->offset; + len = list->value->len; + dpa = dcd->dc.regions[rid].base + offset; + + extents[i].start_dpa = dpa; + extents[i].len = len; + memset(extents[i].tag, 0, 0x10); + extents[i].shared_seq = 0; + if (type == DC_EVENT_ADD_CAPACITY) { + group = cxl_insert_extent_to_extent_group(group, + extents[i].start_dpa, + extents[i].len, + extents[i].tag, + extents[i].shared_seq); + } + + list = list->next; + i++; + } + if (group) { + cxl_extent_group_list_insert_tail(&dcd->dc.extents_pending, group); + } + + /* + * CXL r3.1 section 8.2.9.2.1.6: Dynamic Capacity Event Record + * + * All Dynamic Capacity event records shall set the Event Record Severity + * field in the Common Event Record Format to Informational Event. All + * Dynamic Capacity related events shall be logged in the Dynamic Capacity + * Event Log. + */ + cxl_assign_event_header(hdr, &dynamic_capacity_uuid, flags, sizeof(dCap), + cxl_device_get_timestamp(&dcd->cxl_dstate)); + + dCap.type = type; + /* FIXME: for now, validity flag is cleared */ + dCap.validity_flags = 0; + stw_le_p(&dCap.host_id, hid); + /* only valid for DC_REGION_CONFIG_UPDATED event */ + dCap.updated_region_id = 0; + dCap.flags = 0; + for (i = 0; i < num_extents; i++) { + memcpy(&dCap.dynamic_capacity_extent, &extents[i], + sizeof(CXLDCExtentRaw)); + + if (i < num_extents - 1) { + /* Set "More" flag */ + dCap.flags |= BIT(0); + } + + if (cxl_event_insert(&dcd->cxl_dstate, enc_log, + (CXLEventRecordRaw *)&dCap)) { + cxl_event_irq_assert(dcd); + } + } +} + +void qmp_cxl_add_dynamic_capacity(const char *path, uint16_t host_id, + CxlExtentSelectionPolicy sel_policy, + uint8_t region, const char *tag, + CxlDynamicCapacityExtentList *extents, + Error **errp) +{ + switch (sel_policy) { + case CXL_EXTENT_SELECTION_POLICY_PRESCRIPTIVE: + qmp_cxl_process_dynamic_capacity_prescriptive(path, host_id, + DC_EVENT_ADD_CAPACITY, + region, extents, errp); + return; + default: + error_setg(errp, "Selection policy not supported"); + return; + } +} + +void qmp_cxl_release_dynamic_capacity(const char *path, uint16_t host_id, + CxlExtentRemovalPolicy removal_policy, + bool has_forced_removal, + bool forced_removal, + bool has_sanitize_on_release, + bool sanitize_on_release, + uint8_t region, + const char *tag, + CxlDynamicCapacityExtentList *extents, + Error **errp) +{ + CXLDCEventType type = DC_EVENT_RELEASE_CAPACITY; + + if (has_forced_removal && forced_removal) { + /* TODO: enable forced removal in the future */ + type = DC_EVENT_FORCED_RELEASE_CAPACITY; + error_setg(errp, "Forced removal not supported yet"); + return; + } + + switch (removal_policy) { + case CXL_EXTENT_REMOVAL_POLICY_PRESCRIPTIVE: + qmp_cxl_process_dynamic_capacity_prescriptive(path, host_id, type, + region, extents, errp); + return; + default: + error_setg(errp, "Removal policy not supported"); + return; + } +} + static void ct3_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); diff --git a/hw/mem/cxl_type3_stubs.c b/hw/mem/cxl_type3_stubs.c index 3e1851e32b..c1a5e4a7c1 100644 --- a/hw/mem/cxl_type3_stubs.c +++ b/hw/mem/cxl_type3_stubs.c @@ -67,3 +67,28 @@ void qmp_cxl_inject_correctable_error(const char *path, CxlCorErrorType type, { error_setg(errp, "CXL Type 3 support is not compiled in"); } + +void qmp_cxl_add_dynamic_capacity(const char *path, + uint16_t host_id, + CxlExtentSelectionPolicy sel_policy, + uint8_t region, + const char *tag, + CxlDynamicCapacityExtentList *extents, + Error **errp) +{ + error_setg(errp, "CXL Type 3 support is not compiled in"); +} + +void qmp_cxl_release_dynamic_capacity(const char *path, uint16_t host_id, + CxlExtentRemovalPolicy removal_policy, + bool has_forced_removal, + bool forced_removal, + bool has_sanitize_on_release, + bool sanitize_on_release, + uint8_t region, + const char *tag, + CxlDynamicCapacityExtentList *extents, + Error **errp) +{ + error_setg(errp, "CXL Type 3 support is not compiled in"); +} diff --git a/hw/misc/pvpanic-isa.c b/hw/misc/pvpanic-isa.c index b4f84c4110..9a923b7869 100644 --- a/hw/misc/pvpanic-isa.c +++ b/hw/misc/pvpanic-isa.c @@ -21,7 +21,6 @@ #include "hw/misc/pvpanic.h" #include "qom/object.h" #include "hw/isa/isa.h" -#include "standard-headers/misc/pvpanic.h" #include "hw/acpi/acpi_aml_interface.h" OBJECT_DECLARE_SIMPLE_TYPE(PVPanicISAState, PVPANIC_ISA_DEVICE) @@ -102,7 +101,7 @@ static void build_pvpanic_isa_aml(AcpiDevAmlIf *adev, Aml *scope) static Property pvpanic_isa_properties[] = { DEFINE_PROP_UINT16(PVPANIC_IOPORT_PROP, PVPanicISAState, ioport, 0x505), DEFINE_PROP_UINT8("events", PVPanicISAState, pvpanic.events, - PVPANIC_PANICKED | PVPANIC_CRASH_LOADED), + PVPANIC_EVENTS), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/misc/pvpanic-pci.c b/hw/misc/pvpanic-pci.c index 4d44a881da..106d03ccd6 100644 --- a/hw/misc/pvpanic-pci.c +++ b/hw/misc/pvpanic-pci.c @@ -55,7 +55,7 @@ static void pvpanic_pci_realizefn(PCIDevice *dev, Error **errp) static Property pvpanic_pci_properties[] = { DEFINE_PROP_UINT8("events", PVPanicPCIState, pvpanic.events, - PVPANIC_PANICKED | PVPANIC_CRASH_LOADED), + PVPANIC_EVENTS), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c index 80289ecf5f..3b893340c0 100644 --- a/hw/misc/pvpanic.c +++ b/hw/misc/pvpanic.c @@ -27,7 +27,7 @@ static void handle_event(int event) { static bool logged; - if (event & ~(PVPANIC_PANICKED | PVPANIC_CRASH_LOADED) && !logged) { + if (event & ~PVPANIC_EVENTS && !logged) { qemu_log_mask(LOG_GUEST_ERROR, "pvpanic: unknown event %#x.\n", event); logged = true; } @@ -41,6 +41,11 @@ static void handle_event(int event) qemu_system_guest_crashloaded(NULL); return; } + + if (event & PVPANIC_SHUTDOWN) { + qemu_system_guest_pvshutdown(); + return; + } } /* return supported events on read */ diff --git a/hw/net/igb.c b/hw/net/igb.c index b92bba402e..b6ca2f1b8a 100644 --- a/hw/net/igb.c +++ b/hw/net/igb.c @@ -446,9 +446,16 @@ static void igb_pci_realize(PCIDevice *pci_dev, Error **errp) pcie_ari_init(pci_dev, 0x150); - pcie_sriov_pf_init(pci_dev, IGB_CAP_SRIOV_OFFSET, TYPE_IGBVF, - IGB_82576_VF_DEV_ID, IGB_MAX_VF_FUNCTIONS, IGB_MAX_VF_FUNCTIONS, - IGB_VF_OFFSET, IGB_VF_STRIDE); + if (!pcie_sriov_pf_init(pci_dev, IGB_CAP_SRIOV_OFFSET, + TYPE_IGBVF, IGB_82576_VF_DEV_ID, + IGB_MAX_VF_FUNCTIONS, IGB_MAX_VF_FUNCTIONS, + IGB_VF_OFFSET, IGB_VF_STRIDE, + errp)) { + pcie_cap_exit(pci_dev); + igb_cleanup_msix(s); + msi_uninit(pci_dev); + return; + } pcie_sriov_pf_init_vf_bar(pci_dev, IGBVF_MMIO_BAR_IDX, PCI_BASE_ADDRESS_MEM_TYPE_64 | PCI_BASE_ADDRESS_MEM_PREFETCH, diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index fd1a93701a..18898afe81 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -48,6 +48,7 @@ static const int kernel_feature_bits[] = { VIRTIO_F_IOMMU_PLATFORM, VIRTIO_F_RING_PACKED, VIRTIO_F_RING_RESET, + VIRTIO_F_NOTIFICATION_DATA, VIRTIO_NET_F_HASH_REPORT, VHOST_INVALID_FEATURE_BIT }; @@ -55,6 +56,7 @@ static const int kernel_feature_bits[] = { /* Features supported by others. */ static const int user_feature_bits[] = { VIRTIO_F_NOTIFY_ON_EMPTY, + VIRTIO_F_NOTIFICATION_DATA, VIRTIO_RING_F_INDIRECT_DESC, VIRTIO_RING_F_EVENT_IDX, diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 9c7e85caea..8f30972708 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -2735,6 +2735,10 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q) */ assert(n->host_hdr_len <= n->guest_hdr_len); if (n->host_hdr_len != n->guest_hdr_len) { + if (iov_size(out_sg, out_num) < n->guest_hdr_len) { + virtio_error(vdev, "virtio-net header is invalid"); + goto detach; + } unsigned sg_num = iov_copy(sg, ARRAY_SIZE(sg), out_sg, out_num, 0, n->host_hdr_len); diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 127c3d2383..066389e391 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -8048,7 +8048,8 @@ out: return pow2ceil(bar_size); } -static void nvme_init_sriov(NvmeCtrl *n, PCIDevice *pci_dev, uint16_t offset) +static bool nvme_init_sriov(NvmeCtrl *n, PCIDevice *pci_dev, uint16_t offset, + Error **errp) { uint16_t vf_dev_id = n->params.use_intel_id ? PCI_DEVICE_ID_INTEL_NVME : PCI_DEVICE_ID_REDHAT_NVME; @@ -8057,12 +8058,17 @@ static void nvme_init_sriov(NvmeCtrl *n, PCIDevice *pci_dev, uint16_t offset) le16_to_cpu(cap->vifrsm), NULL, NULL); - pcie_sriov_pf_init(pci_dev, offset, "nvme", vf_dev_id, - n->params.sriov_max_vfs, n->params.sriov_max_vfs, - NVME_VF_OFFSET, NVME_VF_STRIDE); + if (!pcie_sriov_pf_init(pci_dev, offset, "nvme", vf_dev_id, + n->params.sriov_max_vfs, n->params.sriov_max_vfs, + NVME_VF_OFFSET, NVME_VF_STRIDE, + errp)) { + return false; + } pcie_sriov_pf_init_vf_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64, bar_size); + + return true; } static int nvme_add_pm_capability(PCIDevice *pci_dev, uint8_t offset) @@ -8155,6 +8161,12 @@ static bool nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp) return false; } + if (!pci_is_vf(pci_dev) && n->params.sriov_max_vfs && + !nvme_init_sriov(n, pci_dev, 0x120, errp)) { + msix_uninit(pci_dev, &n->bar0, &n->bar0); + return false; + } + nvme_update_msixcap_ts(pci_dev, n->conf_msix_qsize); if (n->params.cmb_size_mb) { @@ -8165,10 +8177,6 @@ static bool nvme_init_pci(NvmeCtrl *n, PCIDevice *pci_dev, Error **errp) nvme_init_pmr(n, pci_dev); } - if (!pci_is_vf(pci_dev) && n->params.sriov_max_vfs) { - nvme_init_sriov(n, pci_dev, 0x120); - } - return true; } diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 50b86d5790..4c7be52951 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -70,7 +70,7 @@ static bool pcie_has_upstream_port(PCIDevice *dev); static Property pci_props[] = { DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1), DEFINE_PROP_STRING("romfile", PCIDevice, romfile), - DEFINE_PROP_UINT32("romsize", PCIDevice, romsize, -1), + DEFINE_PROP_UINT32("romsize", PCIDevice, romsize, UINT32_MAX), DEFINE_PROP_UINT32("rombar", PCIDevice, rom_bar, 1), DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present, QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false), @@ -733,10 +733,17 @@ static bool migrate_is_not_pcie(void *opaque, int version_id) return !pci_is_express((PCIDevice *)opaque); } +static int pci_post_load(void *opaque, int version_id) +{ + pcie_sriov_pf_post_load(opaque); + return 0; +} + const VMStateDescription vmstate_pci_device = { .name = "PCIDevice", .version_id = 2, .minimum_version_id = 1, + .post_load = pci_post_load, .fields = (const VMStateField[]) { VMSTATE_INT32_POSITIVE_LE(version_id, PCIDevice), VMSTATE_BUFFER_UNSAFE_INFO_TEST(config, PCIDevice, @@ -1525,7 +1532,7 @@ static void pci_update_mappings(PCIDevice *d) continue; new_addr = pci_bar_address(d, i, r->type, r->size); - if (!d->has_power) { + if (!d->enabled) { new_addr = PCI_BAR_UNMAPPED; } @@ -1613,7 +1620,7 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val_in, int pci_update_irq_disabled(d, was_irq_disabled); memory_region_set_enabled(&d->bus_master_enable_region, (pci_get_word(d->config + PCI_COMMAND) - & PCI_COMMAND_MASTER) && d->has_power); + & PCI_COMMAND_MASTER) && d->enabled); } msi_write_config(d, addr, val_in, l); @@ -2066,7 +2073,7 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp) g_cmp_uint32, NULL); } - if (pci_dev->romsize != -1 && !is_power_of_2(pci_dev->romsize)) { + if (pci_dev->romsize != UINT32_MAX && !is_power_of_2(pci_dev->romsize)) { error_setg(errp, "ROM size %u is not a power of two", pci_dev->romsize); return; } @@ -2352,7 +2359,7 @@ static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom, return; } - if (load_file || pdev->romsize == -1) { + if (load_file || pdev->romsize == UINT32_MAX) { path = qemu_find_file(QEMU_FILE_TYPE_BIOS, pdev->romfile); if (path == NULL) { path = g_strdup(pdev->romfile); @@ -2371,7 +2378,7 @@ static void pci_add_option_rom(PCIDevice *pdev, bool is_default_rom, pdev->romfile); return; } - if (pdev->romsize != -1) { + if (pdev->romsize != UINT_MAX) { if (size > pdev->romsize) { error_setg(errp, "romfile \"%s\" (%u bytes) " "is too large for ROM size %u", @@ -2884,18 +2891,18 @@ MSIMessage pci_get_msi_message(PCIDevice *dev, int vector) return msg; } -void pci_set_power(PCIDevice *d, bool state) +void pci_set_enabled(PCIDevice *d, bool state) { - if (d->has_power == state) { + if (d->enabled == state) { return; } - d->has_power = state; + d->enabled = state; pci_update_mappings(d); memory_region_set_enabled(&d->bus_master_enable_region, (pci_get_word(d->config + PCI_COMMAND) - & PCI_COMMAND_MASTER) && d->has_power); - if (!d->has_power) { + & PCI_COMMAND_MASTER) && d->enabled); + if (d->qdev.realized) { pci_device_reset(d); } } diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c index dfe6fe6184..0d82727cc9 100644 --- a/hw/pci/pci_host.c +++ b/hw/pci/pci_host.c @@ -86,7 +86,7 @@ void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr, * allowing direct removal of unexposed functions. */ if ((pci_dev->qdev.hotplugged && !pci_get_function_0(pci_dev)) || - !pci_dev->has_power || is_pci_dev_ejected(pci_dev)) { + !pci_dev->enabled || is_pci_dev_ejected(pci_dev)) { return; } @@ -111,7 +111,7 @@ uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr, * allowing direct removal of unexposed functions. */ if ((pci_dev->qdev.hotplugged && !pci_get_function_0(pci_dev)) || - !pci_dev->has_power || is_pci_dev_ejected(pci_dev)) { + !pci_dev->enabled || is_pci_dev_ejected(pci_dev)) { return ~0x0; } diff --git a/hw/pci/pcie_sriov.c b/hw/pci/pcie_sriov.c index e9b23221d7..56523ab4e8 100644 --- a/hw/pci/pcie_sriov.c +++ b/hw/pci/pcie_sriov.c @@ -20,23 +20,43 @@ #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); +static void unparent_vfs(PCIDevice *dev, uint16_t total_vfs) +{ + for (uint16_t i = 0; i < total_vfs; i++) { + PCIDevice *vf = dev->exp.sriov_pf.vf[i]; + object_unparent(OBJECT(vf)); + object_unref(OBJECT(vf)); + } + g_free(dev->exp.sriov_pf.vf); + dev->exp.sriov_pf.vf = NULL; +} -void pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset, +bool 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) + uint16_t vf_offset, uint16_t vf_stride, + Error **errp) { + BusState *bus = qdev_get_parent_bus(&dev->qdev); + int32_t devfn = dev->devfn + vf_offset; uint8_t *cfg = dev->config + offset; uint8_t *wmask; + if (total_vfs) { + uint16_t ari_cap = pcie_find_capability(dev, PCI_EXT_CAP_ID_ARI); + uint16_t first_vf_devfn = dev->devfn + vf_offset; + uint16_t last_vf_devfn = first_vf_devfn + vf_stride * (total_vfs - 1); + + if ((!ari_cap && PCI_SLOT(dev->devfn) != PCI_SLOT(last_vf_devfn)) || + last_vf_devfn >= PCI_DEVFN_MAX) { + error_setg(errp, "VF function number overflows"); + return false; + } + } + 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); @@ -69,13 +89,37 @@ void pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset, pci_set_word(wmask + PCI_SRIOV_SYS_PGSIZE, 0x553); qdev_prop_set_bit(&dev->qdev, "multifunction", true); + + dev->exp.sriov_pf.vf = g_new(PCIDevice *, total_vfs); + + for (uint16_t i = 0; i < total_vfs; i++) { + PCIDevice *vf = pci_new(devfn, vfname); + vf->exp.sriov_vf.pf = dev; + vf->exp.sriov_vf.vf_number = i; + + if (!qdev_realize(&vf->qdev, bus, errp)) { + object_unparent(OBJECT(vf)); + object_unref(vf); + unparent_vfs(dev, i); + return false; + } + + /* set vid/did according to sr/iov spec - they are not used */ + pci_config_set_vendor_id(vf->config, 0xffff); + pci_config_set_device_id(vf->config, 0xffff); + + dev->exp.sriov_pf.vf[i] = vf; + devfn += vf_stride; + } + + return 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; + uint8_t *cfg = dev->config + dev->exp.sriov_cap; + + unparent_vfs(dev, pci_get_word(cfg + PCI_SRIOV_TOTAL_VF)); } void pcie_sriov_pf_init_vf_bar(PCIDevice *dev, int region_num, @@ -141,26 +185,10 @@ void pcie_sriov_vf_register_bar(PCIDevice *dev, int region_num, } } -static PCIDevice *register_vf(PCIDevice *pf, int devfn, const char *name, - uint16_t vf_num) +static void clear_ctrl_vfe(PCIDevice *dev) { - 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; + uint8_t *ctrl = dev->config + dev->exp.sriov_cap + PCI_SRIOV_CTRL; + pci_set_word(ctrl, pci_get_word(ctrl) & ~PCI_SRIOV_CTRL_VFE); } static void register_vfs(PCIDevice *dev) @@ -168,53 +196,31 @@ 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); if (num_vfs > pci_get_word(dev->config + sriov_cap + PCI_SRIOV_TOTAL_VF)) { + clear_ctrl_vfe(dev); return; } - dev->exp.sriov_pf.vf = g_new(PCIDevice *, num_vfs); - 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; + pci_set_enabled(dev->exp.sriov_pf.vf[i], true); } - dev->exp.sriov_pf.num_vfs = num_vfs; } static void unregister_vfs(PCIDevice *dev) { - uint16_t num_vfs = dev->exp.sriov_pf.num_vfs; uint16_t i; + uint8_t *cfg = dev->config + dev->exp.sriov_cap; trace_sriov_unregister_vfs(dev->name, PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn), num_vfs); - for (i = 0; i < num_vfs; i++) { - Error *err = NULL; - PCIDevice *vf = dev->exp.sriov_pf.vf[i]; - if (!object_property_set_bool(OBJECT(vf), "realized", false, &err)) { - error_reportf_err(err, "Failed to unplug: "); - } - object_unparent(OBJECT(vf)); - object_unref(OBJECT(vf)); + PCI_FUNC(dev->devfn)); + for (i = 0; i < pci_get_word(cfg + PCI_SRIOV_TOTAL_VF); i++) { + pci_set_enabled(dev->exp.sriov_pf.vf[i], false); } - g_free(dev->exp.sriov_pf.vf); - dev->exp.sriov_pf.vf = NULL; - dev->exp.sriov_pf.num_vfs = 0; } void pcie_sriov_config_write(PCIDevice *dev, uint32_t address, @@ -235,15 +241,21 @@ void pcie_sriov_config_write(PCIDevice *dev, uint32_t address, 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); - } + if (val & PCI_SRIOV_CTRL_VFE) { + register_vfs(dev); } else { - if (val & PCI_SRIOV_CTRL_VFE) { - register_vfs(dev); - } + unregister_vfs(dev); } + } else if (range_covers_byte(off, len, PCI_SRIOV_NUM_VF)) { + clear_ctrl_vfe(dev); + unregister_vfs(dev); + } +} + +void pcie_sriov_pf_post_load(PCIDevice *dev) +{ + if (dev->exp.sriov_cap) { + register_vfs(dev); } } @@ -306,7 +318,7 @@ PCIDevice *pcie_sriov_get_pf(PCIDevice *dev) PCIDevice *pcie_sriov_get_vf_at_index(PCIDevice *dev, int n) { assert(!pci_is_vf(dev)); - if (n < dev->exp.sriov_pf.num_vfs) { + if (n < pcie_sriov_num_vfs(dev)) { return dev->exp.sriov_pf.vf[n]; } return NULL; @@ -314,5 +326,10 @@ PCIDevice *pcie_sriov_get_vf_at_index(PCIDevice *dev, int n) uint16_t pcie_sriov_num_vfs(PCIDevice *dev) { - return dev->exp.sriov_pf.num_vfs; + uint16_t sriov_cap = dev->exp.sriov_cap; + uint8_t *cfg = dev->config + sriov_cap; + + return sriov_cap && + (pci_get_word(cfg + PCI_SRIOV_CTRL) & PCI_SRIOV_CTRL_VFE) ? + pci_get_word(cfg + PCI_SRIOV_NUM_VF) : 0; } diff --git a/hw/pci/trace-events b/hw/pci/trace-events index 19643aa8c6..e98f575a9d 100644 --- a/hw/pci/trace-events +++ b/hw/pci/trace-events @@ -14,7 +14,7 @@ msix_write_config(char *name, bool enabled, bool masked) "dev %s enabled %d mask # 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_unregister_vfs(const char *name, int slot, int function) "%s %02x:%x: Unregistering 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" # pcie.c diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 7cf9904c35..ed4454bbf7 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1296,6 +1296,10 @@ static void spapr_dt_pci_device_cb(PCIBus *bus, PCIDevice *pdev, return; } + if (!pdev->enabled) { + return; + } + err = spapr_dt_pci_device(p->sphb, pdev, p->fdt, p->offset); if (err < 0) { p->err = err; @@ -1569,7 +1573,9 @@ static void spapr_pci_pre_plug(HotplugHandler *plug_handler, * hotplug, we do not allow functions to be hotplugged to a * slot that already has function 0 present */ - if (plugged_dev->hotplugged && bus->devices[PCI_DEVFN(slotnr, 0)] && + if (plugged_dev->hotplugged && + !pci_is_vf(pdev) && + bus->devices[PCI_DEVFN(slotnr, 0)] && PCI_FUNC(pdev->devfn) != 0) { error_setg(errp, "PCI: slot %d function 0 already occupied by %s," " additional functions can no longer be exposed to guest.", diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 5f23c5ad16..c483ff8064 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -127,9 +127,11 @@ static void subsystem_reset(void) static int virtio_ccw_hcall_notify(const uint64_t *args) { uint64_t subch_id = args[0]; - uint64_t queue = args[1]; + uint64_t data = args[1]; SubchDev *sch; + VirtIODevice *vdev; int cssid, ssid, schid, m; + uint16_t vq_idx = data; if (ioinst_disassemble_sch_ident(subch_id, &m, &cssid, &ssid, &schid)) { return -EINVAL; @@ -138,12 +140,19 @@ static int virtio_ccw_hcall_notify(const uint64_t *args) if (!sch || !css_subch_visible(sch)) { return -EINVAL; } - if (queue >= VIRTIO_QUEUE_MAX) { + + vdev = virtio_ccw_get_vdev(sch); + if (vq_idx >= VIRTIO_QUEUE_MAX || !virtio_queue_get_num(vdev, vq_idx)) { return -EINVAL; } - virtio_queue_notify(virtio_ccw_get_vdev(sch), queue); - return 0; + if (virtio_vdev_has_feature(vdev, VIRTIO_F_NOTIFICATION_DATA)) { + virtio_queue_set_shadow_avail_idx(virtio_get_queue(vdev, vq_idx), + (data >> 16) & 0xFFFF); + } + + virtio_queue_notify(vdev, vq_idx); + return 0; } static int virtio_ccw_hcall_early_printk(const uint64_t *args) diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c index ae26bc19a4..3d5fe0994d 100644 --- a/hw/scsi/vhost-scsi.c +++ b/hw/scsi/vhost-scsi.c @@ -38,6 +38,7 @@ static const int kernel_feature_bits[] = { VIRTIO_RING_F_EVENT_IDX, VIRTIO_SCSI_F_HOTPLUG, VIRTIO_F_RING_RESET, + VIRTIO_F_NOTIFICATION_DATA, VHOST_INVALID_FEATURE_BIT }; diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c index a63b1f4948..cc91ade525 100644 --- a/hw/scsi/vhost-user-scsi.c +++ b/hw/scsi/vhost-user-scsi.c @@ -36,6 +36,7 @@ static const int user_feature_bits[] = { VIRTIO_RING_F_EVENT_IDX, VIRTIO_SCSI_F_HOTPLUG, VIRTIO_F_RING_RESET, + VIRTIO_F_NOTIFICATION_DATA, VHOST_INVALID_FEATURE_BIT }; @@ -181,7 +182,7 @@ static void vhost_user_scsi_disconnect(DeviceState *dev) VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev); if (!s->connected) { - return; + goto done; } s->connected = false; @@ -189,6 +190,7 @@ static void vhost_user_scsi_disconnect(DeviceState *dev) vhost_dev_cleanup(&vsc->dev); +done: /* Re-instate the event handler for new connections */ qemu_chr_fe_set_handlers(&vs->conf.chardev, NULL, NULL, vhost_user_scsi_event, NULL, dev, NULL, true); @@ -214,8 +216,7 @@ static void vhost_user_scsi_event(void *opaque, QEMUChrEvent event) case CHR_EVENT_CLOSED: /* defer close until later to avoid circular close */ vhost_user_async_close(dev, &vs->conf.chardev, &vsc->dev, - vhost_user_scsi_disconnect, - vhost_user_scsi_event); + vhost_user_scsi_disconnect); break; case CHR_EVENT_BREAK: case CHR_EVENT_MUX_IN: diff --git a/hw/virtio/vhost-user-base.c b/hw/virtio/vhost-user-base.c index a83167191e..2bc3423326 100644 --- a/hw/virtio/vhost-user-base.c +++ b/hw/virtio/vhost-user-base.c @@ -223,15 +223,18 @@ static void vub_disconnect(DeviceState *dev) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); VHostUserBase *vub = VHOST_USER_BASE(vdev); + struct vhost_virtqueue *vhost_vqs = vub->vhost_dev.vqs; if (!vub->connected) { - return; + goto done; } vub->connected = false; vub_stop(vdev); vhost_dev_cleanup(&vub->vhost_dev); + g_free(vhost_vqs); +done: /* Re-instate the event handler for new connections */ qemu_chr_fe_set_handlers(&vub->chardev, NULL, NULL, vub_event, @@ -254,7 +257,7 @@ static void vub_event(void *opaque, QEMUChrEvent event) case CHR_EVENT_CLOSED: /* defer close until later to avoid circular close */ vhost_user_async_close(dev, &vub->chardev, &vub->vhost_dev, - vub_disconnect, vub_event); + vub_disconnect); break; case CHR_EVENT_BREAK: case CHR_EVENT_MUX_IN: diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c index cca2cd41be..ae48cc1c96 100644 --- a/hw/virtio/vhost-user-fs.c +++ b/hw/virtio/vhost-user-fs.c @@ -33,7 +33,7 @@ static const int user_feature_bits[] = { VIRTIO_F_RING_PACKED, VIRTIO_F_IOMMU_PLATFORM, VIRTIO_F_RING_RESET, - + VIRTIO_F_NOTIFICATION_DATA, VHOST_INVALID_FEATURE_BIT }; diff --git a/hw/virtio/vhost-user-vsock.c b/hw/virtio/vhost-user-vsock.c index 9431b9792c..802b44a07d 100644 --- a/hw/virtio/vhost-user-vsock.c +++ b/hw/virtio/vhost-user-vsock.c @@ -21,6 +21,7 @@ static const int user_feature_bits[] = { VIRTIO_RING_F_INDIRECT_DESC, VIRTIO_RING_F_EVENT_IDX, VIRTIO_F_NOTIFY_ON_EMPTY, + VIRTIO_F_NOTIFICATION_DATA, VHOST_INVALID_FEATURE_BIT }; diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index cdf9af4a4b..00561daa06 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -371,6 +371,7 @@ static bool vhost_user_per_device_request(VhostUserRequest request) case VHOST_USER_RESET_DEVICE: case VHOST_USER_ADD_MEM_REG: case VHOST_USER_REM_MEM_REG: + case VHOST_USER_SET_LOG_BASE: return true; default: return false; @@ -2776,25 +2777,13 @@ typedef struct { DeviceState *dev; CharBackend *cd; struct vhost_dev *vhost; - IOEventHandler *event_cb; } VhostAsyncCallback; static void vhost_user_async_close_bh(void *opaque) { VhostAsyncCallback *data = opaque; - struct vhost_dev *vhost = data->vhost; - /* - * If the vhost_dev has been cleared in the meantime there is - * nothing left to do as some other path has completed the - * cleanup. - */ - if (vhost->vdev) { - data->cb(data->dev); - } else if (data->event_cb) { - qemu_chr_fe_set_handlers(data->cd, NULL, NULL, data->event_cb, - NULL, data->dev, NULL, true); - } + data->cb(data->dev); g_free(data); } @@ -2806,8 +2795,7 @@ static void vhost_user_async_close_bh(void *opaque) */ void vhost_user_async_close(DeviceState *d, CharBackend *chardev, struct vhost_dev *vhost, - vu_async_close_fn cb, - IOEventHandler *event_cb) + vu_async_close_fn cb) { if (!runstate_check(RUN_STATE_SHUTDOWN)) { /* @@ -2823,7 +2811,6 @@ void vhost_user_async_close(DeviceState *d, data->dev = d; data->cd = chardev; data->vhost = vhost; - data->event_cb = event_cb; /* Disable any further notifications on the chardev */ qemu_chr_fe_set_handlers(chardev, diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c index 12ea87d7a7..fd88df2560 100644 --- a/hw/virtio/vhost-vsock-common.c +++ b/hw/virtio/vhost-vsock-common.c @@ -22,6 +22,7 @@ const int feature_bits[] = { VIRTIO_VSOCK_F_SEQPACKET, VIRTIO_F_RING_RESET, + VIRTIO_F_RING_PACKED, VHOST_INVALID_FEATURE_BIT }; diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 4acd77e890..06fc71746e 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -43,8 +43,9 @@ do { } while (0) #endif -static struct vhost_log *vhost_log; -static struct vhost_log *vhost_log_shm; +static struct vhost_log *vhost_log[VHOST_BACKEND_TYPE_MAX]; +static struct vhost_log *vhost_log_shm[VHOST_BACKEND_TYPE_MAX]; +static QLIST_HEAD(, vhost_dev) vhost_log_devs[VHOST_BACKEND_TYPE_MAX]; /* Memslots used by backends that support private memslots (without an fd). */ static unsigned int used_memslots; @@ -149,6 +150,47 @@ bool vhost_dev_has_iommu(struct vhost_dev *dev) } } +static inline bool vhost_dev_should_log(struct vhost_dev *dev) +{ + assert(dev->vhost_ops); + assert(dev->vhost_ops->backend_type > VHOST_BACKEND_TYPE_NONE); + assert(dev->vhost_ops->backend_type < VHOST_BACKEND_TYPE_MAX); + + return dev == QLIST_FIRST(&vhost_log_devs[dev->vhost_ops->backend_type]); +} + +static inline void vhost_dev_elect_mem_logger(struct vhost_dev *hdev, bool add) +{ + VhostBackendType backend_type; + + assert(hdev->vhost_ops); + + backend_type = hdev->vhost_ops->backend_type; + assert(backend_type > VHOST_BACKEND_TYPE_NONE); + assert(backend_type < VHOST_BACKEND_TYPE_MAX); + + if (add && !QLIST_IS_INSERTED(hdev, logdev_entry)) { + if (QLIST_EMPTY(&vhost_log_devs[backend_type])) { + QLIST_INSERT_HEAD(&vhost_log_devs[backend_type], + hdev, logdev_entry); + } else { + /* + * The first vhost_device in the list is selected as the shared + * logger to scan memory sections. Put new entry next to the head + * to avoid inadvertent change to the underlying logger device. + * This is done in order to get better cache locality and to avoid + * performance churn on the hot path for log scanning. Even when + * new devices come and go quickly, it wouldn't end up changing + * the active leading logger device at all. + */ + QLIST_INSERT_AFTER(QLIST_FIRST(&vhost_log_devs[backend_type]), + hdev, logdev_entry); + } + } else if (!add && QLIST_IS_INSERTED(hdev, logdev_entry)) { + QLIST_REMOVE(hdev, logdev_entry); + } +} + static int vhost_sync_dirty_bitmap(struct vhost_dev *dev, MemoryRegionSection *section, hwaddr first, @@ -166,12 +208,14 @@ static int vhost_sync_dirty_bitmap(struct vhost_dev *dev, start_addr = MAX(first, start_addr); end_addr = MIN(last, end_addr); - for (i = 0; i < dev->mem->nregions; ++i) { - struct vhost_memory_region *reg = dev->mem->regions + i; - vhost_dev_sync_region(dev, section, start_addr, end_addr, - reg->guest_phys_addr, - range_get_last(reg->guest_phys_addr, - reg->memory_size)); + if (vhost_dev_should_log(dev)) { + for (i = 0; i < dev->mem->nregions; ++i) { + struct vhost_memory_region *reg = dev->mem->regions + i; + vhost_dev_sync_region(dev, section, start_addr, end_addr, + reg->guest_phys_addr, + range_get_last(reg->guest_phys_addr, + reg->memory_size)); + } } for (i = 0; i < dev->nvqs; ++i) { struct vhost_virtqueue *vq = dev->vqs + i; @@ -287,6 +331,10 @@ static int vhost_set_backend_type(struct vhost_dev *dev, r = -1; } + if (r == 0) { + assert(dev->vhost_ops->backend_type == backend_type); + } + return r; } @@ -319,16 +367,22 @@ static struct vhost_log *vhost_log_alloc(uint64_t size, bool share) return log; } -static struct vhost_log *vhost_log_get(uint64_t size, bool share) +static struct vhost_log *vhost_log_get(VhostBackendType backend_type, + uint64_t size, bool share) { - struct vhost_log *log = share ? vhost_log_shm : vhost_log; + struct vhost_log *log; + + assert(backend_type > VHOST_BACKEND_TYPE_NONE); + assert(backend_type < VHOST_BACKEND_TYPE_MAX); + + log = share ? vhost_log_shm[backend_type] : vhost_log[backend_type]; if (!log || log->size != size) { log = vhost_log_alloc(size, share); if (share) { - vhost_log_shm = log; + vhost_log_shm[backend_type] = log; } else { - vhost_log = log; + vhost_log[backend_type] = log; } } else { ++log->refcnt; @@ -340,11 +394,20 @@ static struct vhost_log *vhost_log_get(uint64_t size, bool share) static void vhost_log_put(struct vhost_dev *dev, bool sync) { struct vhost_log *log = dev->log; + VhostBackendType backend_type; if (!log) { return; } + assert(dev->vhost_ops); + backend_type = dev->vhost_ops->backend_type; + + if (backend_type == VHOST_BACKEND_TYPE_NONE || + backend_type >= VHOST_BACKEND_TYPE_MAX) { + return; + } + --log->refcnt; if (log->refcnt == 0) { /* Sync only the range covered by the old log */ @@ -352,18 +415,19 @@ static void vhost_log_put(struct vhost_dev *dev, bool sync) vhost_log_sync_range(dev, 0, dev->log_size * VHOST_LOG_CHUNK - 1); } - if (vhost_log == log) { + if (vhost_log[backend_type] == log) { g_free(log->log); - vhost_log = NULL; - } else if (vhost_log_shm == log) { + vhost_log[backend_type] = NULL; + } else if (vhost_log_shm[backend_type] == log) { qemu_memfd_free(log->log, log->size * sizeof(*(log->log)), log->fd); - vhost_log_shm = NULL; + vhost_log_shm[backend_type] = NULL; } g_free(log); } + vhost_dev_elect_mem_logger(dev, false); dev->log = NULL; dev->log_size = 0; } @@ -376,7 +440,8 @@ static bool vhost_dev_log_is_shared(struct vhost_dev *dev) static inline void vhost_dev_log_resize(struct vhost_dev *dev, uint64_t size) { - struct vhost_log *log = vhost_log_get(size, vhost_dev_log_is_shared(dev)); + struct vhost_log *log = vhost_log_get(dev->vhost_ops->backend_type, + size, vhost_dev_log_is_shared(dev)); uint64_t log_base = (uintptr_t)log->log; int r; @@ -978,6 +1043,15 @@ static int vhost_dev_set_log(struct vhost_dev *dev, bool enable_log) goto err_vq; } } + + /* + * At log start we select our vhost_device logger that will scan the + * memory sections and skip for the others. This is possible because + * the log is shared amongst all vhost devices for a given type of + * backend. + */ + vhost_dev_elect_mem_logger(dev, enable_log); + return 0; err_vq: for (; i >= 0; --i) { @@ -2044,7 +2118,8 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings) uint64_t log_base; hdev->log_size = vhost_get_log_size(hdev); - hdev->log = vhost_log_get(hdev->log_size, + hdev->log = vhost_log_get(hdev->vhost_ops->backend_type, + hdev->log_size, vhost_dev_log_is_shared(hdev)); log_base = (uintptr_t)hdev->log->log; r = hdev->vhost_ops->vhost_set_log_base(hdev, @@ -2054,6 +2129,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings) VHOST_OPS_DEBUG(r, "vhost_set_log_base failed"); goto fail_log; } + vhost_dev_elect_mem_logger(hdev, true); } if (vrings) { r = vhost_dev_set_vring_enable(hdev, true); diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c index b9a7ddcd14..7c54c6b5e2 100644 --- a/hw/virtio/virtio-iommu.c +++ b/hw/virtio/virtio-iommu.c @@ -467,6 +467,26 @@ static AddressSpace *virtio_iommu_find_add_as(PCIBus *bus, void *opaque, return &sdev->as; } +static void virtio_iommu_device_clear(VirtIOIOMMU *s, PCIBus *bus, int devfn) +{ + IOMMUPciBus *sbus = g_hash_table_lookup(s->as_by_busptr, bus); + IOMMUDevice *sdev; + + if (!sbus) { + return; + } + + sdev = sbus->pbdev[devfn]; + if (!sdev) { + return; + } + + g_list_free_full(sdev->resv_regions, g_free); + sdev->resv_regions = NULL; + g_free(sdev); + sbus->pbdev[devfn] = NULL; +} + static gboolean hiod_equal(gconstpointer v1, gconstpointer v2) { const struct hiod_key *key1 = v1; @@ -650,6 +670,7 @@ virtio_iommu_unset_iommu_device(PCIBus *bus, void *opaque, int devfn) } g_hash_table_remove(viommu->host_iommu_devices, &key); + virtio_iommu_device_clear(viommu, bus, devfn); } static const PCIIOMMUOps virtio_iommu_ops = { @@ -974,6 +995,9 @@ static void virtio_iommu_handle_command(VirtIODevice *vdev, VirtQueue *vq) iov = elem->out_sg; sz = iov_to_buf(iov, iov_cnt, 0, &head, sizeof(head)); if (unlikely(sz != sizeof(head))) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: read %zu bytes from command head" + "but expected %zu\n", __func__, sz, sizeof(head)); tail.status = VIRTIO_IOMMU_S_DEVERR; goto out; } @@ -1010,6 +1034,25 @@ static void virtio_iommu_handle_command(VirtIODevice *vdev, VirtQueue *vq) out: sz = iov_from_buf(elem->in_sg, elem->in_num, 0, buf ? buf : &tail, output_size); + if (unlikely(sz != output_size)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: wrote %zu bytes to command response" + "but response size is %zu\n", + __func__, sz, output_size); + tail.status = VIRTIO_IOMMU_S_DEVERR; + /* + * We checked that sizeof(tail) can fit to elem->in_sg at the + * beginning of the loop + */ + output_size = sizeof(tail); + g_free(buf); + buf = NULL; + sz = iov_from_buf(elem->in_sg, + elem->in_num, + 0, + &tail, + output_size); + } assert(sz == output_size); virtqueue_push(vq, elem, sz); diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c index 22f9fbcf5a..320428ac0d 100644 --- a/hw/virtio/virtio-mmio.c +++ b/hw/virtio/virtio-mmio.c @@ -248,6 +248,7 @@ static void virtio_mmio_write(void *opaque, hwaddr offset, uint64_t value, { VirtIOMMIOProxy *proxy = (VirtIOMMIOProxy *)opaque; VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + uint16_t vq_idx; trace_virtio_mmio_write_offset(offset, value); @@ -407,8 +408,14 @@ static void virtio_mmio_write(void *opaque, hwaddr offset, uint64_t value, } break; case VIRTIO_MMIO_QUEUE_NOTIFY: - if (value < VIRTIO_QUEUE_MAX) { - virtio_queue_notify(vdev, value); + vq_idx = value; + if (vq_idx < VIRTIO_QUEUE_MAX && virtio_queue_get_num(vdev, vq_idx)) { + if (virtio_vdev_has_feature(vdev, VIRTIO_F_NOTIFICATION_DATA)) { + VirtQueue *vq = virtio_get_queue(vdev, vq_idx); + + virtio_queue_set_shadow_avail_idx(vq, (value >> 16) & 0xFFFF); + } + virtio_queue_notify(vdev, vq_idx); } break; case VIRTIO_MMIO_INTERRUPT_ACK: diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index b1d02f4b3d..9534730bba 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -384,7 +384,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) { VirtIOPCIProxy *proxy = opaque; VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); - uint16_t vector; + uint16_t vector, vq_idx; hwaddr pa; switch (addr) { @@ -408,8 +408,14 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) vdev->queue_sel = val; break; case VIRTIO_PCI_QUEUE_NOTIFY: - if (val < VIRTIO_QUEUE_MAX) { - virtio_queue_notify(vdev, val); + vq_idx = val; + if (vq_idx < VIRTIO_QUEUE_MAX && virtio_queue_get_num(vdev, vq_idx)) { + if (virtio_vdev_has_feature(vdev, VIRTIO_F_NOTIFICATION_DATA)) { + VirtQueue *vq = virtio_get_queue(vdev, vq_idx); + + virtio_queue_set_shadow_avail_idx(vq, val >> 16); + } + virtio_queue_notify(vdev, vq_idx); } break; case VIRTIO_PCI_STATUS: @@ -892,7 +898,7 @@ static int kvm_virtio_pci_vector_use_one(VirtIOPCIProxy *proxy, int queue_no) } ret = kvm_virtio_pci_vq_vector_use(proxy, vector); if (ret < 0) { - goto undo; + return ret; } /* * If guest supports masking, set up irqfd now. @@ -902,25 +908,11 @@ static int kvm_virtio_pci_vector_use_one(VirtIOPCIProxy *proxy, int queue_no) ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); if (ret < 0) { kvm_virtio_pci_vq_vector_release(proxy, vector); - goto undo; + return ret; } } return 0; -undo: - - vector = virtio_queue_vector(vdev, queue_no); - if (vector >= msix_nr_vectors_allocated(dev)) { - return ret; - } - if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { - ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector); - if (ret < 0) { - return ret; - } - kvm_virtio_pci_irqfd_release(proxy, n, vector); - } - return ret; } static int kvm_virtio_pci_vector_vq_use(VirtIOPCIProxy *proxy, int nvqs) { @@ -2230,6 +2222,11 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp) pcie_cap_lnkctl_init(pci_dev); } + if (proxy->flags & VIRTIO_PCI_FLAG_PM_NO_SOFT_RESET) { + pci_set_word(pci_dev->config + pos + PCI_PM_CTRL, + PCI_PM_CTRL_NO_SOFT_RESET); + } + if (proxy->flags & VIRTIO_PCI_FLAG_INIT_PM) { /* Init Power Management Control Register */ pci_set_word(pci_dev->wmask + pos + PCI_PM_CTRL, @@ -2292,18 +2289,46 @@ static void virtio_pci_reset(DeviceState *qdev) } } +static bool virtio_pci_no_soft_reset(PCIDevice *dev) +{ + uint16_t pmcsr; + + if (!pci_is_express(dev) || !dev->exp.pm_cap) { + return false; + } + + pmcsr = pci_get_word(dev->config + dev->exp.pm_cap + PCI_PM_CTRL); + + /* + * When No_Soft_Reset bit is set and the device + * is in D3hot state, don't reset device + */ + return (pmcsr & PCI_PM_CTRL_NO_SOFT_RESET) && + (pmcsr & PCI_PM_CTRL_STATE_MASK) == 3; +} + static void virtio_pci_bus_reset_hold(Object *obj, ResetType type) { PCIDevice *dev = PCI_DEVICE(obj); DeviceState *qdev = DEVICE(obj); + if (virtio_pci_no_soft_reset(dev)) { + return; + } + virtio_pci_reset(qdev); if (pci_is_express(dev)) { + VirtIOPCIProxy *proxy = VIRTIO_PCI(dev); + pcie_cap_deverr_reset(dev); pcie_cap_lnkctl_reset(dev); - pci_set_word(dev->config + dev->exp.pm_cap + PCI_PM_CTRL, 0); + if (proxy->flags & VIRTIO_PCI_FLAG_INIT_PM) { + pci_word_test_and_clear_mask( + dev->config + dev->exp.pm_cap + PCI_PM_CTRL, + PCI_PM_CTRL_STATE_MASK); + } } } @@ -2330,6 +2355,8 @@ static Property virtio_pci_properties[] = { VIRTIO_PCI_FLAG_INIT_LNKCTL_BIT, true), DEFINE_PROP_BIT("x-pcie-pm-init", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_INIT_PM_BIT, true), + DEFINE_PROP_BIT("x-pcie-pm-no-soft-reset", VirtIOPCIProxy, flags, + VIRTIO_PCI_FLAG_PM_NO_SOFT_RESET_BIT, false), DEFINE_PROP_BIT("x-pcie-flr-init", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_INIT_FLR_BIT, true), DEFINE_PROP_BIT("aer", VirtIOPCIProxy, flags, diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 893a072c9d..583a224163 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -323,7 +323,6 @@ static void vring_packed_event_read(VirtIODevice *vdev, /* Make sure flags is seen before off_wrap */ smp_rmb(); e->off_wrap = virtio_lduw_phys_cached(vdev, cache, off_off); - virtio_tswap16s(vdev, &e->flags); } static void vring_packed_off_wrap_write(VirtIODevice *vdev, @@ -1745,6 +1744,11 @@ static void *virtqueue_packed_pop(VirtQueue *vq, size_t sz) &indirect_desc_cache); } while (rc == VIRTQUEUE_READ_DESC_MORE); + if (desc_cache != &indirect_desc_cache) { + /* Buffer ID is included in the last descriptor in the list. */ + id = desc.id; + } + /* Now copy what we have collected and mapped */ elem = virtqueue_alloc_element(sz, out_num, in_num); for (i = 0; i < out_num; i++) { @@ -2264,6 +2268,24 @@ void virtio_queue_set_align(VirtIODevice *vdev, int n, int align) } } +void virtio_queue_set_shadow_avail_idx(VirtQueue *vq, uint16_t shadow_avail_idx) +{ + if (!vq->vring.desc) { + return; + } + + /* + * 16-bit data for packed VQs include 1-bit wrap counter and + * 15-bit shadow_avail_idx. + */ + if (virtio_vdev_has_feature(vq->vdev, VIRTIO_F_RING_PACKED)) { + vq->shadow_avail_wrap_counter = (shadow_avail_idx >> 15) & 0x1; + vq->shadow_avail_idx = shadow_avail_idx & 0x7FFF; + } else { + vq->shadow_avail_idx = shadow_avail_idx; + } +} + static void virtio_queue_notify_vq(VirtQueue *vq) { if (vq->vring.desc && vq->handle_output) { @@ -2962,6 +2984,20 @@ int virtio_set_features(VirtIODevice *vdev, uint64_t val) return ret; } +static void virtio_device_check_notification_compatibility(VirtIODevice *vdev, + Error **errp) +{ + VirtioBusState *bus = VIRTIO_BUS(qdev_get_parent_bus(DEVICE(vdev))); + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(bus); + DeviceState *proxy = DEVICE(BUS(bus)->parent); + + if (virtio_host_has_feature(vdev, VIRTIO_F_NOTIFICATION_DATA) && + k->ioeventfd_enabled(proxy)) { + error_setg(errp, + "notification_data=on without ioeventfd=off is not supported"); + } +} + size_t virtio_get_config_size(const VirtIOConfigSizeParams *params, uint64_t host_features) { @@ -3722,6 +3758,14 @@ static void virtio_device_realize(DeviceState *dev, Error **errp) } } + /* Devices should not use both ioeventfd and notification data feature */ + virtio_device_check_notification_compatibility(vdev, &err); + if (err != NULL) { + error_propagate(errp, err); + vdc->unrealize(dev); + return; + } + virtio_bus_device_plugged(vdev, &err); if (err != NULL) { error_propagate(errp, err); diff --git a/hw/xen/xen_pt_load_rom.c b/hw/xen/xen_pt_load_rom.c index 03422a8a71..6bc64acd33 100644 --- a/hw/xen/xen_pt_load_rom.c +++ b/hw/xen/xen_pt_load_rom.c @@ -53,7 +53,7 @@ void *pci_assign_dev_load_option_rom(PCIDevice *dev, } fseek(fp, 0, SEEK_SET); - if (dev->romsize != -1) { + if (dev->romsize != UINT_MAX) { if (st.st_size > dev->romsize) { error_report("ROM BAR \"%s\" (%ld bytes) is too large for ROM size %u", rom_file, (long) st.st_size, dev->romsize); diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h index 279b276bda..0a4fcb2800 100644 --- a/include/hw/cxl/cxl_device.h +++ b/include/hw/cxl/cxl_device.h @@ -164,7 +164,7 @@ typedef struct CXLEventLog { } CXLEventLog; typedef struct CXLCCI { - const struct cxl_cmd (*cxl_cmd_set)[256]; + struct cxl_cmd cxl_cmd_set[256][256]; struct cel_log { uint16_t opcode; uint16_t effect; @@ -234,7 +234,7 @@ typedef struct cxl_device_state { } timestamp; /* memory region size, HDM */ - uint64_t mem_size; + uint64_t static_mem_size; uint64_t pmem_size; uint64_t vmem_size; @@ -301,6 +301,8 @@ void cxl_initialize_mailbox_t3(CXLCCI *cci, DeviceState *d, size_t payload_max); void cxl_initialize_mailbox_swcci(CXLCCI *cci, DeviceState *intf, DeviceState *d, size_t payload_max); void cxl_init_cci(CXLCCI *cci, size_t payload_max); +void cxl_add_cci_commands(CXLCCI *cci, const struct cxl_cmd (*cxl_cmd_set)[256], + size_t payload_max); int cxl_process_cci_message(CXLCCI *cci, uint8_t set, uint8_t cmd, size_t len_in, uint8_t *pl_in, size_t *len_out, uint8_t *pl_out, @@ -420,6 +422,43 @@ typedef struct CXLPoison { typedef QLIST_HEAD(, CXLPoison) CXLPoisonList; #define CXL_POISON_LIST_LIMIT 256 +#define DCD_MAX_NUM_REGION 8 + +typedef struct CXLDCExtentRaw { + uint64_t start_dpa; + uint64_t len; + uint8_t tag[0x10]; + uint16_t shared_seq; + uint8_t rsvd[0x6]; +} QEMU_PACKED CXLDCExtentRaw; + +typedef struct CXLDCExtent { + uint64_t start_dpa; + uint64_t len; + uint8_t tag[0x10]; + uint16_t shared_seq; + uint8_t rsvd[0x6]; + + QTAILQ_ENTRY(CXLDCExtent) node; +} CXLDCExtent; +typedef QTAILQ_HEAD(, CXLDCExtent) CXLDCExtentList; + +typedef struct CXLDCExtentGroup { + CXLDCExtentList list; + QTAILQ_ENTRY(CXLDCExtentGroup) node; +} CXLDCExtentGroup; +typedef QTAILQ_HEAD(, CXLDCExtentGroup) CXLDCExtentGroupList; + +typedef struct CXLDCRegion { + uint64_t base; /* aligned to 256*MiB */ + uint64_t decode_len; /* aligned to 256*MiB */ + uint64_t len; + uint64_t block_size; + uint32_t dsmadhandle; + uint8_t flags; + unsigned long *blk_bitmap; +} CXLDCRegion; + struct CXLType3Dev { /* Private */ PCIDevice parent_obj; @@ -452,6 +491,23 @@ struct CXLType3Dev { unsigned int poison_list_cnt; bool poison_list_overflowed; uint64_t poison_list_overflow_ts; + + struct dynamic_capacity { + HostMemoryBackend *host_dc; + AddressSpace host_dc_as; + /* + * total_capacity is equivalent to the dynamic capability + * memory region size. + */ + uint64_t total_capacity; /* 256M aligned */ + CXLDCExtentList extents; + CXLDCExtentGroupList extents_pending; + uint32_t total_extent_count; + uint32_t ext_list_gen_seq; + + uint8_t num_regions; /* 0-8 regions */ + CXLDCRegion regions[DCD_MAX_NUM_REGION]; + } dc; }; #define TYPE_CXL_TYPE3 "cxl-type3" @@ -503,4 +559,29 @@ void cxl_event_irq_assert(CXLType3Dev *ct3d); void cxl_set_poison_list_overflowed(CXLType3Dev *ct3d); +CXLDCRegion *cxl_find_dc_region(CXLType3Dev *ct3d, uint64_t dpa, uint64_t len); + +void cxl_remove_extent_from_extent_list(CXLDCExtentList *list, + CXLDCExtent *extent); +void cxl_insert_extent_to_extent_list(CXLDCExtentList *list, uint64_t dpa, + uint64_t len, uint8_t *tag, + uint16_t shared_seq); +bool test_any_bits_set(const unsigned long *addr, unsigned long nr, + unsigned long size); +bool cxl_extents_contains_dpa_range(CXLDCExtentList *list, + uint64_t dpa, uint64_t len); +CXLDCExtentGroup *cxl_insert_extent_to_extent_group(CXLDCExtentGroup *group, + uint64_t dpa, + uint64_t len, + uint8_t *tag, + uint16_t shared_seq); +void cxl_extent_group_list_insert_tail(CXLDCExtentGroupList *list, + CXLDCExtentGroup *group); +void cxl_extent_group_list_delete_front(CXLDCExtentGroupList *list); +void ct3_set_region_block_backed(CXLType3Dev *ct3d, uint64_t dpa, + uint64_t len); +void ct3_clear_region_block_backed(CXLType3Dev *ct3d, uint64_t dpa, + uint64_t len); +bool ct3_test_region_block_backed(CXLType3Dev *ct3d, uint64_t dpa, + uint64_t len); #endif diff --git a/include/hw/cxl/cxl_events.h b/include/hw/cxl/cxl_events.h index 5170b8dbf8..38cadaa0f3 100644 --- a/include/hw/cxl/cxl_events.h +++ b/include/hw/cxl/cxl_events.h @@ -166,4 +166,22 @@ typedef struct CXLEventMemoryModule { uint8_t reserved[0x3d]; } QEMU_PACKED CXLEventMemoryModule; +/* + * CXL r3.1 section Table 8-50: Dynamic Capacity Event Record + * All fields little endian. + */ +typedef struct CXLEventDynamicCapacity { + CXLEventRecordHdr hdr; + uint8_t type; + uint8_t validity_flags; + uint16_t host_id; + uint8_t updated_region_id; + uint8_t flags; + uint8_t reserved2[2]; + uint8_t dynamic_capacity_extent[0x28]; /* defined in cxl_device.h */ + uint8_t reserved[0x18]; + uint32_t extents_avail; + uint32_t tags_avail; +} QEMU_PACKED CXLEventDynamicCapacity; + #endif /* CXL_EVENTS_H */ diff --git a/include/hw/misc/pvpanic.h b/include/hw/misc/pvpanic.h index fab94165d0..9a71a5ad0d 100644 --- a/include/hw/misc/pvpanic.h +++ b/include/hw/misc/pvpanic.h @@ -18,6 +18,12 @@ #include "exec/memory.h" #include "qom/object.h" +#include "standard-headers/misc/pvpanic.h" + +#define PVPANIC_EVENTS (PVPANIC_PANICKED | \ + PVPANIC_CRASH_LOADED | \ + PVPANIC_SHUTDOWN) + #define TYPE_PVPANIC_ISA_DEVICE "pvpanic" #define TYPE_PVPANIC_PCI_DEVICE "pvpanic-pci" diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index eb26cac810..14a869eeaa 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -678,6 +678,6 @@ static inline void pci_irq_pulse(PCIDevice *pci_dev) } MSIMessage pci_get_msi_message(PCIDevice *dev, int vector); -void pci_set_power(PCIDevice *pci_dev, bool state); +void pci_set_enabled(PCIDevice *pci_dev, bool state); #endif diff --git a/include/hw/pci/pci_device.h b/include/hw/pci/pci_device.h index d3dd0f64b2..ca15132508 100644 --- a/include/hw/pci/pci_device.h +++ b/include/hw/pci/pci_device.h @@ -56,7 +56,7 @@ typedef struct PCIReqIDCache PCIReqIDCache; struct PCIDevice { DeviceState qdev; bool partially_hotplugged; - bool has_power; + bool enabled; /* PCI config space */ uint8_t *config; @@ -205,6 +205,21 @@ static inline uint16_t pci_get_bdf(PCIDevice *dev) return PCI_BUILD_BDF(pci_bus_num(pci_get_bus(dev)), dev->devfn); } +static inline void pci_set_power(PCIDevice *pci_dev, bool state) +{ + /* + * Don't change the enabled state of VFs when powering on/off the device. + * + * When powering on, VFs must not be enabled immediately but they must + * wait until the guest configures SR-IOV. + * When powering off, their corresponding PFs will be reset and disable + * VFs. + */ + if (!pci_is_vf(pci_dev)) { + pci_set_enabled(pci_dev, state); + } +} + uint16_t pci_requester_id(PCIDevice *dev); /* DMA access functions */ diff --git a/include/hw/pci/pcie_sriov.h b/include/hw/pci/pcie_sriov.h index 450cbef6c2..c5d2d318d3 100644 --- a/include/hw/pci/pcie_sriov.h +++ b/include/hw/pci/pcie_sriov.h @@ -16,9 +16,7 @@ #include "hw/pci/pci.h" typedef 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 */ } PCIESriovPF; @@ -27,10 +25,11 @@ typedef struct PCIESriovVF { uint16_t vf_number; /* Logical VF number of this function */ } PCIESriovVF; -void pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset, +bool 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); + uint16_t vf_offset, uint16_t vf_stride, + Error **errp); void pcie_sriov_pf_exit(PCIDevice *dev); /* Set up a VF bar in the SR/IOV bar area */ @@ -58,6 +57,8 @@ void pcie_sriov_pf_add_sup_pgsize(PCIDevice *dev, uint16_t opt_sup_pgsize); void pcie_sriov_config_write(PCIDevice *dev, uint32_t address, uint32_t val, int len); +void pcie_sriov_pf_post_load(PCIDevice *dev); + /* Reset SR/IOV */ void pcie_sriov_pf_reset(PCIDevice *dev); diff --git a/include/hw/virtio/vhost-user.h b/include/hw/virtio/vhost-user.h index d7c09ffd34..324cd8663a 100644 --- a/include/hw/virtio/vhost-user.h +++ b/include/hw/virtio/vhost-user.h @@ -108,7 +108,6 @@ typedef void (*vu_async_close_fn)(DeviceState *cb); void vhost_user_async_close(DeviceState *d, CharBackend *chardev, struct vhost_dev *vhost, - vu_async_close_fn cb, - IOEventHandler *event_cb); + vu_async_close_fn cb); #endif diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index 02477788df..d75faf46e9 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -129,6 +129,7 @@ struct vhost_dev { void *opaque; struct vhost_log *log; QLIST_ENTRY(vhost_dev) entry; + QLIST_ENTRY(vhost_dev) logdev_entry; QLIST_HEAD(, vhost_iommu) iommu_list; IOMMUNotifier n; const VhostDevConfigOps *config_ops; diff --git a/include/hw/virtio/virtio-pci.h b/include/hw/virtio/virtio-pci.h index 59d88018c1..9e67ba38c7 100644 --- a/include/hw/virtio/virtio-pci.h +++ b/include/hw/virtio/virtio-pci.h @@ -43,6 +43,7 @@ enum { VIRTIO_PCI_FLAG_INIT_FLR_BIT, VIRTIO_PCI_FLAG_AER_BIT, VIRTIO_PCI_FLAG_ATS_PAGE_ALIGNED_BIT, + VIRTIO_PCI_FLAG_PM_NO_SOFT_RESET_BIT, }; /* Need to activate work-arounds for buggy guests at vmstate load. */ @@ -79,6 +80,10 @@ enum { /* Init Power Management */ #define VIRTIO_PCI_FLAG_INIT_PM (1 << VIRTIO_PCI_FLAG_INIT_PM_BIT) +/* Init The No_Soft_Reset bit of Power Management */ +#define VIRTIO_PCI_FLAG_PM_NO_SOFT_RESET \ + (1 << VIRTIO_PCI_FLAG_PM_NO_SOFT_RESET_BIT) + /* Init Function Level Reset capability */ #define VIRTIO_PCI_FLAG_INIT_FLR (1 << VIRTIO_PCI_FLAG_INIT_FLR_BIT) diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 7d5ffdc145..7512afbc84 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -307,6 +307,8 @@ int virtio_queue_ready(VirtQueue *vq); int virtio_queue_empty(VirtQueue *vq); +void virtio_queue_set_shadow_avail_idx(VirtQueue *vq, uint16_t idx); + /* Host binding interface. */ uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr); @@ -470,9 +472,9 @@ static inline bool virtio_device_started(VirtIODevice *vdev, uint8_t status) * @vdev - the VirtIO device * @status - the devices status bits * - * This is similar to virtio_device_started() but also encapsulates a - * check on the VM status which would prevent a device starting - * anyway. + * This is similar to virtio_device_started() but ignores vdev->started + * and also encapsulates a check on the VM status which would prevent a + * device from starting anyway. */ static inline bool virtio_device_should_start(VirtIODevice *vdev, uint8_t status) { @@ -480,7 +482,7 @@ static inline bool virtio_device_should_start(VirtIODevice *vdev, uint8_t status return false; } - return virtio_device_started(vdev, status); + return status & VIRTIO_CONFIG_S_DRIVER_OK; } static inline void virtio_set_started(VirtIODevice *vdev, bool started) diff --git a/include/standard-headers/linux/ethtool.h b/include/standard-headers/linux/ethtool.h index 01503784d2..b0b4b68410 100644 --- a/include/standard-headers/linux/ethtool.h +++ b/include/standard-headers/linux/ethtool.h @@ -753,6 +753,61 @@ enum ethtool_module_power_mode { }; /** + * enum ethtool_pse_types - Types of PSE controller. + * @ETHTOOL_PSE_UNKNOWN: Type of PSE controller is unknown + * @ETHTOOL_PSE_PODL: PSE controller which support PoDL + * @ETHTOOL_PSE_C33: PSE controller which support Clause 33 (PoE) + */ +enum ethtool_pse_types { + ETHTOOL_PSE_UNKNOWN = 1 << 0, + ETHTOOL_PSE_PODL = 1 << 1, + ETHTOOL_PSE_C33 = 1 << 2, +}; + +/** + * enum ethtool_c33_pse_admin_state - operational state of the PoDL PSE + * functions. IEEE 802.3-2022 30.9.1.1.2 aPSEAdminState + * @ETHTOOL_C33_PSE_ADMIN_STATE_UNKNOWN: state of PSE functions is unknown + * @ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED: PSE functions are disabled + * @ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED: PSE functions are enabled + */ +enum ethtool_c33_pse_admin_state { + ETHTOOL_C33_PSE_ADMIN_STATE_UNKNOWN = 1, + ETHTOOL_C33_PSE_ADMIN_STATE_DISABLED, + ETHTOOL_C33_PSE_ADMIN_STATE_ENABLED, +}; + +/** + * enum ethtool_c33_pse_pw_d_status - power detection status of the PSE. + * IEEE 802.3-2022 30.9.1.1.3 aPoDLPSEPowerDetectionStatus: + * @ETHTOOL_C33_PSE_PW_D_STATUS_UNKNOWN: PSE status is unknown + * @ETHTOOL_C33_PSE_PW_D_STATUS_DISABLED: The enumeration "disabled" + * indicates that the PSE State diagram is in the state DISABLED. + * @ETHTOOL_C33_PSE_PW_D_STATUS_SEARCHING: The enumeration "searching" + * indicates the PSE State diagram is in a state other than those + * listed. + * @ETHTOOL_C33_PSE_PW_D_STATUS_DELIVERING: The enumeration + * "deliveringPower" indicates that the PSE State diagram is in the + * state POWER_ON. + * @ETHTOOL_C33_PSE_PW_D_STATUS_TEST: The enumeration "test" indicates that + * the PSE State diagram is in the state TEST_MODE. + * @ETHTOOL_C33_PSE_PW_D_STATUS_FAULT: The enumeration "fault" indicates that + * the PSE State diagram is in the state TEST_ERROR. + * @ETHTOOL_C33_PSE_PW_D_STATUS_OTHERFAULT: The enumeration "otherFault" + * indicates that the PSE State diagram is in the state IDLE due to + * the variable error_condition = true. + */ +enum ethtool_c33_pse_pw_d_status { + ETHTOOL_C33_PSE_PW_D_STATUS_UNKNOWN = 1, + ETHTOOL_C33_PSE_PW_D_STATUS_DISABLED, + ETHTOOL_C33_PSE_PW_D_STATUS_SEARCHING, + ETHTOOL_C33_PSE_PW_D_STATUS_DELIVERING, + ETHTOOL_C33_PSE_PW_D_STATUS_TEST, + ETHTOOL_C33_PSE_PW_D_STATUS_FAULT, + ETHTOOL_C33_PSE_PW_D_STATUS_OTHERFAULT, +}; + +/** * enum ethtool_podl_pse_admin_state - operational state of the PoDL PSE * functions. IEEE 802.3-2018 30.15.1.1.2 aPoDLPSEAdminState * @ETHTOOL_PODL_PSE_ADMIN_STATE_UNKNOWN: state of PoDL PSE functions are diff --git a/include/standard-headers/linux/pci_regs.h b/include/standard-headers/linux/pci_regs.h index a39193213f..94c00996e6 100644 --- a/include/standard-headers/linux/pci_regs.h +++ b/include/standard-headers/linux/pci_regs.h @@ -1144,8 +1144,14 @@ #define PCI_DOE_DATA_OBJECT_HEADER_2_LENGTH 0x0003ffff #define PCI_DOE_DATA_OBJECT_DISC_REQ_3_INDEX 0x000000ff +#define PCI_DOE_DATA_OBJECT_DISC_REQ_3_VER 0x0000ff00 #define PCI_DOE_DATA_OBJECT_DISC_RSP_3_VID 0x0000ffff #define PCI_DOE_DATA_OBJECT_DISC_RSP_3_PROTOCOL 0x00ff0000 #define PCI_DOE_DATA_OBJECT_DISC_RSP_3_NEXT_INDEX 0xff000000 +/* Compute Express Link (CXL r3.1, sec 8.1.5) */ +#define PCI_DVSEC_CXL_PORT 3 +#define PCI_DVSEC_CXL_PORT_CTL 0x0c +#define PCI_DVSEC_CXL_PORT_CTL_UNMASK_SBR 0x00000001 + #endif /* LINUX_PCI_REGS_H */ diff --git a/include/standard-headers/linux/virtio_bt.h b/include/standard-headers/linux/virtio_bt.h index a11ecc3f92..6f0dee7e32 100644 --- a/include/standard-headers/linux/virtio_bt.h +++ b/include/standard-headers/linux/virtio_bt.h @@ -13,7 +13,6 @@ enum virtio_bt_config_type { VIRTIO_BT_CONFIG_TYPE_PRIMARY = 0, - VIRTIO_BT_CONFIG_TYPE_AMP = 1, }; enum virtio_bt_config_vendor { diff --git a/include/standard-headers/linux/virtio_mem.h b/include/standard-headers/linux/virtio_mem.h index 18c74c527c..6bfa41bd8b 100644 --- a/include/standard-headers/linux/virtio_mem.h +++ b/include/standard-headers/linux/virtio_mem.h @@ -90,6 +90,8 @@ #define VIRTIO_MEM_F_ACPI_PXM 0 /* unplugged memory must not be accessed */ #define VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE 1 +/* plugged memory will remain plugged when suspending+resuming */ +#define VIRTIO_MEM_F_PERSISTENT_SUSPEND 2 /* --- virtio-mem: guest -> host requests --- */ diff --git a/include/standard-headers/linux/virtio_net.h b/include/standard-headers/linux/virtio_net.h index 0f88417742..fc594fe5fc 100644 --- a/include/standard-headers/linux/virtio_net.h +++ b/include/standard-headers/linux/virtio_net.h @@ -56,6 +56,7 @@ #define VIRTIO_NET_F_MQ 22 /* Device supports Receive Flow * Steering */ #define VIRTIO_NET_F_CTRL_MAC_ADDR 23 /* Set MAC address */ +#define VIRTIO_NET_F_DEVICE_STATS 50 /* Device can provide device-level statistics. */ #define VIRTIO_NET_F_VQ_NOTF_COAL 52 /* Device supports virtqueue notification coalescing */ #define VIRTIO_NET_F_NOTF_COAL 53 /* Device supports notifications coalescing */ #define VIRTIO_NET_F_GUEST_USO4 54 /* Guest can handle USOv4 in. */ @@ -406,4 +407,146 @@ struct virtio_net_ctrl_coal_vq { struct virtio_net_ctrl_coal coal; }; +/* + * Device Statistics + */ +#define VIRTIO_NET_CTRL_STATS 8 +#define VIRTIO_NET_CTRL_STATS_QUERY 0 +#define VIRTIO_NET_CTRL_STATS_GET 1 + +struct virtio_net_stats_capabilities { + +#define VIRTIO_NET_STATS_TYPE_CVQ (1ULL << 32) + +#define VIRTIO_NET_STATS_TYPE_RX_BASIC (1ULL << 0) +#define VIRTIO_NET_STATS_TYPE_RX_CSUM (1ULL << 1) +#define VIRTIO_NET_STATS_TYPE_RX_GSO (1ULL << 2) +#define VIRTIO_NET_STATS_TYPE_RX_SPEED (1ULL << 3) + +#define VIRTIO_NET_STATS_TYPE_TX_BASIC (1ULL << 16) +#define VIRTIO_NET_STATS_TYPE_TX_CSUM (1ULL << 17) +#define VIRTIO_NET_STATS_TYPE_TX_GSO (1ULL << 18) +#define VIRTIO_NET_STATS_TYPE_TX_SPEED (1ULL << 19) + + uint64_t supported_stats_types[1]; +}; + +struct virtio_net_ctrl_queue_stats { + struct { + uint16_t vq_index; + uint16_t reserved[3]; + uint64_t types_bitmap[1]; + } stats[1]; +}; + +struct virtio_net_stats_reply_hdr { +#define VIRTIO_NET_STATS_TYPE_REPLY_CVQ 32 + +#define VIRTIO_NET_STATS_TYPE_REPLY_RX_BASIC 0 +#define VIRTIO_NET_STATS_TYPE_REPLY_RX_CSUM 1 +#define VIRTIO_NET_STATS_TYPE_REPLY_RX_GSO 2 +#define VIRTIO_NET_STATS_TYPE_REPLY_RX_SPEED 3 + +#define VIRTIO_NET_STATS_TYPE_REPLY_TX_BASIC 16 +#define VIRTIO_NET_STATS_TYPE_REPLY_TX_CSUM 17 +#define VIRTIO_NET_STATS_TYPE_REPLY_TX_GSO 18 +#define VIRTIO_NET_STATS_TYPE_REPLY_TX_SPEED 19 + uint8_t type; + uint8_t reserved; + uint16_t vq_index; + uint16_t reserved1; + uint16_t size; +}; + +struct virtio_net_stats_cvq { + struct virtio_net_stats_reply_hdr hdr; + + uint64_t command_num; + uint64_t ok_num; +}; + +struct virtio_net_stats_rx_basic { + struct virtio_net_stats_reply_hdr hdr; + + uint64_t rx_notifications; + + uint64_t rx_packets; + uint64_t rx_bytes; + + uint64_t rx_interrupts; + + uint64_t rx_drops; + uint64_t rx_drop_overruns; +}; + +struct virtio_net_stats_tx_basic { + struct virtio_net_stats_reply_hdr hdr; + + uint64_t tx_notifications; + + uint64_t tx_packets; + uint64_t tx_bytes; + + uint64_t tx_interrupts; + + uint64_t tx_drops; + uint64_t tx_drop_malformed; +}; + +struct virtio_net_stats_rx_csum { + struct virtio_net_stats_reply_hdr hdr; + + uint64_t rx_csum_valid; + uint64_t rx_needs_csum; + uint64_t rx_csum_none; + uint64_t rx_csum_bad; +}; + +struct virtio_net_stats_tx_csum { + struct virtio_net_stats_reply_hdr hdr; + + uint64_t tx_csum_none; + uint64_t tx_needs_csum; +}; + +struct virtio_net_stats_rx_gso { + struct virtio_net_stats_reply_hdr hdr; + + uint64_t rx_gso_packets; + uint64_t rx_gso_bytes; + uint64_t rx_gso_packets_coalesced; + uint64_t rx_gso_bytes_coalesced; +}; + +struct virtio_net_stats_tx_gso { + struct virtio_net_stats_reply_hdr hdr; + + uint64_t tx_gso_packets; + uint64_t tx_gso_bytes; + uint64_t tx_gso_segments; + uint64_t tx_gso_segments_bytes; + uint64_t tx_gso_packets_noseg; + uint64_t tx_gso_bytes_noseg; +}; + +struct virtio_net_stats_rx_speed { + struct virtio_net_stats_reply_hdr hdr; + + /* rx_{packets,bytes}_allowance_exceeded are too long. So rename to + * short name. + */ + uint64_t rx_ratelimit_packets; + uint64_t rx_ratelimit_bytes; +}; + +struct virtio_net_stats_tx_speed { + struct virtio_net_stats_reply_hdr hdr; + + /* tx_{packets,bytes}_allowance_exceeded are too long. So rename to + * short name. + */ + uint64_t tx_ratelimit_packets; + uint64_t tx_ratelimit_bytes; +}; + #endif /* _LINUX_VIRTIO_NET_H */ diff --git a/include/standard-headers/misc/pvpanic.h b/include/standard-headers/misc/pvpanic.h index 54b7485390..b115094431 100644 --- a/include/standard-headers/misc/pvpanic.h +++ b/include/standard-headers/misc/pvpanic.h @@ -3,7 +3,10 @@ #ifndef __PVPANIC_H__ #define __PVPANIC_H__ -#define PVPANIC_PANICKED (1 << 0) -#define PVPANIC_CRASH_LOADED (1 << 1) +#include "standard-headers/linux/const.h" + +#define PVPANIC_PANICKED _BITUL(0) +#define PVPANIC_CRASH_LOADED _BITUL(1) +#define PVPANIC_SHUTDOWN _BITUL(2) #endif /* __PVPANIC_H__ */ diff --git a/include/sysemu/runstate.h b/include/sysemu/runstate.h index 0117d243c4..e210a37abf 100644 --- a/include/sysemu/runstate.h +++ b/include/sysemu/runstate.h @@ -104,6 +104,7 @@ void qemu_system_killed(int signal, pid_t pid); void qemu_system_reset(ShutdownCause reason); void qemu_system_guest_panicked(GuestPanicInformation *info); void qemu_system_guest_crashloaded(GuestPanicInformation *info); +void qemu_system_guest_pvshutdown(void); bool qemu_system_dump_in_progress(void); #endif diff --git a/linux-headers/asm-generic/unistd.h b/linux-headers/asm-generic/unistd.h index 75f00965ab..d983c48a3b 100644 --- a/linux-headers/asm-generic/unistd.h +++ b/linux-headers/asm-generic/unistd.h @@ -842,8 +842,11 @@ __SYSCALL(__NR_lsm_set_self_attr, sys_lsm_set_self_attr) #define __NR_lsm_list_modules 461 __SYSCALL(__NR_lsm_list_modules, sys_lsm_list_modules) +#define __NR_mseal 462 +__SYSCALL(__NR_mseal, sys_mseal) + #undef __NR_syscalls -#define __NR_syscalls 462 +#define __NR_syscalls 463 /* * 32 bit systems traditionally used different diff --git a/linux-headers/asm-mips/unistd_n32.h b/linux-headers/asm-mips/unistd_n32.h index ce2e050a9b..fc93b3be30 100644 --- a/linux-headers/asm-mips/unistd_n32.h +++ b/linux-headers/asm-mips/unistd_n32.h @@ -390,5 +390,6 @@ #define __NR_lsm_get_self_attr (__NR_Linux + 459) #define __NR_lsm_set_self_attr (__NR_Linux + 460) #define __NR_lsm_list_modules (__NR_Linux + 461) +#define __NR_mseal (__NR_Linux + 462) #endif /* _ASM_UNISTD_N32_H */ diff --git a/linux-headers/asm-mips/unistd_n64.h b/linux-headers/asm-mips/unistd_n64.h index 5bfb3733ff..e72a3eb2c9 100644 --- a/linux-headers/asm-mips/unistd_n64.h +++ b/linux-headers/asm-mips/unistd_n64.h @@ -366,5 +366,6 @@ #define __NR_lsm_get_self_attr (__NR_Linux + 459) #define __NR_lsm_set_self_attr (__NR_Linux + 460) #define __NR_lsm_list_modules (__NR_Linux + 461) +#define __NR_mseal (__NR_Linux + 462) #endif /* _ASM_UNISTD_N64_H */ diff --git a/linux-headers/asm-mips/unistd_o32.h b/linux-headers/asm-mips/unistd_o32.h index 02eaecd020..b86eb0786c 100644 --- a/linux-headers/asm-mips/unistd_o32.h +++ b/linux-headers/asm-mips/unistd_o32.h @@ -436,5 +436,6 @@ #define __NR_lsm_get_self_attr (__NR_Linux + 459) #define __NR_lsm_set_self_attr (__NR_Linux + 460) #define __NR_lsm_list_modules (__NR_Linux + 461) +#define __NR_mseal (__NR_Linux + 462) #endif /* _ASM_UNISTD_O32_H */ diff --git a/linux-headers/asm-powerpc/unistd_32.h b/linux-headers/asm-powerpc/unistd_32.h index bbab08d6ec..28627b6546 100644 --- a/linux-headers/asm-powerpc/unistd_32.h +++ b/linux-headers/asm-powerpc/unistd_32.h @@ -443,6 +443,7 @@ #define __NR_lsm_get_self_attr 459 #define __NR_lsm_set_self_attr 460 #define __NR_lsm_list_modules 461 +#define __NR_mseal 462 #endif /* _ASM_UNISTD_32_H */ diff --git a/linux-headers/asm-powerpc/unistd_64.h b/linux-headers/asm-powerpc/unistd_64.h index af34cde70f..1fc42a8300 100644 --- a/linux-headers/asm-powerpc/unistd_64.h +++ b/linux-headers/asm-powerpc/unistd_64.h @@ -415,6 +415,7 @@ #define __NR_lsm_get_self_attr 459 #define __NR_lsm_set_self_attr 460 #define __NR_lsm_list_modules 461 +#define __NR_mseal 462 #endif /* _ASM_UNISTD_64_H */ diff --git a/linux-headers/asm-s390/unistd_32.h b/linux-headers/asm-s390/unistd_32.h index a3ece69d82..7706c21b87 100644 --- a/linux-headers/asm-s390/unistd_32.h +++ b/linux-headers/asm-s390/unistd_32.h @@ -434,5 +434,6 @@ #define __NR_lsm_get_self_attr 459 #define __NR_lsm_set_self_attr 460 #define __NR_lsm_list_modules 461 +#define __NR_mseal 462 #endif /* _ASM_S390_UNISTD_32_H */ diff --git a/linux-headers/asm-s390/unistd_64.h b/linux-headers/asm-s390/unistd_64.h index 8c5fd93495..62082d592d 100644 --- a/linux-headers/asm-s390/unistd_64.h +++ b/linux-headers/asm-s390/unistd_64.h @@ -382,5 +382,6 @@ #define __NR_lsm_get_self_attr 459 #define __NR_lsm_set_self_attr 460 #define __NR_lsm_list_modules 461 +#define __NR_mseal 462 #endif /* _ASM_S390_UNISTD_64_H */ diff --git a/linux-headers/asm-x86/unistd_32.h b/linux-headers/asm-x86/unistd_32.h index 5c9c329e93..fb7b8b169b 100644 --- a/linux-headers/asm-x86/unistd_32.h +++ b/linux-headers/asm-x86/unistd_32.h @@ -452,6 +452,7 @@ #define __NR_lsm_get_self_attr 459 #define __NR_lsm_set_self_attr 460 #define __NR_lsm_list_modules 461 +#define __NR_mseal 462 #endif /* _ASM_UNISTD_32_H */ diff --git a/linux-headers/asm-x86/unistd_64.h b/linux-headers/asm-x86/unistd_64.h index d9aab7ae87..da439afee1 100644 --- a/linux-headers/asm-x86/unistd_64.h +++ b/linux-headers/asm-x86/unistd_64.h @@ -374,6 +374,7 @@ #define __NR_lsm_get_self_attr 459 #define __NR_lsm_set_self_attr 460 #define __NR_lsm_list_modules 461 +#define __NR_mseal 462 #endif /* _ASM_UNISTD_64_H */ diff --git a/linux-headers/asm-x86/unistd_x32.h b/linux-headers/asm-x86/unistd_x32.h index 63cdd1ee43..4fcb607c72 100644 --- a/linux-headers/asm-x86/unistd_x32.h +++ b/linux-headers/asm-x86/unistd_x32.h @@ -318,6 +318,7 @@ #define __NR_set_mempolicy_home_node (__X32_SYSCALL_BIT + 450) #define __NR_cachestat (__X32_SYSCALL_BIT + 451) #define __NR_fchmodat2 (__X32_SYSCALL_BIT + 452) +#define __NR_map_shadow_stack (__X32_SYSCALL_BIT + 453) #define __NR_futex_wake (__X32_SYSCALL_BIT + 454) #define __NR_futex_wait (__X32_SYSCALL_BIT + 455) #define __NR_futex_requeue (__X32_SYSCALL_BIT + 456) @@ -326,6 +327,7 @@ #define __NR_lsm_get_self_attr (__X32_SYSCALL_BIT + 459) #define __NR_lsm_set_self_attr (__X32_SYSCALL_BIT + 460) #define __NR_lsm_list_modules (__X32_SYSCALL_BIT + 461) +#define __NR_mseal (__X32_SYSCALL_BIT + 462) #define __NR_rt_sigaction (__X32_SYSCALL_BIT + 512) #define __NR_rt_sigreturn (__X32_SYSCALL_BIT + 513) #define __NR_ioctl (__X32_SYSCALL_BIT + 514) diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index 038731cdef..c93876ca0b 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -1217,9 +1217,9 @@ struct kvm_vfio_spapr_tce { /* Available with KVM_CAP_SPAPR_RESIZE_HPT */ #define KVM_PPC_RESIZE_HPT_PREPARE _IOR(KVMIO, 0xad, struct kvm_ppc_resize_hpt) #define KVM_PPC_RESIZE_HPT_COMMIT _IOR(KVMIO, 0xae, struct kvm_ppc_resize_hpt) -/* Available with KVM_CAP_PPC_RADIX_MMU or KVM_CAP_PPC_HASH_MMU_V3 */ +/* Available with KVM_CAP_PPC_MMU_RADIX or KVM_CAP_PPC_MMU_HASH_V3 */ #define KVM_PPC_CONFIGURE_V3_MMU _IOW(KVMIO, 0xaf, struct kvm_ppc_mmuv3_cfg) -/* Available with KVM_CAP_PPC_RADIX_MMU */ +/* Available with KVM_CAP_PPC_MMU_RADIX */ #define KVM_PPC_GET_RMMU_INFO _IOW(KVMIO, 0xb0, struct kvm_ppc_rmmu_info) /* Available with KVM_CAP_PPC_GET_CPU_CHAR */ #define KVM_PPC_GET_CPU_CHAR _IOR(KVMIO, 0xb1, struct kvm_ppc_cpu_char) diff --git a/linux-headers/linux/stddef.h b/linux-headers/linux/stddef.h index bf9749dd14..96aa341942 100644 --- a/linux-headers/linux/stddef.h +++ b/linux-headers/linux/stddef.h @@ -55,4 +55,12 @@ #define __counted_by(m) #endif +#ifndef __counted_by_le +#define __counted_by_le(m) +#endif + +#ifndef __counted_by_be +#define __counted_by_be(m) +#endif + #endif /* _LINUX_STDDEF_H */ diff --git a/meson.build b/meson.build index 3a1ad4ddeb..6a93da48e1 100644 --- a/meson.build +++ b/meson.build @@ -93,7 +93,7 @@ else iasl = find_program(get_option('iasl'), required: true) endif -edk2_targets = [ 'arm-softmmu', 'aarch64-softmmu', 'i386-softmmu', 'x86_64-softmmu' ] +edk2_targets = [ 'arm-softmmu', 'aarch64-softmmu', 'i386-softmmu', 'x86_64-softmmu', 'riscv64-softmmu' ] unpack_edk2_blobs = false foreach target : edk2_targets if target in target_dirs @@ -2862,6 +2862,12 @@ have_cpuid_h = cc.links(''' }''') config_host_data.set('CONFIG_CPUID_H', have_cpuid_h) +# Don't bother to advertise asm/hwprobe.h for old versions that do +# not contain RISCV_HWPROBE_EXT_ZBA. +config_host_data.set('CONFIG_ASM_HWPROBE_H', + cc.has_header_symbol('asm/hwprobe.h', + 'RISCV_HWPROBE_EXT_ZBA')) + config_host_data.set('CONFIG_AVX2_OPT', get_option('avx2') \ .require(have_cpuid_h, error_message: 'cpuid.h not available, cannot enable AVX2') \ .require(cc.links(''' diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index 85e73dd6a7..daa38428c5 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -62,6 +62,7 @@ const int vdpa_feature_bits[] = { VIRTIO_F_RING_PACKED, VIRTIO_F_RING_RESET, VIRTIO_F_VERSION_1, + VIRTIO_F_NOTIFICATION_DATA, VIRTIO_NET_F_CSUM, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, VIRTIO_NET_F_CTRL_MAC_ADDR, @@ -399,7 +400,10 @@ static int vhost_vdpa_net_data_load(NetClientState *nc) } for (int i = 0; i < v->dev->nvqs; ++i) { - vhost_vdpa_set_vring_ready(v, i + v->dev->vq_index); + int ret = vhost_vdpa_set_vring_ready(v, i + v->dev->vq_index); + if (ret < 0) { + return ret; + } } return 0; } @@ -1238,7 +1242,10 @@ static int vhost_vdpa_net_cvq_load(NetClientState *nc) assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA); - vhost_vdpa_set_vring_ready(v, v->dev->vq_index); + r = vhost_vdpa_set_vring_ready(v, v->dev->vq_index); + if (unlikely(r < 0)) { + return r; + } if (v->shadow_vqs_enabled) { n = VIRTIO_NET(v->dev->vdev); @@ -1277,7 +1284,10 @@ static int vhost_vdpa_net_cvq_load(NetClientState *nc) } for (int i = 0; i < v->dev->vq_index; ++i) { - vhost_vdpa_set_vring_ready(v, i); + r = vhost_vdpa_set_vring_ready(v, i); + if (unlikely(r < 0)) { + return r; + } } return 0; diff --git a/pc-bios/meson.build b/pc-bios/meson.build index 0760612bea..8602b45b9b 100644 --- a/pc-bios/meson.build +++ b/pc-bios/meson.build @@ -4,6 +4,8 @@ if unpack_edk2_blobs 'edk2-aarch64-code.fd', 'edk2-arm-code.fd', 'edk2-arm-vars.fd', + 'edk2-riscv-code.fd', + 'edk2-riscv-vars.fd', 'edk2-i386-code.fd', 'edk2-i386-secure-code.fd', 'edk2-i386-vars.fd', diff --git a/qapi/cxl.json b/qapi/cxl.json index 4281726dec..bdfac67c47 100644 --- a/qapi/cxl.json +++ b/qapi/cxl.json @@ -361,3 +361,192 @@ ## {'command': 'cxl-inject-correctable-error', 'data': {'path': 'str', 'type': 'CxlCorErrorType'}} + +## +# @CxlDynamicCapacityExtent: +# +# A single dynamic capacity extent. This is a contiguous allocation +# of memory by Device Physical Address within a single Dynamic +# Capacity Region on a CXL Type 3 Device. +# +# @offset: The offset (in bytes) to the start of the region +# where the extent belongs to. +# +# @len: The length of the extent in bytes. +# +# Since: 9.1 +## +{ 'struct': 'CxlDynamicCapacityExtent', + 'data': { + 'offset':'uint64', + 'len': 'uint64' + } +} + +## +# @CxlExtentSelectionPolicy: +# +# The policy to use for selecting which extents comprise the added +# capacity, as defined in Compute Express Link (CXL) Specification, +# Revision 3.1, Table 7-70. +# +# @free: Device is responsible for allocating the requested memory +# capacity and is free to do this using any combination of +# supported extents. +# +# @contiguous: Device is responsible for allocating the requested +# memory capacity but must do so as a single contiguous +# extent. +# +# @prescriptive: The precise set of extents to be allocated is +# specified by the command. Thus allocation is being managed +# by the issuer of the allocation command, not the device. +# +# @enable-shared-access: Capacity has already been allocated to a +# different host using free, contiguous or prescriptive policy +# with a known tag. This policy then instructs the device to +# make the capacity with the specified tag available to an +# additional host. Capacity is implicit as it matches that +# already associated with the tag. Note that the extent list +# (and hence Device Physical Addresses) used are per host, so +# a device may use different representations on each host. +# The ordering of the extents provided to each host is indicated +# to the host using per extent sequence numbers generated by +# the device. Has a similar meaning for temporal sharing, but +# in that case there may be only one host involved. +# +# Since: 9.1 +## +{ 'enum': 'CxlExtentSelectionPolicy', + 'data': ['free', + 'contiguous', + 'prescriptive', + 'enable-shared-access'] +} + +## +# @cxl-add-dynamic-capacity: +# +# Initiate adding dynamic capacity extents to a host. This simulates +# operations defined in Compute Express Link (CXL) Specification, +# Revision 3.1, Section 7.6.7.6.5. Note that, currently, establishing +# success or failure of the full Add Dynamic Capacity flow requires +# out of band communication with the OS of the CXL host. +# +# @path: path to the CXL Dynamic Capacity Device in the QOM tree. +# +# @host-id: The "Host ID" field as defined in Compute Express Link +# (CXL) Specification, Revision 3.1, Table 7-70. +# +# @selection-policy: The "Selection Policy" bits as defined in +# Compute Express Link (CXL) Specification, Revision 3.1, +# Table 7-70. It specifies the policy to use for selecting +# which extents comprise the added capacity. +# +# @region: The "Region Number" field as defined in Compute Express +# Link (CXL) Specification, Revision 3.1, Table 7-70. Valid +# range is from 0-7. +# +# @tag: The "Tag" field as defined in Compute Express Link (CXL) +# Specification, Revision 3.1, Table 7-70. +# +# @extents: The "Extent List" field as defined in Compute Express Link +# (CXL) Specification, Revision 3.1, Table 7-70. +# +# Features: +# +# @unstable: For now this command is subject to change. +# +# Since : 9.1 +## +{ 'command': 'cxl-add-dynamic-capacity', + 'data': { 'path': 'str', + 'host-id': 'uint16', + 'selection-policy': 'CxlExtentSelectionPolicy', + 'region': 'uint8', + '*tag': 'str', + 'extents': [ 'CxlDynamicCapacityExtent' ] + }, + 'features': [ 'unstable' ] +} + +## +# @CxlExtentRemovalPolicy: +# +# The policy to use for selecting which extents comprise the released +# capacity, defined in the "Flags" field in Compute Express Link (CXL) +# Specification, Revision 3.1, Table 7-71. +# +# @tag-based: Extents are selected by the device based on tag, with +# no requirement for contiguous extents. +# +# @prescriptive: Extent list of capacity to release is included in +# the request payload. +# +# Since: 9.1 +## +{ 'enum': 'CxlExtentRemovalPolicy', + 'data': ['tag-based', + 'prescriptive'] +} + +## +# @cxl-release-dynamic-capacity: +# +# Initiate release of dynamic capacity extents from a host. This +# simulates operations defined in Compute Express Link (CXL) +# Specification, Revision 3.1, Section 7.6.7.6.6. Note that, +# currently, success or failure of the full Release Dynamic Capacity +# flow requires out of band communication with the OS of the CXL host. +# +# @path: path to the CXL Dynamic Capacity Device in the QOM tree. +# +# @host-id: The "Host ID" field as defined in Compute Express Link +# (CXL) Specification, Revision 3.1, Table 7-71. +# +# @removal-policy: Bit[3:0] of the "Flags" field as defined in +# Compute Express Link (CXL) Specification, Revision 3.1, +# Table 7-71. +# +# @forced-removal: Bit[4] of the "Flags" field in Compute Express +# Link (CXL) Specification, Revision 3.1, Table 7-71. When set, +# the device does not wait for a Release Dynamic Capacity command +# from the host. Instead, the host immediately looses access to +# the released capacity. +# +# @sanitize-on-release: Bit[5] of the "Flags" field in Compute +# Express Link (CXL) Specification, Revision 3.1, Table 7-71. +# When set, the device should sanitize all released capacity as +# a result of this request. This ensures that all user data +# and metadata is made permanently unavailable by whatever +# means is appropriate for the media type. Note that changing +# encryption keys is not sufficient. +# +# @region: The "Region Number" field as defined in Compute Express +# Link Specification, Revision 3.1, Table 7-71. Valid range +# is from 0-7. +# +# @tag: The "Tag" field as defined in Compute Express Link (CXL) +# Specification, Revision 3.1, Table 7-71. +# +# @extents: The "Extent List" field as defined in Compute Express +# Link (CXL) Specification, Revision 3.1, Table 7-71. +# +# Features: +# +# @unstable: For now this command is subject to change. +# +# Since : 9.1 +## +{ 'command': 'cxl-release-dynamic-capacity', + 'data': { 'path': 'str', + 'host-id': 'uint16', + 'removal-policy': 'CxlExtentRemovalPolicy', + '*forced-removal': 'bool', + '*sanitize-on-release': 'bool', + 'region': 'uint8', + '*tag': 'str', + 'extents': [ 'CxlDynamicCapacityExtent' ] + }, + 'features': [ 'unstable' ] +} diff --git a/qapi/qom.json b/qapi/qom.json index 8bd299265e..92b0fea76c 100644 --- a/qapi/qom.json +++ b/qapi/qom.json @@ -600,7 +600,9 @@ # preallocation threads (default: none) (since 7.2) # # @share: if false, the memory is private to QEMU; if true, it is -# shared (default: false) +# shared (default false for backends memory-backend-file and +# memory-backend-ram, true for backends memory-backend-epc, +# memory-backend-memfd, and memory-backend-shm) # # @reserve: if true, reserve swap space (or huge pages) if applicable # (default: true) (since 6.1) @@ -700,8 +702,6 @@ # # Properties for memory-backend-memfd objects. # -# The @share boolean option is true by default with memfd. -# # @hugetlb: if true, the file to be created resides in the hugetlbfs # filesystem (default: false) # @@ -722,12 +722,25 @@ '*seal': 'bool' } } ## +# @MemoryBackendShmProperties: +# +# Properties for memory-backend-shm objects. +# +# This memory backend supports only shared memory, which is the +# default. +# +# Since: 9.1 +## +{ 'struct': 'MemoryBackendShmProperties', + 'base': 'MemoryBackendProperties', + 'data': { }, + 'if': 'CONFIG_POSIX' } + +## # @MemoryBackendEpcProperties: # # Properties for memory-backend-epc objects. # -# The @share boolean option is true by default with epc -# # The @merge boolean option is false by default with epc # # The @dump boolean option is false by default with epc @@ -1051,6 +1064,8 @@ { 'name': 'memory-backend-memfd', 'if': 'CONFIG_LINUX' }, 'memory-backend-ram', + { 'name': 'memory-backend-shm', + 'if': 'CONFIG_POSIX' }, 'pef-guest', { 'name': 'pr-manager-helper', 'if': 'CONFIG_LINUX' }, @@ -1123,6 +1138,8 @@ 'memory-backend-memfd': { 'type': 'MemoryBackendMemfdProperties', 'if': 'CONFIG_LINUX' }, 'memory-backend-ram': 'MemoryBackendProperties', + 'memory-backend-shm': { 'type': 'MemoryBackendShmProperties', + 'if': 'CONFIG_POSIX' }, 'pr-manager-helper': { 'type': 'PrManagerHelperProperties', 'if': 'CONFIG_LINUX' }, 'qtest': 'QtestProperties', diff --git a/qapi/run-state.json b/qapi/run-state.json index f8773f23b2..5ac0fec852 100644 --- a/qapi/run-state.json +++ b/qapi/run-state.json @@ -463,6 +463,20 @@ 'data': { 'action': 'GuestPanicAction', '*info': 'GuestPanicInformation' } } ## +# @GUEST_PVSHUTDOWN: +# +# Emitted when guest submits a shutdown request via pvpanic interface +# +# Since: 9.1 +# +# Example: +# +# <- { "event": "GUEST_PVSHUTDOWN", +# "timestamp": { "seconds": 1648245259, "microseconds": 893771 } } +## +{ 'event': 'GUEST_PVSHUTDOWN' } + +## # @GuestPanicAction: # # An enumeration of the actions taken when guest OS panic is detected diff --git a/qemu-options.hx b/qemu-options.hx index 8ca7f34ef0..ad6521ef5e 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -5240,6 +5240,22 @@ SRST The ``share`` boolean option is on by default with memfd. + ``-object memory-backend-shm,id=id,merge=on|off,dump=on|off,share=on|off,prealloc=on|off,size=size,host-nodes=host-nodes,policy=default|preferred|bind|interleave`` + Creates a POSIX shared memory backend object, which allows + QEMU to share the memory with an external process (e.g. when + using vhost-user). + + ``memory-backend-shm`` is a more portable and less featureful version + of ``memory-backend-memfd``. It can then be used in any POSIX system, + especially when memfd is not supported. + + Please refer to ``memory-backend-file`` for a description of the + options. + + The ``share`` boolean option is on by default with shm. Setting it to + off will cause a failure during allocation because it is not supported + by this backend. + ``-object iommufd,id=id[,fd=fd]`` Creates an iommufd backend which allows control of DMA mapping through the ``/dev/iommu`` device. diff --git a/subprojects/libvhost-user/libvhost-user.c b/subprojects/libvhost-user/libvhost-user.c index a879149fef..9c630c2170 100644 --- a/subprojects/libvhost-user/libvhost-user.c +++ b/subprojects/libvhost-user/libvhost-user.c @@ -568,7 +568,7 @@ vu_message_read_default(VuDev *dev, int conn_fd, VhostUserMsg *vmsg) if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { fd_size = cmsg->cmsg_len - CMSG_LEN(0); vmsg->fd_num = fd_size / sizeof(int); - assert(fd_size < VHOST_MEMORY_BASELINE_NREGIONS); + assert(vmsg->fd_num <= VHOST_MEMORY_BASELINE_NREGIONS); memcpy(vmsg->fds, CMSG_DATA(cmsg), fd_size); break; } @@ -632,12 +632,18 @@ vu_message_write(VuDev *dev, int conn_fd, VhostUserMsg *vmsg) memcpy(CMSG_DATA(cmsg), vmsg->fds, fdsize); } else { msg.msg_controllen = 0; + msg.msg_control = NULL; } do { rc = sendmsg(conn_fd, &msg, 0); } while (rc < 0 && (errno == EINTR || errno == EAGAIN)); + if (rc <= 0) { + vu_panic(dev, "Error while writing: %s", strerror(errno)); + return false; + } + if (vmsg->size) { do { if (vmsg->data) { @@ -1668,6 +1674,17 @@ vu_get_protocol_features_exec(VuDev *dev, VhostUserMsg *vmsg) features |= dev->iface->get_protocol_features(dev); } +#ifndef MFD_ALLOW_SEALING + /* + * If MFD_ALLOW_SEALING is not defined, we are not able to handle + * VHOST_USER_GET_INFLIGHT_FD messages, since we can't create a memfd. + * Those messages are used only if VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD + * is negotiated. A device implementation can enable it, so let's mask + * it to avoid a runtime panic. + */ + features &= ~(1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD); +#endif + vmsg_set_reply_u64(vmsg, features); return true; } diff --git a/system/runstate.c b/system/runstate.c index ec32e270cb..c833316f6d 100644 --- a/system/runstate.c +++ b/system/runstate.c @@ -584,6 +584,12 @@ void qemu_system_guest_crashloaded(GuestPanicInformation *info) qapi_free_GuestPanicInformation(info); } +void qemu_system_guest_pvshutdown(void) +{ + qapi_event_send_guest_pvshutdown(); + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); +} + void qemu_system_reset_request(ShutdownCause reason) { if (reboot_action == REBOOT_ACTION_SHUTDOWN && diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 056d117cd1..becca2efa5 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -2711,11 +2711,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) } /* Tell fw_cfg to notify the BIOS to reserve the range. */ - ret = e820_add_entry(identity_base, 0x4000, E820_RESERVED); - if (ret < 0) { - fprintf(stderr, "e820_add_entry() table is full\n"); - return ret; - } + e820_add_entry(identity_base, 0x4000, E820_RESERVED); shadow_mem = object_property_get_int(OBJECT(s), "kvm-shadow-mem", &error_abort); if (shadow_mem != -1) { diff --git a/target/i386/kvm/xen-emu.c b/target/i386/kvm/xen-emu.c index fc2c2321ac..2f89dc628e 100644 --- a/target/i386/kvm/xen-emu.c +++ b/target/i386/kvm/xen-emu.c @@ -176,12 +176,7 @@ int kvm_xen_init(KVMState *s, uint32_t hypercall_msr) s->xen_caps = xen_caps; /* Tell fw_cfg to notify the BIOS to reserve the range. */ - ret = e820_add_entry(XEN_SPECIAL_AREA_ADDR, XEN_SPECIAL_AREA_SIZE, - E820_RESERVED); - if (ret < 0) { - fprintf(stderr, "e820_add_entry() table is full\n"); - return ret; - } + e820_add_entry(XEN_SPECIAL_AREA_ADDR, XEN_SPECIAL_AREA_SIZE, E820_RESERVED); /* The pages couldn't be overlaid until KVM was initialized */ xen_primary_console_reset(); diff --git a/tcg/optimize.c b/tcg/optimize.c index 8886f7037a..ba16ec27e2 100644 --- a/tcg/optimize.c +++ b/tcg/optimize.c @@ -2384,7 +2384,7 @@ static bool fold_setcond2(OptContext *ctx, TCGOp *op) case TCG_COND_TSTEQ: case TCG_COND_TSTNE: - if (arg_is_const_val(op->args[2], 0)) { + if (arg_is_const_val(op->args[3], 0)) { goto do_setcond_high; } if (arg_is_const_val(op->args[4], 0)) { diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc index 639363039b..d334857226 100644 --- a/tcg/riscv/tcg-target.c.inc +++ b/tcg/riscv/tcg-target.c.inc @@ -113,20 +113,6 @@ static const int tcg_target_call_iarg_regs[] = { TCG_REG_A7, }; -#ifndef have_zbb -bool have_zbb; -#endif -#if defined(__riscv_arch_test) && defined(__riscv_zba) -# define have_zba true -#else -static bool have_zba; -#endif -#if defined(__riscv_arch_test) && defined(__riscv_zicond) -# define have_zicond true -#else -static bool have_zicond; -#endif - static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot) { tcg_debug_assert(kind == TCG_CALL_RET_NORMAL); @@ -594,7 +580,7 @@ static void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg) static void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg) { - if (have_zbb) { + if (cpuinfo & CPUINFO_ZBB) { tcg_out_opc_reg(s, OPC_ZEXT_H, ret, arg, TCG_REG_ZERO); } else { tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16); @@ -604,7 +590,7 @@ static void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg) static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg) { - if (have_zba) { + if (cpuinfo & CPUINFO_ZBA) { tcg_out_opc_reg(s, OPC_ADD_UW, ret, arg, TCG_REG_ZERO); } else { tcg_out_opc_imm(s, OPC_SLLI, ret, arg, 32); @@ -614,7 +600,7 @@ static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg) static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) { - if (have_zbb) { + if (cpuinfo & CPUINFO_ZBB) { tcg_out_opc_imm(s, OPC_SEXT_B, ret, arg, 0); } else { tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 24); @@ -624,7 +610,7 @@ static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) static void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) { - if (have_zbb) { + if (cpuinfo & CPUINFO_ZBB) { tcg_out_opc_imm(s, OPC_SEXT_H, ret, arg, 0); } else { tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16); @@ -1080,7 +1066,7 @@ static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret, int tmpflags; TCGReg t; - if (!have_zicond && (!c_cmp2 || cmp2 == 0)) { + if (!(cpuinfo & CPUINFO_ZICOND) && (!c_cmp2 || cmp2 == 0)) { tcg_out_movcond_br2(s, cond, ret, cmp1, cmp2, val1, c_val1, val2, c_val2); return; @@ -1089,7 +1075,7 @@ static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret, tmpflags = tcg_out_setcond_int(s, cond, TCG_REG_TMP0, cmp1, cmp2, c_cmp2); t = tmpflags & ~SETCOND_FLAGS; - if (have_zicond) { + if (cpuinfo & CPUINFO_ZICOND) { if (tmpflags & SETCOND_INV) { tcg_out_movcond_zicond(s, ret, t, val2, c_val2, val1, c_val1); } else { @@ -1304,7 +1290,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase, /* TLB Hit - translate address using addend. */ if (addr_type != TCG_TYPE_I32) { tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2); - } else if (have_zba) { + } else if (cpuinfo & CPUINFO_ZBA) { tcg_out_opc_reg(s, OPC_ADD_UW, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2); } else { @@ -1335,7 +1321,7 @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase, if (addr_type != TCG_TYPE_I32) { tcg_out_opc_reg(s, OPC_ADD, base, addr_reg, TCG_GUEST_BASE_REG); - } else if (have_zba) { + } else if (cpuinfo & CPUINFO_ZBA) { tcg_out_opc_reg(s, OPC_ADD_UW, base, addr_reg, TCG_GUEST_BASE_REG); } else { @@ -2110,62 +2096,8 @@ static void tcg_out_tb_start(TCGContext *s) /* nothing to do */ } -static volatile sig_atomic_t got_sigill; - -static void sigill_handler(int signo, siginfo_t *si, void *data) -{ - /* Skip the faulty instruction */ - ucontext_t *uc = (ucontext_t *)data; - uc->uc_mcontext.__gregs[REG_PC] += 4; - - got_sigill = 1; -} - -static void tcg_target_detect_isa(void) -{ -#if !defined(have_zba) || !defined(have_zbb) || !defined(have_zicond) - /* - * TODO: It is expected that this will be determinable via - * linux riscv_hwprobe syscall, not yet merged. - * In the meantime, test via sigill. - */ - - struct sigaction sa_old, sa_new; - - memset(&sa_new, 0, sizeof(sa_new)); - sa_new.sa_flags = SA_SIGINFO; - sa_new.sa_sigaction = sigill_handler; - sigaction(SIGILL, &sa_new, &sa_old); - -#ifndef have_zba - /* Probe for Zba: add.uw zero,zero,zero. */ - got_sigill = 0; - asm volatile(".insn r 0x3b, 0, 0x04, zero, zero, zero" : : : "memory"); - have_zba = !got_sigill; -#endif - -#ifndef have_zbb - /* Probe for Zba: andn zero,zero,zero. */ - got_sigill = 0; - asm volatile(".insn r 0x33, 7, 0x20, zero, zero, zero" : : : "memory"); - have_zbb = !got_sigill; -#endif - -#ifndef have_zicond - /* Probe for Zicond: czero.eqz zero,zero,zero. */ - got_sigill = 0; - asm volatile(".insn r 0x33, 5, 0x07, zero, zero, zero" : : : "memory"); - have_zicond = !got_sigill; -#endif - - sigaction(SIGILL, &sa_old, NULL); -#endif -} - static void tcg_target_init(TCGContext *s) { - tcg_target_detect_isa(); - tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff; tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff; diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h index 2c1b680b93..1a347eaf6e 100644 --- a/tcg/riscv/tcg-target.h +++ b/tcg/riscv/tcg-target.h @@ -25,6 +25,8 @@ #ifndef RISCV_TCG_TARGET_H #define RISCV_TCG_TARGET_H +#include "host/cpuinfo.h" + #define TCG_TARGET_INSN_UNIT_SIZE 4 #define TCG_TARGET_NB_REGS 32 #define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1) @@ -80,18 +82,12 @@ typedef enum { #define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_NORMAL #define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL -#if defined(__riscv_arch_test) && defined(__riscv_zbb) -# define have_zbb true -#else -extern bool have_zbb; -#endif - /* optional instructions */ #define TCG_TARGET_HAS_negsetcond_i32 1 #define TCG_TARGET_HAS_div_i32 1 #define TCG_TARGET_HAS_rem_i32 1 #define TCG_TARGET_HAS_div2_i32 0 -#define TCG_TARGET_HAS_rot_i32 have_zbb +#define TCG_TARGET_HAS_rot_i32 (cpuinfo & CPUINFO_ZBB) #define TCG_TARGET_HAS_deposit_i32 0 #define TCG_TARGET_HAS_extract_i32 0 #define TCG_TARGET_HAS_sextract_i32 0 @@ -106,17 +102,17 @@ extern bool have_zbb; #define TCG_TARGET_HAS_ext16s_i32 1 #define TCG_TARGET_HAS_ext8u_i32 1 #define TCG_TARGET_HAS_ext16u_i32 1 -#define TCG_TARGET_HAS_bswap16_i32 have_zbb -#define TCG_TARGET_HAS_bswap32_i32 have_zbb +#define TCG_TARGET_HAS_bswap16_i32 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_bswap32_i32 (cpuinfo & CPUINFO_ZBB) #define TCG_TARGET_HAS_not_i32 1 -#define TCG_TARGET_HAS_andc_i32 have_zbb -#define TCG_TARGET_HAS_orc_i32 have_zbb -#define TCG_TARGET_HAS_eqv_i32 have_zbb +#define TCG_TARGET_HAS_andc_i32 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_orc_i32 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_eqv_i32 (cpuinfo & CPUINFO_ZBB) #define TCG_TARGET_HAS_nand_i32 0 #define TCG_TARGET_HAS_nor_i32 0 -#define TCG_TARGET_HAS_clz_i32 have_zbb -#define TCG_TARGET_HAS_ctz_i32 have_zbb -#define TCG_TARGET_HAS_ctpop_i32 have_zbb +#define TCG_TARGET_HAS_clz_i32 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_ctz_i32 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_ctpop_i32 (cpuinfo & CPUINFO_ZBB) #define TCG_TARGET_HAS_brcond2 1 #define TCG_TARGET_HAS_setcond2 1 #define TCG_TARGET_HAS_qemu_st8_i32 0 @@ -125,7 +121,7 @@ extern bool have_zbb; #define TCG_TARGET_HAS_div_i64 1 #define TCG_TARGET_HAS_rem_i64 1 #define TCG_TARGET_HAS_div2_i64 0 -#define TCG_TARGET_HAS_rot_i64 have_zbb +#define TCG_TARGET_HAS_rot_i64 (cpuinfo & CPUINFO_ZBB) #define TCG_TARGET_HAS_deposit_i64 0 #define TCG_TARGET_HAS_extract_i64 0 #define TCG_TARGET_HAS_sextract_i64 0 @@ -137,18 +133,18 @@ extern bool have_zbb; #define TCG_TARGET_HAS_ext8u_i64 1 #define TCG_TARGET_HAS_ext16u_i64 1 #define TCG_TARGET_HAS_ext32u_i64 1 -#define TCG_TARGET_HAS_bswap16_i64 have_zbb -#define TCG_TARGET_HAS_bswap32_i64 have_zbb -#define TCG_TARGET_HAS_bswap64_i64 have_zbb +#define TCG_TARGET_HAS_bswap16_i64 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_bswap32_i64 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_bswap64_i64 (cpuinfo & CPUINFO_ZBB) #define TCG_TARGET_HAS_not_i64 1 -#define TCG_TARGET_HAS_andc_i64 have_zbb -#define TCG_TARGET_HAS_orc_i64 have_zbb -#define TCG_TARGET_HAS_eqv_i64 have_zbb +#define TCG_TARGET_HAS_andc_i64 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_orc_i64 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_eqv_i64 (cpuinfo & CPUINFO_ZBB) #define TCG_TARGET_HAS_nand_i64 0 #define TCG_TARGET_HAS_nor_i64 0 -#define TCG_TARGET_HAS_clz_i64 have_zbb -#define TCG_TARGET_HAS_ctz_i64 have_zbb -#define TCG_TARGET_HAS_ctpop_i64 have_zbb +#define TCG_TARGET_HAS_clz_i64 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_ctz_i64 (cpuinfo & CPUINFO_ZBB) +#define TCG_TARGET_HAS_ctpop_i64 (cpuinfo & CPUINFO_ZBB) #define TCG_TARGET_HAS_add2_i64 1 #define TCG_TARGET_HAS_sub2_i64 1 #define TCG_TARGET_HAS_mulu2_i64 0 diff --git a/tests/data/acpi/virt/APIC b/tests/data/acpi/aarch64/virt/APIC Binary files differindex 179d274770..179d274770 100644 --- a/tests/data/acpi/virt/APIC +++ b/tests/data/acpi/aarch64/virt/APIC diff --git a/tests/data/acpi/virt/APIC.acpihmatvirt b/tests/data/acpi/aarch64/virt/APIC.acpihmatvirt Binary files differindex 68200204c6..68200204c6 100644 --- a/tests/data/acpi/virt/APIC.acpihmatvirt +++ b/tests/data/acpi/aarch64/virt/APIC.acpihmatvirt diff --git a/tests/data/acpi/virt/APIC.topology b/tests/data/acpi/aarch64/virt/APIC.topology Binary files differindex 3a6ac525e7..3a6ac525e7 100644 --- a/tests/data/acpi/virt/APIC.topology +++ b/tests/data/acpi/aarch64/virt/APIC.topology diff --git a/tests/data/acpi/virt/DBG2 b/tests/data/acpi/aarch64/virt/DBG2 Binary files differindex 0a05e1a47f..0a05e1a47f 100644 --- a/tests/data/acpi/virt/DBG2 +++ b/tests/data/acpi/aarch64/virt/DBG2 diff --git a/tests/data/acpi/virt/DSDT b/tests/data/acpi/aarch64/virt/DSDT Binary files differindex c475039907..c475039907 100644 --- a/tests/data/acpi/virt/DSDT +++ b/tests/data/acpi/aarch64/virt/DSDT diff --git a/tests/data/acpi/virt/DSDT.acpihmatvirt b/tests/data/acpi/aarch64/virt/DSDT.acpihmatvirt Binary files differindex aee6ba017c..aee6ba017c 100644 --- a/tests/data/acpi/virt/DSDT.acpihmatvirt +++ b/tests/data/acpi/aarch64/virt/DSDT.acpihmatvirt diff --git a/tests/data/acpi/virt/DSDT.memhp b/tests/data/acpi/aarch64/virt/DSDT.memhp Binary files differindex bae36cdd39..bae36cdd39 100644 --- a/tests/data/acpi/virt/DSDT.memhp +++ b/tests/data/acpi/aarch64/virt/DSDT.memhp diff --git a/tests/data/acpi/virt/DSDT.pxb b/tests/data/acpi/aarch64/virt/DSDT.pxb Binary files differindex fbd78f44c4..fbd78f44c4 100644 --- a/tests/data/acpi/virt/DSDT.pxb +++ b/tests/data/acpi/aarch64/virt/DSDT.pxb diff --git a/tests/data/acpi/virt/DSDT.topology b/tests/data/acpi/aarch64/virt/DSDT.topology Binary files differindex 501314c91b..501314c91b 100644 --- a/tests/data/acpi/virt/DSDT.topology +++ b/tests/data/acpi/aarch64/virt/DSDT.topology diff --git a/tests/data/acpi/virt/FACP b/tests/data/acpi/aarch64/virt/FACP Binary files differindex da0c3644cc..da0c3644cc 100644 --- a/tests/data/acpi/virt/FACP +++ b/tests/data/acpi/aarch64/virt/FACP diff --git a/tests/data/acpi/virt/GTDT b/tests/data/acpi/aarch64/virt/GTDT Binary files differindex 7f330e04d1..7f330e04d1 100644 --- a/tests/data/acpi/virt/GTDT +++ b/tests/data/acpi/aarch64/virt/GTDT diff --git a/tests/data/acpi/virt/HMAT.acpihmatvirt b/tests/data/acpi/aarch64/virt/HMAT.acpihmatvirt Binary files differindex 6494d11b9f..6494d11b9f 100644 --- a/tests/data/acpi/virt/HMAT.acpihmatvirt +++ b/tests/data/acpi/aarch64/virt/HMAT.acpihmatvirt diff --git a/tests/data/acpi/virt/IORT b/tests/data/acpi/aarch64/virt/IORT Binary files differindex 7efd0ce8a6..7efd0ce8a6 100644 --- a/tests/data/acpi/virt/IORT +++ b/tests/data/acpi/aarch64/virt/IORT diff --git a/tests/data/acpi/virt/MCFG b/tests/data/acpi/aarch64/virt/MCFG Binary files differindex f4ae3203a4..f4ae3203a4 100644 --- a/tests/data/acpi/virt/MCFG +++ b/tests/data/acpi/aarch64/virt/MCFG diff --git a/tests/data/acpi/virt/NFIT.memhp b/tests/data/acpi/aarch64/virt/NFIT.memhp Binary files differindex 203db8c7be..203db8c7be 100644 --- a/tests/data/acpi/virt/NFIT.memhp +++ b/tests/data/acpi/aarch64/virt/NFIT.memhp diff --git a/tests/data/acpi/virt/PPTT b/tests/data/acpi/aarch64/virt/PPTT Binary files differindex 7a1258ecf1..7a1258ecf1 100644 --- a/tests/data/acpi/virt/PPTT +++ b/tests/data/acpi/aarch64/virt/PPTT diff --git a/tests/data/acpi/virt/PPTT.acpihmatvirt b/tests/data/acpi/aarch64/virt/PPTT.acpihmatvirt Binary files differindex 4eef303a5b..4eef303a5b 100644 --- a/tests/data/acpi/virt/PPTT.acpihmatvirt +++ b/tests/data/acpi/aarch64/virt/PPTT.acpihmatvirt diff --git a/tests/data/acpi/virt/PPTT.topology b/tests/data/acpi/aarch64/virt/PPTT.topology Binary files differindex 3fbcae5ff0..3fbcae5ff0 100644 --- a/tests/data/acpi/virt/PPTT.topology +++ b/tests/data/acpi/aarch64/virt/PPTT.topology diff --git a/tests/data/acpi/pc/SLIT.memhp b/tests/data/acpi/aarch64/virt/SLIT.memhp Binary files differindex 67f00813af..67f00813af 100644 --- a/tests/data/acpi/pc/SLIT.memhp +++ b/tests/data/acpi/aarch64/virt/SLIT.memhp diff --git a/tests/data/acpi/virt/SPCR b/tests/data/acpi/aarch64/virt/SPCR Binary files differindex cf0f2b7522..cf0f2b7522 100644 --- a/tests/data/acpi/virt/SPCR +++ b/tests/data/acpi/aarch64/virt/SPCR diff --git a/tests/data/acpi/virt/SRAT.acpihmatvirt b/tests/data/acpi/aarch64/virt/SRAT.acpihmatvirt Binary files differindex 6fe55dd7d0..6fe55dd7d0 100644 --- a/tests/data/acpi/virt/SRAT.acpihmatvirt +++ b/tests/data/acpi/aarch64/virt/SRAT.acpihmatvirt diff --git a/tests/data/acpi/virt/SRAT.memhp b/tests/data/acpi/aarch64/virt/SRAT.memhp Binary files differindex 01294cc892..01294cc892 100644 --- a/tests/data/acpi/virt/SRAT.memhp +++ b/tests/data/acpi/aarch64/virt/SRAT.memhp diff --git a/tests/data/acpi/virt/SRAT.numamem b/tests/data/acpi/aarch64/virt/SRAT.numamem Binary files differindex d45f40338c..d45f40338c 100644 --- a/tests/data/acpi/virt/SRAT.numamem +++ b/tests/data/acpi/aarch64/virt/SRAT.numamem diff --git a/tests/data/acpi/virt/SSDT.memhp b/tests/data/acpi/aarch64/virt/SSDT.memhp Binary files differindex fb3dcde5a1..fb3dcde5a1 100644 --- a/tests/data/acpi/virt/SSDT.memhp +++ b/tests/data/acpi/aarch64/virt/SSDT.memhp diff --git a/tests/data/acpi/virt/VIOT b/tests/data/acpi/aarch64/virt/VIOT Binary files differindex 921f40d88c..921f40d88c 100644 --- a/tests/data/acpi/virt/VIOT +++ b/tests/data/acpi/aarch64/virt/VIOT diff --git a/tests/data/acpi/rebuild-expected-aml.sh b/tests/data/acpi/rebuild-expected-aml.sh index dcf2e2f221..c1092fb8ba 100755 --- a/tests/data/acpi/rebuild-expected-aml.sh +++ b/tests/data/acpi/rebuild-expected-aml.sh @@ -12,7 +12,7 @@ # This work is licensed under the terms of the GNU GPLv2. # See the COPYING.LIB file in the top-level directory. -qemu_arches="x86_64 aarch64" +qemu_arches="x86_64 aarch64 riscv64" if [ ! -e "tests/qtest/bios-tables-test" ]; then echo "Test: bios-tables-test is required! Run make check before this script." @@ -36,7 +36,8 @@ fi if [ -z "$qemu_bins" ]; then echo "Only the following architectures are currently supported: $qemu_arches" echo "None of these configured!" - echo "To fix, run configure --target-list=x86_64-softmmu,aarch64-softmmu" + echo "To fix, run configure \ + --target-list=x86_64-softmmu,aarch64-softmmu,riscv64-softmmu" exit 1; fi diff --git a/tests/data/acpi/microvm/APIC b/tests/data/acpi/x86/microvm/APIC Binary files differindex 672764e711..672764e711 100644 --- a/tests/data/acpi/microvm/APIC +++ b/tests/data/acpi/x86/microvm/APIC diff --git a/tests/data/acpi/microvm/APIC.ioapic2 b/tests/data/acpi/x86/microvm/APIC.ioapic2 Binary files differindex 6f24fdb12c..6f24fdb12c 100644 --- a/tests/data/acpi/microvm/APIC.ioapic2 +++ b/tests/data/acpi/x86/microvm/APIC.ioapic2 diff --git a/tests/data/acpi/microvm/APIC.pcie b/tests/data/acpi/x86/microvm/APIC.pcie Binary files differindex 2239ca76a6..2239ca76a6 100644 --- a/tests/data/acpi/microvm/APIC.pcie +++ b/tests/data/acpi/x86/microvm/APIC.pcie diff --git a/tests/data/acpi/microvm/DSDT b/tests/data/acpi/x86/microvm/DSDT Binary files differindex f477668f2e..f477668f2e 100644 --- a/tests/data/acpi/microvm/DSDT +++ b/tests/data/acpi/x86/microvm/DSDT diff --git a/tests/data/acpi/microvm/DSDT.ioapic2 b/tests/data/acpi/x86/microvm/DSDT.ioapic2 Binary files differindex e5924a4996..e5924a4996 100644 --- a/tests/data/acpi/microvm/DSDT.ioapic2 +++ b/tests/data/acpi/x86/microvm/DSDT.ioapic2 diff --git a/tests/data/acpi/microvm/DSDT.pcie b/tests/data/acpi/x86/microvm/DSDT.pcie Binary files differindex 765f14ef3d..765f14ef3d 100644 --- a/tests/data/acpi/microvm/DSDT.pcie +++ b/tests/data/acpi/x86/microvm/DSDT.pcie diff --git a/tests/data/acpi/microvm/DSDT.rtc b/tests/data/acpi/x86/microvm/DSDT.rtc Binary files differindex e375473b5f..e375473b5f 100644 --- a/tests/data/acpi/microvm/DSDT.rtc +++ b/tests/data/acpi/x86/microvm/DSDT.rtc diff --git a/tests/data/acpi/microvm/DSDT.usb b/tests/data/acpi/x86/microvm/DSDT.usb Binary files differindex d63fd84620..d63fd84620 100644 --- a/tests/data/acpi/microvm/DSDT.usb +++ b/tests/data/acpi/x86/microvm/DSDT.usb diff --git a/tests/data/acpi/microvm/ERST.pcie b/tests/data/acpi/x86/microvm/ERST.pcie Binary files differindex a6d0cb7838..a6d0cb7838 100644 --- a/tests/data/acpi/microvm/ERST.pcie +++ b/tests/data/acpi/x86/microvm/ERST.pcie diff --git a/tests/data/acpi/microvm/FACP b/tests/data/acpi/x86/microvm/FACP Binary files differindex f12cef5cb6..f12cef5cb6 100644 --- a/tests/data/acpi/microvm/FACP +++ b/tests/data/acpi/x86/microvm/FACP diff --git a/tests/data/acpi/pc/APIC b/tests/data/acpi/x86/pc/APIC Binary files differindex 868a3432f0..868a3432f0 100644 --- a/tests/data/acpi/pc/APIC +++ b/tests/data/acpi/x86/pc/APIC diff --git a/tests/data/acpi/pc/APIC.acpihmat b/tests/data/acpi/x86/pc/APIC.acpihmat Binary files differindex 125d1ff087..125d1ff087 100644 --- a/tests/data/acpi/pc/APIC.acpihmat +++ b/tests/data/acpi/x86/pc/APIC.acpihmat diff --git a/tests/data/acpi/pc/APIC.cphp b/tests/data/acpi/x86/pc/APIC.cphp Binary files differindex a2c2a24e5e..a2c2a24e5e 100644 --- a/tests/data/acpi/pc/APIC.cphp +++ b/tests/data/acpi/x86/pc/APIC.cphp diff --git a/tests/data/acpi/pc/APIC.dimmpxm b/tests/data/acpi/x86/pc/APIC.dimmpxm Binary files differindex 9b5922bc72..9b5922bc72 100644 --- a/tests/data/acpi/pc/APIC.dimmpxm +++ b/tests/data/acpi/x86/pc/APIC.dimmpxm diff --git a/tests/data/acpi/pc/DSDT b/tests/data/acpi/x86/pc/DSDT Binary files differindex c93ad6b7f8..c93ad6b7f8 100644 --- a/tests/data/acpi/pc/DSDT +++ b/tests/data/acpi/x86/pc/DSDT diff --git a/tests/data/acpi/pc/DSDT.acpierst b/tests/data/acpi/x86/pc/DSDT.acpierst Binary files differindex f643fa2d03..f643fa2d03 100644 --- a/tests/data/acpi/pc/DSDT.acpierst +++ b/tests/data/acpi/x86/pc/DSDT.acpierst diff --git a/tests/data/acpi/pc/DSDT.acpihmat b/tests/data/acpi/x86/pc/DSDT.acpihmat Binary files differindex 9d3695ff28..9d3695ff28 100644 --- a/tests/data/acpi/pc/DSDT.acpihmat +++ b/tests/data/acpi/x86/pc/DSDT.acpihmat diff --git a/tests/data/acpi/pc/DSDT.bridge b/tests/data/acpi/x86/pc/DSDT.bridge Binary files differindex 840b45f354..840b45f354 100644 --- a/tests/data/acpi/pc/DSDT.bridge +++ b/tests/data/acpi/x86/pc/DSDT.bridge diff --git a/tests/data/acpi/pc/DSDT.cphp b/tests/data/acpi/x86/pc/DSDT.cphp Binary files differindex dbc0141b2b..dbc0141b2b 100644 --- a/tests/data/acpi/pc/DSDT.cphp +++ b/tests/data/acpi/x86/pc/DSDT.cphp diff --git a/tests/data/acpi/pc/DSDT.dimmpxm b/tests/data/acpi/x86/pc/DSDT.dimmpxm Binary files differindex 1294f655d4..1294f655d4 100644 --- a/tests/data/acpi/pc/DSDT.dimmpxm +++ b/tests/data/acpi/x86/pc/DSDT.dimmpxm diff --git a/tests/data/acpi/pc/DSDT.hpbridge b/tests/data/acpi/x86/pc/DSDT.hpbridge Binary files differindex 8012b5eb31..8012b5eb31 100644 --- a/tests/data/acpi/pc/DSDT.hpbridge +++ b/tests/data/acpi/x86/pc/DSDT.hpbridge diff --git a/tests/data/acpi/pc/DSDT.hpbrroot b/tests/data/acpi/x86/pc/DSDT.hpbrroot Binary files differindex 4fa0c6fe72..4fa0c6fe72 100644 --- a/tests/data/acpi/pc/DSDT.hpbrroot +++ b/tests/data/acpi/x86/pc/DSDT.hpbrroot diff --git a/tests/data/acpi/pc/DSDT.ipmikcs b/tests/data/acpi/x86/pc/DSDT.ipmikcs Binary files differindex 0a891baf45..0a891baf45 100644 --- a/tests/data/acpi/pc/DSDT.ipmikcs +++ b/tests/data/acpi/x86/pc/DSDT.ipmikcs diff --git a/tests/data/acpi/pc/DSDT.memhp b/tests/data/acpi/x86/pc/DSDT.memhp Binary files differindex 9b442a64cf..9b442a64cf 100644 --- a/tests/data/acpi/pc/DSDT.memhp +++ b/tests/data/acpi/x86/pc/DSDT.memhp diff --git a/tests/data/acpi/pc/DSDT.nohpet b/tests/data/acpi/x86/pc/DSDT.nohpet Binary files differindex 1754c68788..1754c68788 100644 --- a/tests/data/acpi/pc/DSDT.nohpet +++ b/tests/data/acpi/x86/pc/DSDT.nohpet diff --git a/tests/data/acpi/pc/DSDT.numamem b/tests/data/acpi/x86/pc/DSDT.numamem Binary files differindex 9fc731d3d2..9fc731d3d2 100644 --- a/tests/data/acpi/pc/DSDT.numamem +++ b/tests/data/acpi/x86/pc/DSDT.numamem diff --git a/tests/data/acpi/pc/DSDT.roothp b/tests/data/acpi/x86/pc/DSDT.roothp Binary files differindex e654c83ebe..e654c83ebe 100644 --- a/tests/data/acpi/pc/DSDT.roothp +++ b/tests/data/acpi/x86/pc/DSDT.roothp diff --git a/tests/data/acpi/pc/ERST.acpierst b/tests/data/acpi/x86/pc/ERST.acpierst Binary files differindex 7965ac2562..7965ac2562 100644 --- a/tests/data/acpi/pc/ERST.acpierst +++ b/tests/data/acpi/x86/pc/ERST.acpierst diff --git a/tests/data/acpi/pc/FACP b/tests/data/acpi/x86/pc/FACP Binary files differindex 5fe21a5967..5fe21a5967 100644 --- a/tests/data/acpi/pc/FACP +++ b/tests/data/acpi/x86/pc/FACP diff --git a/tests/data/acpi/pc/FACP.nosmm b/tests/data/acpi/x86/pc/FACP.nosmm Binary files differindex 7e19550748..7e19550748 100644 --- a/tests/data/acpi/pc/FACP.nosmm +++ b/tests/data/acpi/x86/pc/FACP.nosmm diff --git a/tests/data/acpi/pc/FACS b/tests/data/acpi/x86/pc/FACS Binary files differindex fc67ecc407..fc67ecc407 100644 --- a/tests/data/acpi/pc/FACS +++ b/tests/data/acpi/x86/pc/FACS diff --git a/tests/data/acpi/pc/HMAT.acpihmat b/tests/data/acpi/x86/pc/HMAT.acpihmat Binary files differindex a9d8e5cd47..a9d8e5cd47 100644 --- a/tests/data/acpi/pc/HMAT.acpihmat +++ b/tests/data/acpi/x86/pc/HMAT.acpihmat diff --git a/tests/data/acpi/pc/HPET b/tests/data/acpi/x86/pc/HPET Binary files differindex 19f704abdd..19f704abdd 100644 --- a/tests/data/acpi/pc/HPET +++ b/tests/data/acpi/x86/pc/HPET diff --git a/tests/data/acpi/pc/NFIT.dimmpxm b/tests/data/acpi/x86/pc/NFIT.dimmpxm Binary files differindex 02d23385bc..02d23385bc 100644 --- a/tests/data/acpi/pc/NFIT.dimmpxm +++ b/tests/data/acpi/x86/pc/NFIT.dimmpxm diff --git a/tests/data/acpi/pc/SLIT.cphp b/tests/data/acpi/x86/pc/SLIT.cphp Binary files differindex 67f00813af..67f00813af 100644 --- a/tests/data/acpi/pc/SLIT.cphp +++ b/tests/data/acpi/x86/pc/SLIT.cphp diff --git a/tests/data/acpi/q35/SLIT.memhp b/tests/data/acpi/x86/pc/SLIT.memhp Binary files differindex 67f00813af..67f00813af 100644 --- a/tests/data/acpi/q35/SLIT.memhp +++ b/tests/data/acpi/x86/pc/SLIT.memhp diff --git a/tests/data/acpi/pc/SRAT.acpihmat b/tests/data/acpi/x86/pc/SRAT.acpihmat Binary files differindex e0b36e97f6..e0b36e97f6 100644 --- a/tests/data/acpi/pc/SRAT.acpihmat +++ b/tests/data/acpi/x86/pc/SRAT.acpihmat diff --git a/tests/data/acpi/pc/SRAT.cphp b/tests/data/acpi/x86/pc/SRAT.cphp Binary files differindex d8ce4f5a9c..d8ce4f5a9c 100644 --- a/tests/data/acpi/pc/SRAT.cphp +++ b/tests/data/acpi/x86/pc/SRAT.cphp diff --git a/tests/data/acpi/pc/SRAT.dimmpxm b/tests/data/acpi/x86/pc/SRAT.dimmpxm Binary files differindex 7eed48cf2d..7eed48cf2d 100644 --- a/tests/data/acpi/pc/SRAT.dimmpxm +++ b/tests/data/acpi/x86/pc/SRAT.dimmpxm diff --git a/tests/data/acpi/pc/SRAT.memhp b/tests/data/acpi/x86/pc/SRAT.memhp Binary files differindex a5b5f9adef..a5b5f9adef 100644 --- a/tests/data/acpi/pc/SRAT.memhp +++ b/tests/data/acpi/x86/pc/SRAT.memhp diff --git a/tests/data/acpi/pc/SRAT.numamem b/tests/data/acpi/x86/pc/SRAT.numamem Binary files differindex 56da58e269..56da58e269 100644 --- a/tests/data/acpi/pc/SRAT.numamem +++ b/tests/data/acpi/x86/pc/SRAT.numamem diff --git a/tests/data/acpi/pc/SSDT.dimmpxm b/tests/data/acpi/x86/pc/SSDT.dimmpxm Binary files differindex 70f133412f..70f133412f 100644 --- a/tests/data/acpi/pc/SSDT.dimmpxm +++ b/tests/data/acpi/x86/pc/SSDT.dimmpxm diff --git a/tests/data/acpi/pc/WAET b/tests/data/acpi/x86/pc/WAET Binary files differindex ac0db59183..ac0db59183 100644 --- a/tests/data/acpi/pc/WAET +++ b/tests/data/acpi/x86/pc/WAET diff --git a/tests/data/acpi/q35/APIC b/tests/data/acpi/x86/q35/APIC Binary files differindex 868a3432f0..868a3432f0 100644 --- a/tests/data/acpi/q35/APIC +++ b/tests/data/acpi/x86/q35/APIC diff --git a/tests/data/acpi/q35/APIC.acpihmat b/tests/data/acpi/x86/q35/APIC.acpihmat Binary files differindex 125d1ff087..125d1ff087 100644 --- a/tests/data/acpi/q35/APIC.acpihmat +++ b/tests/data/acpi/x86/q35/APIC.acpihmat diff --git a/tests/data/acpi/q35/APIC.acpihmat-noinitiator b/tests/data/acpi/x86/q35/APIC.acpihmat-noinitiator Binary files differindex 9b5922bc72..9b5922bc72 100644 --- a/tests/data/acpi/q35/APIC.acpihmat-noinitiator +++ b/tests/data/acpi/x86/q35/APIC.acpihmat-noinitiator diff --git a/tests/data/acpi/q35/APIC.core-count b/tests/data/acpi/x86/q35/APIC.core-count Binary files differindex d9d7ca9a89..d9d7ca9a89 100644 --- a/tests/data/acpi/q35/APIC.core-count +++ b/tests/data/acpi/x86/q35/APIC.core-count diff --git a/tests/data/acpi/q35/APIC.core-count2 b/tests/data/acpi/x86/q35/APIC.core-count2 Binary files differindex 4f24284434..4f24284434 100644 --- a/tests/data/acpi/q35/APIC.core-count2 +++ b/tests/data/acpi/x86/q35/APIC.core-count2 diff --git a/tests/data/acpi/q35/APIC.cphp b/tests/data/acpi/x86/q35/APIC.cphp Binary files differindex a2c2a24e5e..a2c2a24e5e 100644 --- a/tests/data/acpi/q35/APIC.cphp +++ b/tests/data/acpi/x86/q35/APIC.cphp diff --git a/tests/data/acpi/q35/APIC.dimmpxm b/tests/data/acpi/x86/q35/APIC.dimmpxm Binary files differindex 9b5922bc72..9b5922bc72 100644 --- a/tests/data/acpi/q35/APIC.dimmpxm +++ b/tests/data/acpi/x86/q35/APIC.dimmpxm diff --git a/tests/data/acpi/q35/APIC.thread-count b/tests/data/acpi/x86/q35/APIC.thread-count Binary files differindex c27e87fcf1..c27e87fcf1 100644 --- a/tests/data/acpi/q35/APIC.thread-count +++ b/tests/data/acpi/x86/q35/APIC.thread-count diff --git a/tests/data/acpi/q35/APIC.thread-count2 b/tests/data/acpi/x86/q35/APIC.thread-count2 Binary files differindex ac200ab7aa..ac200ab7aa 100644 --- a/tests/data/acpi/q35/APIC.thread-count2 +++ b/tests/data/acpi/x86/q35/APIC.thread-count2 diff --git a/tests/data/acpi/q35/APIC.type4-count b/tests/data/acpi/x86/q35/APIC.type4-count Binary files differindex ab60a6ef06..ab60a6ef06 100644 --- a/tests/data/acpi/q35/APIC.type4-count +++ b/tests/data/acpi/x86/q35/APIC.type4-count diff --git a/tests/data/acpi/q35/APIC.xapic b/tests/data/acpi/x86/q35/APIC.xapic Binary files differindex 83bd28325a..83bd28325a 100644 --- a/tests/data/acpi/q35/APIC.xapic +++ b/tests/data/acpi/x86/q35/APIC.xapic diff --git a/tests/data/acpi/q35/CEDT.cxl b/tests/data/acpi/x86/q35/CEDT.cxl Binary files differindex ff8203af07..ff8203af07 100644 --- a/tests/data/acpi/q35/CEDT.cxl +++ b/tests/data/acpi/x86/q35/CEDT.cxl diff --git a/tests/data/acpi/q35/DMAR.dmar b/tests/data/acpi/x86/q35/DMAR.dmar Binary files differindex 0dca6e68ad..0dca6e68ad 100644 --- a/tests/data/acpi/q35/DMAR.dmar +++ b/tests/data/acpi/x86/q35/DMAR.dmar diff --git a/tests/data/acpi/q35/DSDT b/tests/data/acpi/x86/q35/DSDT Binary files differindex fb89ae0ac6..fb89ae0ac6 100644 --- a/tests/data/acpi/q35/DSDT +++ b/tests/data/acpi/x86/q35/DSDT diff --git a/tests/data/acpi/q35/DSDT.acpierst b/tests/data/acpi/x86/q35/DSDT.acpierst Binary files differindex 46fd25400b..46fd25400b 100644 --- a/tests/data/acpi/q35/DSDT.acpierst +++ b/tests/data/acpi/x86/q35/DSDT.acpierst diff --git a/tests/data/acpi/q35/DSDT.acpihmat b/tests/data/acpi/x86/q35/DSDT.acpihmat Binary files differindex 61c5bd52a4..61c5bd52a4 100644 --- a/tests/data/acpi/q35/DSDT.acpihmat +++ b/tests/data/acpi/x86/q35/DSDT.acpihmat diff --git a/tests/data/acpi/q35/DSDT.acpihmat-noinitiator b/tests/data/acpi/x86/q35/DSDT.acpihmat-noinitiator Binary files differindex 3aaa2bbdf5..3aaa2bbdf5 100644 --- a/tests/data/acpi/q35/DSDT.acpihmat-noinitiator +++ b/tests/data/acpi/x86/q35/DSDT.acpihmat-noinitiator diff --git a/tests/data/acpi/q35/DSDT.applesmc b/tests/data/acpi/x86/q35/DSDT.applesmc Binary files differindex 944209adea..944209adea 100644 --- a/tests/data/acpi/q35/DSDT.applesmc +++ b/tests/data/acpi/x86/q35/DSDT.applesmc diff --git a/tests/data/acpi/q35/DSDT.bridge b/tests/data/acpi/x86/q35/DSDT.bridge Binary files differindex d9938dba8f..d9938dba8f 100644 --- a/tests/data/acpi/q35/DSDT.bridge +++ b/tests/data/acpi/x86/q35/DSDT.bridge diff --git a/tests/data/acpi/q35/DSDT.core-count b/tests/data/acpi/x86/q35/DSDT.core-count Binary files differindex a24b04cbdb..a24b04cbdb 100644 --- a/tests/data/acpi/q35/DSDT.core-count +++ b/tests/data/acpi/x86/q35/DSDT.core-count diff --git a/tests/data/acpi/q35/DSDT.core-count2 b/tests/data/acpi/x86/q35/DSDT.core-count2 Binary files differindex 3a0cb8c581..3a0cb8c581 100644 --- a/tests/data/acpi/q35/DSDT.core-count2 +++ b/tests/data/acpi/x86/q35/DSDT.core-count2 diff --git a/tests/data/acpi/q35/DSDT.cphp b/tests/data/acpi/x86/q35/DSDT.cphp Binary files differindex 20955d0aa3..20955d0aa3 100644 --- a/tests/data/acpi/q35/DSDT.cphp +++ b/tests/data/acpi/x86/q35/DSDT.cphp diff --git a/tests/data/acpi/q35/DSDT.cxl b/tests/data/acpi/x86/q35/DSDT.cxl Binary files differindex afcdc0d0ba..afcdc0d0ba 100644 --- a/tests/data/acpi/q35/DSDT.cxl +++ b/tests/data/acpi/x86/q35/DSDT.cxl diff --git a/tests/data/acpi/q35/DSDT.dimmpxm b/tests/data/acpi/x86/q35/DSDT.dimmpxm Binary files differindex 228374b55b..228374b55b 100644 --- a/tests/data/acpi/q35/DSDT.dimmpxm +++ b/tests/data/acpi/x86/q35/DSDT.dimmpxm diff --git a/tests/data/acpi/q35/DSDT.ipmibt b/tests/data/acpi/x86/q35/DSDT.ipmibt Binary files differindex 45f911ada5..45f911ada5 100644 --- a/tests/data/acpi/q35/DSDT.ipmibt +++ b/tests/data/acpi/x86/q35/DSDT.ipmibt diff --git a/tests/data/acpi/q35/DSDT.ipmismbus b/tests/data/acpi/x86/q35/DSDT.ipmismbus Binary files differindex e5d6811bee..e5d6811bee 100644 --- a/tests/data/acpi/q35/DSDT.ipmismbus +++ b/tests/data/acpi/x86/q35/DSDT.ipmismbus diff --git a/tests/data/acpi/q35/DSDT.ivrs b/tests/data/acpi/x86/q35/DSDT.ivrs Binary files differindex 46fd25400b..46fd25400b 100644 --- a/tests/data/acpi/q35/DSDT.ivrs +++ b/tests/data/acpi/x86/q35/DSDT.ivrs diff --git a/tests/data/acpi/q35/DSDT.memhp b/tests/data/acpi/x86/q35/DSDT.memhp Binary files differindex 5ce081187a..5ce081187a 100644 --- a/tests/data/acpi/q35/DSDT.memhp +++ b/tests/data/acpi/x86/q35/DSDT.memhp diff --git a/tests/data/acpi/q35/DSDT.mmio64 b/tests/data/acpi/x86/q35/DSDT.mmio64 Binary files differindex bdf36c4d57..bdf36c4d57 100644 --- a/tests/data/acpi/q35/DSDT.mmio64 +++ b/tests/data/acpi/x86/q35/DSDT.mmio64 diff --git a/tests/data/acpi/q35/DSDT.multi-bridge b/tests/data/acpi/x86/q35/DSDT.multi-bridge Binary files differindex 1db43a69e4..1db43a69e4 100644 --- a/tests/data/acpi/q35/DSDT.multi-bridge +++ b/tests/data/acpi/x86/q35/DSDT.multi-bridge diff --git a/tests/data/acpi/q35/DSDT.noacpihp b/tests/data/acpi/x86/q35/DSDT.noacpihp Binary files differindex 8bc16887e1..8bc16887e1 100644 --- a/tests/data/acpi/q35/DSDT.noacpihp +++ b/tests/data/acpi/x86/q35/DSDT.noacpihp diff --git a/tests/data/acpi/q35/DSDT.nohpet b/tests/data/acpi/x86/q35/DSDT.nohpet Binary files differindex c13e45e361..c13e45e361 100644 --- a/tests/data/acpi/q35/DSDT.nohpet +++ b/tests/data/acpi/x86/q35/DSDT.nohpet diff --git a/tests/data/acpi/q35/DSDT.numamem b/tests/data/acpi/x86/q35/DSDT.numamem Binary files differindex ba6669437e..ba6669437e 100644 --- a/tests/data/acpi/q35/DSDT.numamem +++ b/tests/data/acpi/x86/q35/DSDT.numamem diff --git a/tests/data/acpi/q35/DSDT.pvpanic-isa b/tests/data/acpi/x86/q35/DSDT.pvpanic-isa Binary files differindex 6ad42873e9..6ad42873e9 100644 --- a/tests/data/acpi/q35/DSDT.pvpanic-isa +++ b/tests/data/acpi/x86/q35/DSDT.pvpanic-isa diff --git a/tests/data/acpi/q35/DSDT.thread-count b/tests/data/acpi/x86/q35/DSDT.thread-count Binary files differindex a24b04cbdb..a24b04cbdb 100644 --- a/tests/data/acpi/q35/DSDT.thread-count +++ b/tests/data/acpi/x86/q35/DSDT.thread-count diff --git a/tests/data/acpi/q35/DSDT.thread-count2 b/tests/data/acpi/x86/q35/DSDT.thread-count2 Binary files differindex 3a0cb8c581..3a0cb8c581 100644 --- a/tests/data/acpi/q35/DSDT.thread-count2 +++ b/tests/data/acpi/x86/q35/DSDT.thread-count2 diff --git a/tests/data/acpi/q35/DSDT.tis.tpm12 b/tests/data/acpi/x86/q35/DSDT.tis.tpm12 Binary files differindex e381ce4cbf..e381ce4cbf 100644 --- a/tests/data/acpi/q35/DSDT.tis.tpm12 +++ b/tests/data/acpi/x86/q35/DSDT.tis.tpm12 diff --git a/tests/data/acpi/q35/DSDT.tis.tpm2 b/tests/data/acpi/x86/q35/DSDT.tis.tpm2 Binary files differindex a09253042c..a09253042c 100644 --- a/tests/data/acpi/q35/DSDT.tis.tpm2 +++ b/tests/data/acpi/x86/q35/DSDT.tis.tpm2 diff --git a/tests/data/acpi/q35/DSDT.type4-count b/tests/data/acpi/x86/q35/DSDT.type4-count Binary files differindex edc23198cd..edc23198cd 100644 --- a/tests/data/acpi/q35/DSDT.type4-count +++ b/tests/data/acpi/x86/q35/DSDT.type4-count diff --git a/tests/data/acpi/q35/DSDT.viot b/tests/data/acpi/x86/q35/DSDT.viot Binary files differindex 64e81f5711..64e81f5711 100644 --- a/tests/data/acpi/q35/DSDT.viot +++ b/tests/data/acpi/x86/q35/DSDT.viot diff --git a/tests/data/acpi/q35/DSDT.xapic b/tests/data/acpi/x86/q35/DSDT.xapic Binary files differindex d4acd851c6..d4acd851c6 100644 --- a/tests/data/acpi/q35/DSDT.xapic +++ b/tests/data/acpi/x86/q35/DSDT.xapic diff --git a/tests/data/acpi/q35/ERST.acpierst b/tests/data/acpi/x86/q35/ERST.acpierst Binary files differindex 7965ac2562..7965ac2562 100644 --- a/tests/data/acpi/q35/ERST.acpierst +++ b/tests/data/acpi/x86/q35/ERST.acpierst diff --git a/tests/data/acpi/q35/FACP b/tests/data/acpi/x86/q35/FACP Binary files differindex a8f6a89611..a8f6a89611 100644 --- a/tests/data/acpi/q35/FACP +++ b/tests/data/acpi/x86/q35/FACP diff --git a/tests/data/acpi/q35/FACP.core-count b/tests/data/acpi/x86/q35/FACP.core-count Binary files differindex 31fa5dd19c..31fa5dd19c 100644 --- a/tests/data/acpi/q35/FACP.core-count +++ b/tests/data/acpi/x86/q35/FACP.core-count diff --git a/tests/data/acpi/q35/FACP.core-count2 b/tests/data/acpi/x86/q35/FACP.core-count2 Binary files differindex 31fa5dd19c..31fa5dd19c 100644 --- a/tests/data/acpi/q35/FACP.core-count2 +++ b/tests/data/acpi/x86/q35/FACP.core-count2 diff --git a/tests/data/acpi/q35/FACP.nosmm b/tests/data/acpi/x86/q35/FACP.nosmm Binary files differindex c4e6d18ee5..c4e6d18ee5 100644 --- a/tests/data/acpi/q35/FACP.nosmm +++ b/tests/data/acpi/x86/q35/FACP.nosmm diff --git a/tests/data/acpi/q35/FACP.slic b/tests/data/acpi/x86/q35/FACP.slic Binary files differindex 48bbb1cf5a..48bbb1cf5a 100644 --- a/tests/data/acpi/q35/FACP.slic +++ b/tests/data/acpi/x86/q35/FACP.slic diff --git a/tests/data/acpi/q35/FACP.thread-count b/tests/data/acpi/x86/q35/FACP.thread-count Binary files differindex 31fa5dd19c..31fa5dd19c 100644 --- a/tests/data/acpi/q35/FACP.thread-count +++ b/tests/data/acpi/x86/q35/FACP.thread-count diff --git a/tests/data/acpi/q35/FACP.thread-count2 b/tests/data/acpi/x86/q35/FACP.thread-count2 Binary files differindex 31fa5dd19c..31fa5dd19c 100644 --- a/tests/data/acpi/q35/FACP.thread-count2 +++ b/tests/data/acpi/x86/q35/FACP.thread-count2 diff --git a/tests/data/acpi/q35/FACP.type4-count b/tests/data/acpi/x86/q35/FACP.type4-count Binary files differindex 31fa5dd19c..31fa5dd19c 100644 --- a/tests/data/acpi/q35/FACP.type4-count +++ b/tests/data/acpi/x86/q35/FACP.type4-count diff --git a/tests/data/acpi/q35/FACP.xapic b/tests/data/acpi/x86/q35/FACP.xapic Binary files differindex 31fa5dd19c..31fa5dd19c 100644 --- a/tests/data/acpi/q35/FACP.xapic +++ b/tests/data/acpi/x86/q35/FACP.xapic diff --git a/tests/data/acpi/q35/FACS b/tests/data/acpi/x86/q35/FACS Binary files differindex fc67ecc407..fc67ecc407 100644 --- a/tests/data/acpi/q35/FACS +++ b/tests/data/acpi/x86/q35/FACS diff --git a/tests/data/acpi/q35/HMAT.acpihmat b/tests/data/acpi/x86/q35/HMAT.acpihmat Binary files differindex a9d8e5cd47..a9d8e5cd47 100644 --- a/tests/data/acpi/q35/HMAT.acpihmat +++ b/tests/data/acpi/x86/q35/HMAT.acpihmat diff --git a/tests/data/acpi/q35/HMAT.acpihmat-noinitiator b/tests/data/acpi/x86/q35/HMAT.acpihmat-noinitiator Binary files differindex 6494d11b9f..6494d11b9f 100644 --- a/tests/data/acpi/q35/HMAT.acpihmat-noinitiator +++ b/tests/data/acpi/x86/q35/HMAT.acpihmat-noinitiator diff --git a/tests/data/acpi/q35/HPET b/tests/data/acpi/x86/q35/HPET Binary files differindex 19f704abdd..19f704abdd 100644 --- a/tests/data/acpi/q35/HPET +++ b/tests/data/acpi/x86/q35/HPET diff --git a/tests/data/acpi/q35/IVRS.ivrs b/tests/data/acpi/x86/q35/IVRS.ivrs Binary files differindex 7f9e91aabc..7f9e91aabc 100644 --- a/tests/data/acpi/q35/IVRS.ivrs +++ b/tests/data/acpi/x86/q35/IVRS.ivrs diff --git a/tests/data/acpi/q35/MCFG b/tests/data/acpi/x86/q35/MCFG Binary files differindex 696bc969f2..696bc969f2 100644 --- a/tests/data/acpi/q35/MCFG +++ b/tests/data/acpi/x86/q35/MCFG diff --git a/tests/data/acpi/q35/NFIT.dimmpxm b/tests/data/acpi/x86/q35/NFIT.dimmpxm Binary files differindex 02d23385bc..02d23385bc 100644 --- a/tests/data/acpi/q35/NFIT.dimmpxm +++ b/tests/data/acpi/x86/q35/NFIT.dimmpxm diff --git a/tests/data/acpi/q35/SLIC.slic b/tests/data/acpi/x86/q35/SLIC.slic Binary files differindex fd26592e24..fd26592e24 100644 --- a/tests/data/acpi/q35/SLIC.slic +++ b/tests/data/acpi/x86/q35/SLIC.slic diff --git a/tests/data/acpi/q35/SLIT.cphp b/tests/data/acpi/x86/q35/SLIT.cphp Binary files differindex 67f00813af..67f00813af 100644 --- a/tests/data/acpi/q35/SLIT.cphp +++ b/tests/data/acpi/x86/q35/SLIT.cphp diff --git a/tests/data/acpi/virt/SLIT.memhp b/tests/data/acpi/x86/q35/SLIT.memhp Binary files differindex 67f00813af..67f00813af 100644 --- a/tests/data/acpi/virt/SLIT.memhp +++ b/tests/data/acpi/x86/q35/SLIT.memhp diff --git a/tests/data/acpi/q35/SRAT.acpihmat b/tests/data/acpi/x86/q35/SRAT.acpihmat Binary files differindex e0b36e97f6..e0b36e97f6 100644 --- a/tests/data/acpi/q35/SRAT.acpihmat +++ b/tests/data/acpi/x86/q35/SRAT.acpihmat diff --git a/tests/data/acpi/q35/SRAT.acpihmat-noinitiator b/tests/data/acpi/x86/q35/SRAT.acpihmat-noinitiator Binary files differindex a11d3119ab..a11d3119ab 100644 --- a/tests/data/acpi/q35/SRAT.acpihmat-noinitiator +++ b/tests/data/acpi/x86/q35/SRAT.acpihmat-noinitiator diff --git a/tests/data/acpi/q35/SRAT.cphp b/tests/data/acpi/x86/q35/SRAT.cphp Binary files differindex d8ce4f5a9c..d8ce4f5a9c 100644 --- a/tests/data/acpi/q35/SRAT.cphp +++ b/tests/data/acpi/x86/q35/SRAT.cphp diff --git a/tests/data/acpi/q35/SRAT.dimmpxm b/tests/data/acpi/x86/q35/SRAT.dimmpxm Binary files differindex 7eed48cf2d..7eed48cf2d 100644 --- a/tests/data/acpi/q35/SRAT.dimmpxm +++ b/tests/data/acpi/x86/q35/SRAT.dimmpxm diff --git a/tests/data/acpi/q35/SRAT.memhp b/tests/data/acpi/x86/q35/SRAT.memhp Binary files differindex a5b5f9adef..a5b5f9adef 100644 --- a/tests/data/acpi/q35/SRAT.memhp +++ b/tests/data/acpi/x86/q35/SRAT.memhp diff --git a/tests/data/acpi/q35/SRAT.mmio64 b/tests/data/acpi/x86/q35/SRAT.mmio64 Binary files differindex f5e1e3932a..f5e1e3932a 100644 --- a/tests/data/acpi/q35/SRAT.mmio64 +++ b/tests/data/acpi/x86/q35/SRAT.mmio64 diff --git a/tests/data/acpi/q35/SRAT.numamem b/tests/data/acpi/x86/q35/SRAT.numamem Binary files differindex 56da58e269..56da58e269 100644 --- a/tests/data/acpi/q35/SRAT.numamem +++ b/tests/data/acpi/x86/q35/SRAT.numamem diff --git a/tests/data/acpi/q35/SRAT.xapic b/tests/data/acpi/x86/q35/SRAT.xapic Binary files differindex 1a91cfa65f..1a91cfa65f 100644 --- a/tests/data/acpi/q35/SRAT.xapic +++ b/tests/data/acpi/x86/q35/SRAT.xapic diff --git a/tests/data/acpi/q35/SSDT.dimmpxm b/tests/data/acpi/x86/q35/SSDT.dimmpxm Binary files differindex 9ea4e0d0ce..9ea4e0d0ce 100644 --- a/tests/data/acpi/q35/SSDT.dimmpxm +++ b/tests/data/acpi/x86/q35/SSDT.dimmpxm diff --git a/tests/data/acpi/q35/TCPA.tis.tpm12 b/tests/data/acpi/x86/q35/TCPA.tis.tpm12 Binary files differindex a56961b413..a56961b413 100644 --- a/tests/data/acpi/q35/TCPA.tis.tpm12 +++ b/tests/data/acpi/x86/q35/TCPA.tis.tpm12 diff --git a/tests/data/acpi/q35/TPM2.tis.tpm2 b/tests/data/acpi/x86/q35/TPM2.tis.tpm2 Binary files differindex fe0f05987b..fe0f05987b 100644 --- a/tests/data/acpi/q35/TPM2.tis.tpm2 +++ b/tests/data/acpi/x86/q35/TPM2.tis.tpm2 diff --git a/tests/data/acpi/q35/VIOT.viot b/tests/data/acpi/x86/q35/VIOT.viot Binary files differindex 275c78fbe8..275c78fbe8 100644 --- a/tests/data/acpi/q35/VIOT.viot +++ b/tests/data/acpi/x86/q35/VIOT.viot diff --git a/tests/data/acpi/q35/WAET b/tests/data/acpi/x86/q35/WAET Binary files differindex ac0db59183..ac0db59183 100644 --- a/tests/data/acpi/q35/WAET +++ b/tests/data/acpi/x86/q35/WAET diff --git a/tests/data/uefi-boot-images/bios-tables-test.riscv64.iso.qcow2 b/tests/data/uefi-boot-images/bios-tables-test.riscv64.iso.qcow2 Binary files differnew file mode 100644 index 0000000000..c720bf99a4 --- /dev/null +++ b/tests/data/uefi-boot-images/bios-tables-test.riscv64.iso.qcow2 diff --git a/tests/qemu-iotests/061 b/tests/qemu-iotests/061 index 53c7d428e3..b71ac097d1 100755 --- a/tests/qemu-iotests/061 +++ b/tests/qemu-iotests/061 @@ -326,12 +326,14 @@ $QEMU_IMG amend -o "data_file=foo" "$TEST_IMG" echo _make_test_img -o "compat=1.1,data_file=$TEST_IMG.data" 64M $QEMU_IMG amend -o "data_file=foo" "$TEST_IMG" -_img_info --format-specific +$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt +$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts echo $QEMU_IMG amend -o "data_file=" --image-opts "data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -_img_info --format-specific +$QEMU_IO -c "read 0 4k" "$TEST_IMG" 2>&1 | _filter_testdir | _filter_imgfmt +$QEMU_IO -c "open -o data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" -c "read 0 4k" | _filter_qemu_io TEST_IMG="data-file.filename=$TEST_IMG.data,file.filename=$TEST_IMG" _img_info --format-specific --image-opts echo diff --git a/tests/qemu-iotests/061.out b/tests/qemu-iotests/061.out index 139fc68177..24c33add7c 100644 --- a/tests/qemu-iotests/061.out +++ b/tests/qemu-iotests/061.out @@ -545,7 +545,9 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 qemu-img: data-file can only be set for images that use an external data file Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 data_file=TEST_DIR/t.IMGFMT.data -qemu-img: Could not open 'TEST_DIR/t.IMGFMT': Could not open 'foo': No such file or directory +qemu-io: can't open device TEST_DIR/t.IMGFMT: Could not open 'foo': No such file or directory +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) image: TEST_DIR/t.IMGFMT file format: IMGFMT virtual size: 64 MiB (67108864 bytes) @@ -560,7 +562,9 @@ Format specific information: corrupt: false extended l2: false -qemu-img: Could not open 'TEST_DIR/t.IMGFMT': 'data-file' is required for this image +qemu-io: can't open device TEST_DIR/t.IMGFMT: 'data-file' is required for this image +read 4096/4096 bytes at offset 0 +4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) image: TEST_DIR/t.IMGFMT file format: IMGFMT virtual size: 64 MiB (67108864 bytes) diff --git a/tests/qemu-iotests/244 b/tests/qemu-iotests/244 index 3e61fa25bb..bb9cc6512f 100755 --- a/tests/qemu-iotests/244 +++ b/tests/qemu-iotests/244 @@ -215,9 +215,22 @@ $QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$TEST_IMG" $QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$TEST_IMG" # blkdebug doesn't support copy offloading, so this tests the error path -$QEMU_IMG amend -f $IMGFMT -o "data_file=blkdebug::$TEST_IMG.data" "$TEST_IMG" -$QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$TEST_IMG" -$QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$TEST_IMG" +test_img_with_blkdebug="json:{ + 'driver': 'qcow2', + 'file': { + 'driver': 'file', + 'filename': '$TEST_IMG' + }, + 'data-file': { + 'driver': 'blkdebug', + 'image': { + 'driver': 'file', + 'filename': '$TEST_IMG.data' + } + } +}" +$QEMU_IMG convert -f $IMGFMT -O $IMGFMT -n -C "$TEST_IMG.src" "$test_img_with_blkdebug" +$QEMU_IMG compare -f $IMGFMT -F $IMGFMT "$TEST_IMG.src" "$test_img_with_blkdebug" echo echo "=== Flushing should flush the data file ===" diff --git a/tests/qemu-iotests/270 b/tests/qemu-iotests/270 index 74352342db..c37b674aa2 100755 --- a/tests/qemu-iotests/270 +++ b/tests/qemu-iotests/270 @@ -60,8 +60,16 @@ _make_test_img -o cluster_size=2M,data_file="$TEST_IMG.orig" \ # "write" 2G of data without using any space. # (qemu-img create does not like it, though, because null-co does not # support image creation.) -$QEMU_IMG amend -o data_file="json:{'driver':'null-co',,'size':'4294967296'}" \ - "$TEST_IMG" +test_img_with_null_data="json:{ + 'driver': '$IMGFMT', + 'file': { + 'filename': '$TEST_IMG' + }, + 'data-file': { + 'driver': 'null-co', + 'size':'4294967296' + } +}" # This gives us a range of: # 2^31 - 512 + 768 - 1 = 2^31 + 255 > 2^31 @@ -74,7 +82,7 @@ $QEMU_IMG amend -o data_file="json:{'driver':'null-co',,'size':'4294967296'}" \ # on L2 boundaries, we need large L2 tables; hence the cluster size of # 2 MB. (Anything from 256 kB should work, though, because then one L2 # table covers 8 GB.) -$QEMU_IO -c "write 768 $((2 ** 31 - 512))" "$TEST_IMG" | _filter_qemu_io +$QEMU_IO -c "write 768 $((2 ** 31 - 512))" "$test_img_with_null_data" | _filter_qemu_io _check_test_img diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index d1ff4db7a2..f4c4704bab 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -78,6 +78,7 @@ typedef struct { bool tcg_only; const char *machine; + const char *arch; const char *machine_param; const char *variant; const char *uefi_fl1; @@ -262,8 +263,19 @@ static void dump_aml_files(test_data *data, bool rebuild) g_assert(exp_sdt->aml); if (rebuild) { - aml_file = g_strdup_printf("%s/%s/%.4s%s", data_dir, data->machine, + aml_file = g_strdup_printf("%s/%s/%s/%.4s%s", data_dir, + data->arch, data->machine, sdt->aml, ext); + + /* + * To keep test cases not failing before the DATA files are moved to + * ${arch}/${machine} folder, add this check as well. + */ + if (!g_file_test(aml_file, G_FILE_TEST_EXISTS)) { + aml_file = g_strdup_printf("%s/%s/%.4s%s", data_dir, + data->machine, sdt->aml, ext); + } + if (!g_file_test(aml_file, G_FILE_TEST_EXISTS) && sdt->aml_len == exp_sdt->aml_len && !memcmp(sdt->aml, exp_sdt->aml, sdt->aml_len)) { @@ -398,8 +410,13 @@ static GArray *load_expected_aml(test_data *data) memset(&exp_sdt, 0, sizeof(exp_sdt)); try_again: - aml_file = g_strdup_printf("%s/%s/%.4s%s", data_dir, data->machine, - sdt->aml, ext); + aml_file = g_strdup_printf("%s/%s/%s/%.4s%s", data_dir, data->arch, + data->machine, sdt->aml, ext); + if (!g_file_test(aml_file, G_FILE_TEST_EXISTS)) { + aml_file = g_strdup_printf("%s/%s/%.4s%s", data_dir, data->machine, + sdt->aml, ext); + } + if (verbosity_level >= 2) { fprintf(stderr, "Looking for expected file '%s'\n", aml_file); } @@ -916,6 +933,7 @@ static void test_acpi_piix4_tcg(void) * This is to make guest actually run. */ data.machine = MACHINE_PC; + data.arch = "x86"; data.required_struct_types = base_required_struct_types; data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); test_acpi_one(NULL, &data); @@ -927,6 +945,7 @@ static void test_acpi_piix4_tcg_bridge(void) test_data data = {}; data.machine = MACHINE_PC; + data.arch = "x86"; data.variant = ".bridge"; data.required_struct_types = base_required_struct_types; data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); @@ -964,6 +983,7 @@ static void test_acpi_piix4_no_root_hotplug(void) test_data data = {}; data.machine = MACHINE_PC; + data.arch = "x86"; data.variant = ".roothp"; data.required_struct_types = base_required_struct_types; data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); @@ -980,6 +1000,7 @@ static void test_acpi_piix4_no_bridge_hotplug(void) test_data data = {}; data.machine = MACHINE_PC; + data.arch = "x86"; data.variant = ".hpbridge"; data.required_struct_types = base_required_struct_types; data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); @@ -996,6 +1017,7 @@ static void test_acpi_piix4_no_acpi_pci_hotplug(void) test_data data = {}; data.machine = MACHINE_PC; + data.arch = "x86"; data.variant = ".hpbrroot"; data.required_struct_types = base_required_struct_types; data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); @@ -1017,6 +1039,7 @@ static void test_acpi_q35_tcg(void) test_data data = {}; data.machine = MACHINE_Q35; + data.arch = "x86"; data.required_struct_types = base_required_struct_types; data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); test_acpi_one(NULL, &data); @@ -1032,6 +1055,7 @@ static void test_acpi_q35_kvm_type4_count(void) { test_data data = { .machine = MACHINE_Q35, + .arch = "x86", .variant = ".type4-count", .required_struct_types = base_required_struct_types, .required_struct_types_len = ARRAY_SIZE(base_required_struct_types), @@ -1048,6 +1072,7 @@ static void test_acpi_q35_kvm_core_count(void) { test_data data = { .machine = MACHINE_Q35, + .arch = "x86", .variant = ".core-count", .required_struct_types = base_required_struct_types, .required_struct_types_len = ARRAY_SIZE(base_required_struct_types), @@ -1065,6 +1090,7 @@ static void test_acpi_q35_kvm_core_count2(void) { test_data data = { .machine = MACHINE_Q35, + .arch = "x86", .variant = ".core-count2", .required_struct_types = base_required_struct_types, .required_struct_types_len = ARRAY_SIZE(base_required_struct_types), @@ -1082,6 +1108,7 @@ static void test_acpi_q35_kvm_thread_count(void) { test_data data = { .machine = MACHINE_Q35, + .arch = "x86", .variant = ".thread-count", .required_struct_types = base_required_struct_types, .required_struct_types_len = ARRAY_SIZE(base_required_struct_types), @@ -1099,6 +1126,7 @@ static void test_acpi_q35_kvm_thread_count2(void) { test_data data = { .machine = MACHINE_Q35, + .arch = "x86", .variant = ".thread-count2", .required_struct_types = base_required_struct_types, .required_struct_types_len = ARRAY_SIZE(base_required_struct_types), @@ -1117,6 +1145,7 @@ static void test_acpi_q35_tcg_bridge(void) test_data data = {}; data.machine = MACHINE_Q35; + data.arch = "x86", data.variant = ".bridge"; data.required_struct_types = base_required_struct_types; data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); @@ -1131,6 +1160,7 @@ static void test_acpi_q35_tcg_no_acpi_hotplug(void) test_data data = {}; data.machine = MACHINE_Q35; + data.arch = "x86", data.variant = ".noacpihp"; data.required_struct_types = base_required_struct_types; data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); @@ -1159,6 +1189,7 @@ static void test_acpi_q35_multif_bridge(void) { test_data data = { .machine = MACHINE_Q35, + .arch = "x86", .variant = ".multi-bridge", }; test_vm_prepare("-S" @@ -1208,6 +1239,7 @@ static void test_acpi_q35_tcg_mmio64(void) { test_data data = { .machine = MACHINE_Q35, + .arch = "x86", .variant = ".mmio64", .tcg_only = true, .required_struct_types = base_required_struct_types, @@ -1228,6 +1260,7 @@ static void test_acpi_piix4_tcg_cphp(void) test_data data = {}; data.machine = MACHINE_PC; + data.arch = "x86"; data.variant = ".cphp"; test_acpi_one("-smp 2,cores=3,sockets=2,maxcpus=6" " -object memory-backend-ram,id=ram0,size=64M" @@ -1243,6 +1276,7 @@ static void test_acpi_q35_tcg_cphp(void) test_data data = {}; data.machine = MACHINE_Q35; + data.arch = "x86", data.variant = ".cphp"; test_acpi_one(" -smp 2,cores=3,sockets=2,maxcpus=6" " -object memory-backend-ram,id=ram0,size=64M" @@ -1262,6 +1296,7 @@ static void test_acpi_q35_tcg_ipmi(void) test_data data = {}; data.machine = MACHINE_Q35; + data.arch = "x86", data.variant = ".ipmibt"; data.required_struct_types = ipmi_required_struct_types; data.required_struct_types_len = ARRAY_SIZE(ipmi_required_struct_types); @@ -1276,6 +1311,7 @@ static void test_acpi_q35_tcg_smbus_ipmi(void) test_data data = {}; data.machine = MACHINE_Q35; + data.arch = "x86", data.variant = ".ipmismbus"; data.required_struct_types = ipmi_required_struct_types; data.required_struct_types_len = ARRAY_SIZE(ipmi_required_struct_types); @@ -1293,6 +1329,7 @@ static void test_acpi_piix4_tcg_ipmi(void) * This is to make guest actually run. */ data.machine = MACHINE_PC; + data.arch = "x86"; data.variant = ".ipmikcs"; data.required_struct_types = ipmi_required_struct_types; data.required_struct_types_len = ARRAY_SIZE(ipmi_required_struct_types); @@ -1307,6 +1344,7 @@ static void test_acpi_q35_tcg_memhp(void) test_data data = {}; data.machine = MACHINE_Q35; + data.arch = "x86", data.variant = ".memhp"; test_acpi_one(" -m 128,slots=3,maxmem=1G" " -object memory-backend-ram,id=ram0,size=64M" @@ -1322,6 +1360,7 @@ static void test_acpi_piix4_tcg_memhp(void) test_data data = {}; data.machine = MACHINE_PC; + data.arch = "x86"; data.variant = ".memhp"; test_acpi_one(" -m 128,slots=3,maxmem=1G" " -object memory-backend-ram,id=ram0,size=64M" @@ -1337,6 +1376,7 @@ static void test_acpi_piix4_tcg_nosmm(void) test_data data = {}; data.machine = MACHINE_PC; + data.arch = "x86"; data.variant = ".nosmm"; test_acpi_one("-machine smm=off", &data); free_test_data(&data); @@ -1347,6 +1387,7 @@ static void test_acpi_piix4_tcg_smm_compat(void) test_data data = {}; data.machine = MACHINE_PC; + data.arch = "x86"; data.variant = ".smm-compat"; test_acpi_one("-global PIIX4_PM.smm-compat=on", &data); free_test_data(&data); @@ -1357,6 +1398,7 @@ static void test_acpi_piix4_tcg_smm_compat_nosmm(void) test_data data = {}; data.machine = MACHINE_PC; + data.arch = "x86"; data.variant = ".smm-compat-nosmm"; test_acpi_one("-global PIIX4_PM.smm-compat=on -machine smm=off", &data); free_test_data(&data); @@ -1367,6 +1409,7 @@ static void test_acpi_piix4_tcg_nohpet(void) test_data data = {}; data.machine = MACHINE_PC; + data.arch = "x86"; data.machine_param = ",hpet=off"; data.variant = ".nohpet"; test_acpi_one(NULL, &data); @@ -1378,6 +1421,7 @@ static void test_acpi_q35_tcg_numamem(void) test_data data = {}; data.machine = MACHINE_Q35; + data.arch = "x86", data.variant = ".numamem"; test_acpi_one(" -object memory-backend-ram,id=ram0,size=128M" " -numa node -numa node,memdev=ram0", &data); @@ -1389,6 +1433,7 @@ static void test_acpi_q35_kvm_xapic(void) test_data data = {}; data.machine = MACHINE_Q35; + data.arch = "x86", data.variant = ".xapic"; test_acpi_one(" -object memory-backend-ram,id=ram0,size=128M" " -numa node -numa node,memdev=ram0" @@ -1401,6 +1446,7 @@ static void test_acpi_q35_tcg_nosmm(void) test_data data = {}; data.machine = MACHINE_Q35; + data.arch = "x86", data.variant = ".nosmm"; test_acpi_one("-machine smm=off", &data); free_test_data(&data); @@ -1411,6 +1457,7 @@ static void test_acpi_q35_tcg_smm_compat(void) test_data data = {}; data.machine = MACHINE_Q35; + data.arch = "x86", data.variant = ".smm-compat"; test_acpi_one("-global ICH9-LPC.smm-compat=on", &data); free_test_data(&data); @@ -1421,6 +1468,7 @@ static void test_acpi_q35_tcg_smm_compat_nosmm(void) test_data data = {}; data.machine = MACHINE_Q35; + data.arch = "x86", data.variant = ".smm-compat-nosmm"; test_acpi_one("-global ICH9-LPC.smm-compat=on -machine smm=off", &data); free_test_data(&data); @@ -1431,6 +1479,7 @@ static void test_acpi_q35_tcg_nohpet(void) test_data data = {}; data.machine = MACHINE_Q35; + data.arch = "x86", data.machine_param = ",hpet=off"; data.variant = ".nohpet"; test_acpi_one(NULL, &data); @@ -1442,6 +1491,7 @@ static void test_acpi_q35_kvm_dmar(void) test_data data = {}; data.machine = MACHINE_Q35; + data.arch = "x86", data.variant = ".dmar"; test_acpi_one("-machine kernel-irqchip=split -accel kvm" " -device intel-iommu,intremap=on,device-iotlb=on", &data); @@ -1453,6 +1503,7 @@ static void test_acpi_q35_tcg_ivrs(void) test_data data = {}; data.machine = MACHINE_Q35; + data.arch = "x86", data.variant = ".ivrs"; data.tcg_only = true, test_acpi_one(" -device amd-iommu", &data); @@ -1464,6 +1515,7 @@ static void test_acpi_piix4_tcg_numamem(void) test_data data = {}; data.machine = MACHINE_PC; + data.arch = "x86"; data.variant = ".numamem"; test_acpi_one(" -object memory-backend-ram,id=ram0,size=128M" " -numa node -numa node,memdev=ram0", &data); @@ -1472,8 +1524,9 @@ static void test_acpi_piix4_tcg_numamem(void) uint64_t tpm_tis_base_addr; -static void test_acpi_tcg_tpm(const char *machine, const char *tpm_if, - uint64_t base, enum TPMVersion tpm_version) +static void test_acpi_tcg_tpm(const char *machine, const char *arch, + const char *tpm_if, uint64_t base, + enum TPMVersion tpm_version) { gchar *tmp_dir_name = g_strdup_printf("qemu-test_acpi_%s_tcg_%s.XXXXXX", machine, tpm_if); @@ -1500,6 +1553,7 @@ static void test_acpi_tcg_tpm(const char *machine, const char *tpm_if, tpm_emu_test_wait_cond(&test); data.machine = machine; + data.arch = arch; data.variant = variant; args = g_strdup_printf( @@ -1523,19 +1577,20 @@ static void test_acpi_tcg_tpm(const char *machine, const char *tpm_if, static void test_acpi_q35_tcg_tpm2_tis(void) { - test_acpi_tcg_tpm("q35", "tis", 0xFED40000, TPM_VERSION_2_0); + test_acpi_tcg_tpm("q35", "x86", "tis", 0xFED40000, TPM_VERSION_2_0); } static void test_acpi_q35_tcg_tpm12_tis(void) { - test_acpi_tcg_tpm("q35", "tis", 0xFED40000, TPM_VERSION_1_2); + test_acpi_tcg_tpm("q35", "x86", "tis", 0xFED40000, TPM_VERSION_1_2); } -static void test_acpi_tcg_dimm_pxm(const char *machine) +static void test_acpi_tcg_dimm_pxm(const char *machine, const char *arch) { test_data data = {}; data.machine = machine; + data.arch = arch; data.variant = ".dimmpxm"; test_acpi_one(" -machine nvdimm=on,nvdimm-persistence=cpu" " -smp 4,sockets=4" @@ -1562,18 +1617,19 @@ static void test_acpi_tcg_dimm_pxm(const char *machine) static void test_acpi_q35_tcg_dimm_pxm(void) { - test_acpi_tcg_dimm_pxm(MACHINE_Q35); + test_acpi_tcg_dimm_pxm(MACHINE_Q35, "x86"); } static void test_acpi_piix4_tcg_dimm_pxm(void) { - test_acpi_tcg_dimm_pxm(MACHINE_PC); + test_acpi_tcg_dimm_pxm(MACHINE_PC, "x86"); } -static void test_acpi_virt_tcg_memhp(void) +static void test_acpi_aarch64_virt_tcg_memhp(void) { test_data data = { .machine = "virt", + .arch = "aarch64", .tcg_only = true, .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", @@ -1603,6 +1659,7 @@ static void test_acpi_virt_tcg_memhp(void) static void test_acpi_microvm_prepare(test_data *data) { data->machine = "microvm"; + data->arch = "x86"; data->required_struct_types = NULL; /* no smbios */ data->required_struct_types_len = 0; data->blkdev = "virtio-blk-device"; @@ -1663,10 +1720,11 @@ static void test_acpi_microvm_ioapic2_tcg(void) free_test_data(&data); } -static void test_acpi_virt_tcg_numamem(void) +static void test_acpi_aarch64_virt_tcg_numamem(void) { test_data data = { .machine = "virt", + .arch = "aarch64", .tcg_only = true, .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", @@ -1685,10 +1743,11 @@ static void test_acpi_virt_tcg_numamem(void) } -static void test_acpi_virt_tcg_pxb(void) +static void test_acpi_aarch64_virt_tcg_pxb(void) { test_data data = { .machine = "virt", + .arch = "aarch64", .tcg_only = true, .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", @@ -1717,11 +1776,12 @@ static void test_acpi_virt_tcg_pxb(void) free_test_data(&data); } -static void test_acpi_tcg_acpi_hmat(const char *machine) +static void test_acpi_tcg_acpi_hmat(const char *machine, const char *arch) { test_data data = {}; data.machine = machine; + data.arch = arch; data.variant = ".acpihmat"; test_acpi_one(" -machine hmat=on" " -smp 2,sockets=2" @@ -1750,18 +1810,19 @@ static void test_acpi_tcg_acpi_hmat(const char *machine) static void test_acpi_q35_tcg_acpi_hmat(void) { - test_acpi_tcg_acpi_hmat(MACHINE_Q35); + test_acpi_tcg_acpi_hmat(MACHINE_Q35, "x86"); } static void test_acpi_piix4_tcg_acpi_hmat(void) { - test_acpi_tcg_acpi_hmat(MACHINE_PC); + test_acpi_tcg_acpi_hmat(MACHINE_PC, "x86"); } -static void test_acpi_virt_tcg_acpi_hmat(void) +static void test_acpi_aarch64_virt_tcg_acpi_hmat(void) { test_data data = { .machine = "virt", + .arch = "aarch64", .tcg_only = true, .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", @@ -1820,6 +1881,7 @@ static void test_acpi_q35_tcg_acpi_hmat_noinitiator(void) test_data data = {}; data.machine = MACHINE_Q35; + data.arch = "x86"; data.variant = ".acpihmat-noinitiator"; test_acpi_one(" -machine hmat=on" " -smp 4,sockets=2" @@ -1863,13 +1925,14 @@ static void test_acpi_q35_tcg_acpi_hmat_noinitiator(void) } #ifdef CONFIG_POSIX -static void test_acpi_erst(const char *machine) +static void test_acpi_erst(const char *machine, const char *arch) { gchar *tmp_path = g_dir_make_tmp("qemu-test-erst.XXXXXX", NULL); gchar *params; test_data data = {}; data.machine = machine; + data.arch = arch; data.variant = ".acpierst"; params = g_strdup_printf( " -object memory-backend-file,id=erstnvram," @@ -1884,12 +1947,12 @@ static void test_acpi_erst(const char *machine) static void test_acpi_piix4_acpi_erst(void) { - test_acpi_erst(MACHINE_PC); + test_acpi_erst(MACHINE_PC, "x86"); } static void test_acpi_q35_acpi_erst(void) { - test_acpi_erst(MACHINE_Q35); + test_acpi_erst(MACHINE_Q35, "x86"); } static void test_acpi_microvm_acpi_erst(void) @@ -1914,10 +1977,11 @@ static void test_acpi_microvm_acpi_erst(void) } #endif /* CONFIG_POSIX */ -static void test_acpi_virt_tcg(void) +static void test_acpi_aarch64_virt_tcg(void) { test_data data = { .machine = "virt", + .arch = "aarch64", .tcg_only = true, .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", @@ -1933,10 +1997,11 @@ static void test_acpi_virt_tcg(void) free_test_data(&data); } -static void test_acpi_virt_tcg_topology(void) +static void test_acpi_aarch64_virt_tcg_topology(void) { test_data data = { .machine = "virt", + .arch = "aarch64", .variant = ".topology", .tcg_only = true, .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", @@ -1955,6 +2020,7 @@ static void test_acpi_q35_viot(void) { test_data data = { .machine = MACHINE_Q35, + .arch = "x86", .variant = ".viot", }; @@ -1979,6 +2045,7 @@ static void test_acpi_q35_cxl(void) test_data data = { .machine = MACHINE_Q35, + .arch = "x86", .variant = ".cxl", }; /* @@ -2016,10 +2083,11 @@ static void test_acpi_q35_cxl(void) } #endif /* CONFIG_POSIX */ -static void test_acpi_virt_viot(void) +static void test_acpi_aarch64_virt_viot(void) { test_data data = { .machine = "virt", + .arch = "aarch64", .tcg_only = true, .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", @@ -2043,6 +2111,7 @@ static void test_acpi_q35_slic(void) { test_data data = { .machine = MACHINE_Q35, + .arch = "x86", .variant = ".slic", }; @@ -2057,6 +2126,7 @@ static void test_acpi_q35_applesmc(void) { test_data data = { .machine = MACHINE_Q35, + .arch = "x86", .variant = ".applesmc", }; @@ -2070,6 +2140,7 @@ static void test_acpi_q35_pvpanic_isa(void) { test_data data = { .machine = MACHINE_Q35, + .arch = "x86", .variant = ".pvpanic-isa", }; @@ -2082,6 +2153,7 @@ static void test_acpi_pc_smbios_options(void) uint8_t req_type11[] = { 11 }; test_data data = { .machine = MACHINE_PC, + .arch = "x86", .variant = ".pc_smbios_options", .required_struct_types = req_type11, .required_struct_types_len = ARRAY_SIZE(req_type11), @@ -2096,6 +2168,7 @@ static void test_acpi_pc_smbios_blob(void) uint8_t req_type11[] = { 11 }; test_data data = { .machine = MACHINE_PC, + .arch = "x86", .variant = ".pc_smbios_blob", .required_struct_types = req_type11, .required_struct_types_len = ARRAY_SIZE(req_type11), @@ -2145,6 +2218,7 @@ static void test_acpi_piix4_oem_fields(void) test_data data = {}; data.machine = MACHINE_PC; + data.arch = "x86"; data.required_struct_types = base_required_struct_types; data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); @@ -2163,6 +2237,7 @@ static void test_acpi_q35_oem_fields(void) test_data data = {}; data.machine = MACHINE_Q35; + data.arch = "x86"; data.required_struct_types = base_required_struct_types; data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); @@ -2192,10 +2267,11 @@ static void test_acpi_microvm_oem_fields(void) g_free(args); } -static void test_acpi_virt_oem_fields(void) +static void test_acpi_aarch64_virt_oem_fields(void) { test_data data = { .machine = "virt", + .arch = "aarch64", .tcg_only = true, .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", @@ -2364,16 +2440,19 @@ int main(int argc, char *argv[]) } } else if (strcmp(arch, "aarch64") == 0) { if (has_tcg && qtest_has_device("virtio-blk-pci")) { - qtest_add_func("acpi/virt", test_acpi_virt_tcg); + qtest_add_func("acpi/virt", test_acpi_aarch64_virt_tcg); qtest_add_func("acpi/virt/acpihmatvirt", - test_acpi_virt_tcg_acpi_hmat); - qtest_add_func("acpi/virt/topology", test_acpi_virt_tcg_topology); - qtest_add_func("acpi/virt/numamem", test_acpi_virt_tcg_numamem); - qtest_add_func("acpi/virt/memhp", test_acpi_virt_tcg_memhp); - qtest_add_func("acpi/virt/pxb", test_acpi_virt_tcg_pxb); - qtest_add_func("acpi/virt/oem-fields", test_acpi_virt_oem_fields); + test_acpi_aarch64_virt_tcg_acpi_hmat); + qtest_add_func("acpi/virt/topology", + test_acpi_aarch64_virt_tcg_topology); + qtest_add_func("acpi/virt/numamem", + test_acpi_aarch64_virt_tcg_numamem); + qtest_add_func("acpi/virt/memhp", test_acpi_aarch64_virt_tcg_memhp); + qtest_add_func("acpi/virt/pxb", test_acpi_aarch64_virt_tcg_pxb); + qtest_add_func("acpi/virt/oem-fields", + test_acpi_aarch64_virt_oem_fields); if (qtest_has_device("virtio-iommu-pci")) { - qtest_add_func("acpi/virt/viot", test_acpi_virt_viot); + qtest_add_func("acpi/virt/viot", test_acpi_aarch64_virt_viot); } } } diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 12792948ff..6508bfb1a2 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -259,6 +259,9 @@ qtests_s390x = \ qtests_riscv32 = \ (config_all_devices.has_key('CONFIG_SIFIVE_E_AON') ? ['sifive-e-aon-watchdog-test'] : []) +qtests_riscv64 = \ + (unpack_edk2_blobs ? ['bios-tables-test'] : []) + qos_test_ss = ss.source_set() qos_test_ss.add( 'ac97-test.c', diff --git a/tests/qtest/pvpanic-pci-test.c b/tests/qtest/pvpanic-pci-test.c index 2c05b376ba..dc021c2fdf 100644 --- a/tests/qtest/pvpanic-pci-test.c +++ b/tests/qtest/pvpanic-pci-test.c @@ -16,6 +16,7 @@ #include "qapi/qmp/qdict.h" #include "libqos/pci.h" #include "libqos/pci-pc.h" +#include "hw/misc/pvpanic.h" #include "hw/pci/pci_regs.h" static void test_panic_nopause(void) @@ -34,7 +35,7 @@ static void test_panic_nopause(void) bar = qpci_iomap(dev, 0, NULL); qpci_memread(dev, bar, 0, &val, sizeof(val)); - g_assert_cmpuint(val, ==, 3); + g_assert_cmpuint(val, ==, PVPANIC_EVENTS); val = 1; qpci_memwrite(dev, bar, 0, &val, sizeof(val)); @@ -67,7 +68,7 @@ static void test_panic(void) bar = qpci_iomap(dev, 0, NULL); qpci_memread(dev, bar, 0, &val, sizeof(val)); - g_assert_cmpuint(val, ==, 3); + g_assert_cmpuint(val, ==, PVPANIC_EVENTS); val = 1; qpci_memwrite(dev, bar, 0, &val, sizeof(val)); @@ -84,11 +85,50 @@ static void test_panic(void) qtest_quit(qts); } +static void test_pvshutdown(void) +{ + uint8_t val; + QDict *response, *data; + QTestState *qts; + QPCIBus *pcibus; + QPCIDevice *dev; + QPCIBar bar; + + qts = qtest_init("-device pvpanic-pci,addr=04.0"); + pcibus = qpci_new_pc(qts, NULL); + dev = qpci_device_find(pcibus, QPCI_DEVFN(0x4, 0x0)); + qpci_device_enable(dev); + bar = qpci_iomap(dev, 0, NULL); + + qpci_memread(dev, bar, 0, &val, sizeof(val)); + g_assert_cmpuint(val, ==, PVPANIC_EVENTS); + + val = PVPANIC_SHUTDOWN; + qpci_memwrite(dev, bar, 0, &val, sizeof(val)); + + response = qtest_qmp_eventwait_ref(qts, "GUEST_PVSHUTDOWN"); + qobject_unref(response); + + response = qtest_qmp_eventwait_ref(qts, "SHUTDOWN"); + g_assert(qdict_haskey(response, "data")); + data = qdict_get_qdict(response, "data"); + g_assert(qdict_haskey(data, "guest")); + g_assert(qdict_get_bool(data, "guest")); + g_assert(qdict_haskey(data, "reason")); + g_assert_cmpstr(qdict_get_str(data, "reason"), ==, "guest-shutdown"); + qobject_unref(response); + + g_free(dev); + qpci_free_pc(pcibus); + qtest_quit(qts); +} + int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); qtest_add_func("/pvpanic-pci/panic", test_panic); qtest_add_func("/pvpanic-pci/panic-nopause", test_panic_nopause); + qtest_add_func("/pvpanic-pci/pvshutdown", test_pvshutdown); return g_test_run(); } diff --git a/tests/qtest/pvpanic-test.c b/tests/qtest/pvpanic-test.c index 78f1cf8186..d49d2ba931 100644 --- a/tests/qtest/pvpanic-test.c +++ b/tests/qtest/pvpanic-test.c @@ -10,6 +10,7 @@ #include "qemu/osdep.h" #include "libqtest.h" #include "qapi/qmp/qdict.h" +#include "hw/misc/pvpanic.h" static void test_panic_nopause(void) { @@ -20,7 +21,7 @@ static void test_panic_nopause(void) qts = qtest_init("-device pvpanic -action panic=none"); val = qtest_inb(qts, 0x505); - g_assert_cmpuint(val, ==, 3); + g_assert_cmpuint(val, ==, PVPANIC_EVENTS); qtest_outb(qts, 0x505, 0x1); @@ -43,7 +44,7 @@ static void test_panic(void) qts = qtest_init("-device pvpanic -action panic=pause"); val = qtest_inb(qts, 0x505); - g_assert_cmpuint(val, ==, 3); + g_assert_cmpuint(val, ==, PVPANIC_EVENTS); qtest_outb(qts, 0x505, 0x1); @@ -57,11 +58,40 @@ static void test_panic(void) qtest_quit(qts); } +static void test_pvshutdown(void) +{ + uint8_t val; + QDict *response, *data; + QTestState *qts; + + qts = qtest_init("-device pvpanic"); + + val = qtest_inb(qts, 0x505); + g_assert_cmpuint(val, ==, PVPANIC_EVENTS); + + qtest_outb(qts, 0x505, PVPANIC_SHUTDOWN); + + response = qtest_qmp_eventwait_ref(qts, "GUEST_PVSHUTDOWN"); + qobject_unref(response); + + response = qtest_qmp_eventwait_ref(qts, "SHUTDOWN"); + g_assert(qdict_haskey(response, "data")); + data = qdict_get_qdict(response, "data"); + g_assert(qdict_haskey(data, "guest")); + g_assert(qdict_get_bool(data, "guest")); + g_assert(qdict_haskey(data, "reason")); + g_assert_cmpstr(qdict_get_str(data, "reason"), ==, "guest-shutdown"); + qobject_unref(response); + + qtest_quit(qts); +} + int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); qtest_add_func("/pvpanic/panic", test_panic); qtest_add_func("/pvpanic/panic-nopause", test_panic_nopause); + qtest_add_func("/pvpanic/pvshutdown", test_pvshutdown); return g_test_run(); } diff --git a/tests/qtest/vhost-user-blk-test.c b/tests/qtest/vhost-user-blk-test.c index 117b9acd10..ea90d41232 100644 --- a/tests/qtest/vhost-user-blk-test.c +++ b/tests/qtest/vhost-user-blk-test.c @@ -906,7 +906,7 @@ static void start_vhost_user_blk(GString *cmd_line, int vus_instances, vhost_user_blk_bin); g_string_append_printf(cmd_line, - " -object memory-backend-memfd,id=mem,size=256M,share=on " + " -object memory-backend-shm,id=mem,size=256M " " -M memory-backend=mem -m 256M "); for (i = 0; i < vus_instances; i++) { diff --git a/tests/qtest/vhost-user-test.c b/tests/qtest/vhost-user-test.c index 929af5c183..d6075001e7 100644 --- a/tests/qtest/vhost-user-test.c +++ b/tests/qtest/vhost-user-test.c @@ -44,6 +44,8 @@ "mem-path=%s,share=on -numa node,memdev=mem" #define QEMU_CMD_MEMFD " -m %d -object memory-backend-memfd,id=mem,size=%dM," \ " -numa node,memdev=mem" +#define QEMU_CMD_SHM " -m %d -object memory-backend-shm,id=mem,size=%dM," \ + " -numa node,memdev=mem" #define QEMU_CMD_CHR " -chardev socket,id=%s,path=%s%s" #define QEMU_CMD_NETDEV " -netdev vhost-user,id=hs0,chardev=%s,vhostforce=on" @@ -195,6 +197,7 @@ enum test_memfd { TEST_MEMFD_AUTO, TEST_MEMFD_YES, TEST_MEMFD_NO, + TEST_MEMFD_SHM, }; static void append_vhost_net_opts(TestServer *s, GString *cmd_line, @@ -228,6 +231,8 @@ static void append_mem_opts(TestServer *server, GString *cmd_line, if (memfd == TEST_MEMFD_YES) { g_string_append_printf(cmd_line, QEMU_CMD_MEMFD, size, size); + } else if (memfd == TEST_MEMFD_SHM) { + g_string_append_printf(cmd_line, QEMU_CMD_SHM, size, size); } else { const char *root = init_hugepagefs() ? : server->tmpfs; @@ -458,7 +463,10 @@ static void chr_read(void *opaque, const uint8_t *buf, int size) case VHOST_USER_SET_VRING_KICK: case VHOST_USER_SET_VRING_CALL: /* consume the fd */ - qemu_chr_fe_get_msgfds(chr, &fd, 1); + if (!qemu_chr_fe_get_msgfds(chr, &fd, 1) && fd < 0) { + qos_printf("call fd: %d, do not set non-blocking\n", fd); + break; + } /* * This is a non-blocking eventfd. * The receive function forces it to be blocking, @@ -788,6 +796,19 @@ static void *vhost_user_test_setup_memfd(GString *cmd_line, void *arg) return server; } +static void *vhost_user_test_setup_shm(GString *cmd_line, void *arg) +{ + TestServer *server = test_server_new("vhost-user-test", arg); + test_server_listen(server); + + append_mem_opts(server, cmd_line, 256, TEST_MEMFD_SHM); + server->vu_ops->append_opts(server, cmd_line, ""); + + g_test_queue_destroy(vhost_user_test_cleanup, server); + + return server; +} + static void test_read_guest_mem(void *obj, void *arg, QGuestAllocator *alloc) { TestServer *server = arg; @@ -1081,6 +1102,11 @@ static void register_vhost_user_test(void) "virtio-net", test_read_guest_mem, &opts); + opts.before = vhost_user_test_setup_shm; + qos_add_test("vhost-user/read-guest-mem/shm", + "virtio-net", + test_read_guest_mem, &opts); + if (qemu_memfd_check(MFD_ALLOW_SEALING)) { opts.before = vhost_user_test_setup_memfd; qos_add_test("vhost-user/read-guest-mem/memfd", diff --git a/tests/tcg/x86_64/Makefile.target b/tests/tcg/x86_64/Makefile.target index 5fedf22117..eda9bd7396 100644 --- a/tests/tcg/x86_64/Makefile.target +++ b/tests/tcg/x86_64/Makefile.target @@ -8,6 +8,8 @@ include $(SRC_PATH)/tests/tcg/i386/Makefile.target +X86_64_TESTS += test-2413 + ifeq ($(filter %-linux-user, $(TARGET)),$(TARGET)) X86_64_TESTS += vsyscall X86_64_TESTS += noexec diff --git a/tests/tcg/x86_64/test-2413.c b/tests/tcg/x86_64/test-2413.c new file mode 100644 index 0000000000..456e5332fc --- /dev/null +++ b/tests/tcg/x86_64/test-2413.c @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* Copyright 2024 Linaro, Ltd. */ +/* See https://gitlab.com/qemu-project/qemu/-/issues/2413 */ + +#include <assert.h> + +void test(unsigned long *a, unsigned long *d, unsigned long c) +{ + asm("xorl %%eax, %%eax\n\t" + "xorl %%edx, %%edx\n\t" + "testb $0x20, %%cl\n\t" + "sete %%al\n\t" + "setne %%dl\n\t" + "shll %%cl, %%eax\n\t" + "shll %%cl, %%edx\n\t" + : "=a"(*a), "=d"(*d) + : "c"(c)); +} + +int main(void) +{ + unsigned long a, c, d; + + for (c = 0; c < 64; c++) { + test(&a, &d, c); + assert(a == (c & 0x20 ? 0 : 1u << (c & 0x1f))); + assert(d == (c & 0x20 ? 1u << (c & 0x1f) : 0)); + } + return 0; +} diff --git a/tests/uefi-test-tools/Makefile b/tests/uefi-test-tools/Makefile index 0c003f2877..f4eaebd8ff 100644 --- a/tests/uefi-test-tools/Makefile +++ b/tests/uefi-test-tools/Makefile @@ -12,7 +12,7 @@ edk2_dir := ../../roms/edk2 images_dir := ../data/uefi-boot-images -emulation_targets := arm aarch64 i386 x86_64 +emulation_targets := arm aarch64 i386 x86_64 riscv64 uefi_binaries := bios-tables-test intermediate_suffixes := .efi .fat .iso.raw @@ -56,7 +56,8 @@ Build/%.iso.raw: Build/%.fat # stripped from, the argument. map_arm_to_uefi = $(subst arm,ARM,$(1)) map_aarch64_to_uefi = $(subst aarch64,AA64,$(call map_arm_to_uefi,$(1))) -map_i386_to_uefi = $(subst i386,IA32,$(call map_aarch64_to_uefi,$(1))) +map_riscv64_to_uefi = $(subst riscv64,RISCV64,$(call map_aarch64_to_uefi,$(1))) +map_i386_to_uefi = $(subst i386,IA32,$(call map_riscv64_to_uefi,$(1))) map_x86_64_to_uefi = $(subst x86_64,X64,$(call map_i386_to_uefi,$(1))) map_to_uefi = $(subst .,,$(call map_x86_64_to_uefi,$(1))) @@ -70,7 +71,7 @@ Build/%.fat: Build/%.efi uefi_bin_b=$$(stat --format=%s -- $<) && \ uefi_fat_kb=$$(( (uefi_bin_b * 11 / 10 + 1023) / 1024 )) && \ uefi_fat_kb=$$(( uefi_fat_kb >= 64 ? uefi_fat_kb : 64 )) && \ - mkdosfs -C $@ -n $(basename $(@F)) -- $$uefi_fat_kb + mkdosfs -C $@ -n "bios-test" -- $$uefi_fat_kb MTOOLS_SKIP_CHECK=1 mmd -i $@ ::EFI MTOOLS_SKIP_CHECK=1 mmd -i $@ ::EFI/BOOT MTOOLS_SKIP_CHECK=1 mcopy -i $@ -- $< \ @@ -95,15 +96,9 @@ Build/%.fat: Build/%.efi # we must mark the recipe manually as recursive, by using the "+" indicator. # This way, when the inner "make" starts a parallel build of the target edk2 # module, it can communicate with the outer "make"'s job server. -Build/bios-tables-test.%.efi: build-edk2-tools - +./build.sh $(edk2_dir) BiosTablesTest $* $@ - -build-edk2-tools: - cd $(edk2_dir)/BaseTools && git submodule update --init --force - $(MAKE) -C $(edk2_dir)/BaseTools \ - PYTHON_COMMAND=$${EDK2_PYTHON_COMMAND:-python3} \ - EXTRA_OPTFLAGS='$(EDK2_BASETOOLS_OPTFLAGS)' \ - EXTRA_LDFLAGS='$(EDK2_BASETOOLS_LDFLAGS)' +Build/bios-tables-test.%.efi: + $(PYTHON) ../../roms/edk2-build.py --config uefi-test-build.config \ + --match $* clean: rm -rf Build Conf log diff --git a/tests/uefi-test-tools/UefiTestToolsPkg/UefiTestToolsPkg.dsc b/tests/uefi-test-tools/UefiTestToolsPkg/UefiTestToolsPkg.dsc index c8511cd732..0902fd3c73 100644 --- a/tests/uefi-test-tools/UefiTestToolsPkg/UefiTestToolsPkg.dsc +++ b/tests/uefi-test-tools/UefiTestToolsPkg/UefiTestToolsPkg.dsc @@ -19,7 +19,7 @@ PLATFORM_VERSION = 0.1 PLATFORM_NAME = UefiTestTools SKUID_IDENTIFIER = DEFAULT - SUPPORTED_ARCHITECTURES = ARM|AARCH64|IA32|X64 + SUPPORTED_ARCHITECTURES = ARM|AARCH64|IA32|X64|RISCV64 BUILD_TARGETS = DEBUG [BuildOptions.IA32] @@ -60,6 +60,10 @@ [LibraryClasses.IA32, LibraryClasses.X64] BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf + RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf + +[LibraryClasses.RISCV64] + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf [PcdsFixedAtBuild] gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8040004F diff --git a/tests/uefi-test-tools/uefi-test-build.config b/tests/uefi-test-tools/uefi-test-build.config new file mode 100644 index 0000000000..a4c61fc97a --- /dev/null +++ b/tests/uefi-test-tools/uefi-test-build.config @@ -0,0 +1,52 @@ +[global] +core = ../../roms/edk2 + +#################################################################################### +# arm + +[build.arm] +conf = UefiTestToolsPkg/UefiTestToolsPkg.dsc +plat = UefiTestTools +dest = ./Build +arch = ARM +cpy1 = ARM/BiosTablesTest.efi bios-tables-test.arm.efi + +#################################################################################### +# aarch64 + +[build.aarch64] +conf = UefiTestToolsPkg/UefiTestToolsPkg.dsc +plat = UefiTestTools +dest = ./Build +arch = AARCH64 +cpy1 = AARCH64/BiosTablesTest.efi bios-tables-test.aarch64.efi + +#################################################################################### +# riscv64 + +[build.riscv64] +conf = UefiTestToolsPkg/UefiTestToolsPkg.dsc +plat = UefiTestTools +dest = ./Build +arch = RISCV64 +cpy1 = RISCV64/BiosTablesTest.efi bios-tables-test.riscv64.efi + +#################################################################################### +# ia32 + +[build.ia32] +conf = UefiTestToolsPkg/UefiTestToolsPkg.dsc +plat = UefiTestTools +dest = ./Build +arch = IA32 +cpy1 = IA32/BiosTablesTest.efi bios-tables-test.i386.efi + +#################################################################################### +# x64 + +[build.x64] +conf = UefiTestToolsPkg/UefiTestToolsPkg.dsc +plat = UefiTestTools +dest = ./Build +arch = X64 +cpy1 = X64/BiosTablesTest.efi bios-tables-test.x86_64.efi diff --git a/util/cpuinfo-aarch64.c b/util/cpuinfo-aarch64.c index 4c8a005715..8ca775a14b 100644 --- a/util/cpuinfo-aarch64.c +++ b/util/cpuinfo-aarch64.c @@ -20,6 +20,12 @@ #ifdef CONFIG_DARWIN # include <sys/sysctl.h> #endif +#ifdef __OpenBSD__ +# include <machine/armreg.h> +# include <machine/cpu.h> +# include <sys/types.h> +# include <sys/sysctl.h> +#endif unsigned cpuinfo; @@ -72,6 +78,36 @@ unsigned __attribute__((constructor)) cpuinfo_init(void) info |= sysctl_for_bool("hw.optional.arm.FEAT_PMULL") * CPUINFO_PMULL; info |= sysctl_for_bool("hw.optional.arm.FEAT_BTI") * CPUINFO_BTI; #endif +#ifdef __OpenBSD__ + int mib[2]; + uint64_t isar0; + uint64_t pfr1; + size_t len; + + mib[0] = CTL_MACHDEP; + mib[1] = CPU_ID_AA64ISAR0; + len = sizeof(isar0); + if (sysctl(mib, 2, &isar0, &len, NULL, 0) != -1) { + if (ID_AA64ISAR0_ATOMIC(isar0) >= ID_AA64ISAR0_ATOMIC_IMPL) { + info |= CPUINFO_LSE; + } + if (ID_AA64ISAR0_AES(isar0) >= ID_AA64ISAR0_AES_BASE) { + info |= CPUINFO_AES; + } + if (ID_AA64ISAR0_AES(isar0) >= ID_AA64ISAR0_AES_PMULL) { + info |= CPUINFO_PMULL; + } + } + + mib[0] = CTL_MACHDEP; + mib[1] = CPU_ID_AA64PFR1; + len = sizeof(pfr1); + if (sysctl(mib, 2, &pfr1, &len, NULL, 0) != -1) { + if (ID_AA64PFR1_BT(pfr1) >= ID_AA64PFR1_BT_IMPL) { + info |= CPUINFO_BTI; + } + } +#endif cpuinfo = info; return info; diff --git a/util/cpuinfo-ppc.c b/util/cpuinfo-ppc.c index b2d8893a06..1304f9aa80 100644 --- a/util/cpuinfo-ppc.c +++ b/util/cpuinfo-ppc.c @@ -6,11 +6,20 @@ #include "qemu/osdep.h" #include "host/cpuinfo.h" -#include <asm/cputable.h> -#ifdef CONFIG_GETAUXVAL -# include <sys/auxv.h> -#else -# include "elf.h" +#ifdef CONFIG_LINUX +# include <asm/cputable.h> +# ifdef CONFIG_GETAUXVAL +# include <sys/auxv.h> +# else +# include "elf.h" +# endif +#endif +#ifdef __FreeBSD__ +# include <machine/cpu.h> +# ifndef PPC_FEATURE2_ARCH_3_1 +# define PPC_FEATURE2_ARCH_3_1 0 +# endif +# define PPC_FEATURE2_VEC_CRYPTO PPC_FEATURE2_HAS_VEC_CRYPTO #endif unsigned cpuinfo; @@ -19,16 +28,17 @@ unsigned cpuinfo; unsigned __attribute__((constructor)) cpuinfo_init(void) { unsigned info = cpuinfo; - unsigned long hwcap, hwcap2; if (info) { return info; } - hwcap = qemu_getauxval(AT_HWCAP); - hwcap2 = qemu_getauxval(AT_HWCAP2); info = CPUINFO_ALWAYS; +#if defined(CONFIG_LINUX) || defined(__FreeBSD__) + unsigned long hwcap = qemu_getauxval(AT_HWCAP); + unsigned long hwcap2 = qemu_getauxval(AT_HWCAP2); + /* Version numbers are monotonic, and so imply all lower versions. */ if (hwcap2 & PPC_FEATURE2_ARCH_3_1) { info |= CPUINFO_V3_1 | CPUINFO_V3_0 | CPUINFO_V2_07 | CPUINFO_V2_06; @@ -58,6 +68,7 @@ unsigned __attribute__((constructor)) cpuinfo_init(void) } } } +#endif cpuinfo = info; return info; diff --git a/util/cpuinfo-riscv.c b/util/cpuinfo-riscv.c new file mode 100644 index 0000000000..497ce12680 --- /dev/null +++ b/util/cpuinfo-riscv.c @@ -0,0 +1,118 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * Host specific cpu identification for RISC-V. + */ + +#include "qemu/osdep.h" +#include "host/cpuinfo.h" + +#ifdef CONFIG_ASM_HWPROBE_H +#include <asm/hwprobe.h> +#include <sys/syscall.h> +#endif + +unsigned cpuinfo; +static volatile sig_atomic_t got_sigill; + +static void sigill_handler(int signo, siginfo_t *si, void *data) +{ + /* Skip the faulty instruction */ + ucontext_t *uc = (ucontext_t *)data; + +#ifdef __linux__ + uc->uc_mcontext.__gregs[REG_PC] += 4; +#elif defined(__OpenBSD__) + uc->sc_sepc += 4; +#else +# error Unsupported OS +#endif + + got_sigill = 1; +} + +/* Called both as constructor and (possibly) via other constructors. */ +unsigned __attribute__((constructor)) cpuinfo_init(void) +{ + unsigned left = CPUINFO_ZBA | CPUINFO_ZBB | CPUINFO_ZICOND; + unsigned info = cpuinfo; + + if (info) { + return info; + } + + /* Test for compile-time settings. */ +#if defined(__riscv_arch_test) && defined(__riscv_zba) + info |= CPUINFO_ZBA; +#endif +#if defined(__riscv_arch_test) && defined(__riscv_zbb) + info |= CPUINFO_ZBB; +#endif +#if defined(__riscv_arch_test) && defined(__riscv_zicond) + info |= CPUINFO_ZICOND; +#endif + left &= ~info; + +#ifdef CONFIG_ASM_HWPROBE_H + if (left) { + /* + * TODO: glibc 2.40 will introduce <sys/hwprobe.h>, which + * provides __riscv_hwprobe and __riscv_hwprobe_one, + * which is a slightly cleaner interface. + */ + struct riscv_hwprobe pair = { .key = RISCV_HWPROBE_KEY_IMA_EXT_0 }; + if (syscall(__NR_riscv_hwprobe, &pair, 1, 0, NULL, 0) == 0 + && pair.key >= 0) { + info |= pair.value & RISCV_HWPROBE_EXT_ZBA ? CPUINFO_ZBA : 0; + info |= pair.value & RISCV_HWPROBE_EXT_ZBB ? CPUINFO_ZBB : 0; + left &= ~(CPUINFO_ZBA | CPUINFO_ZBB); +#ifdef RISCV_HWPROBE_EXT_ZICOND + info |= pair.value & RISCV_HWPROBE_EXT_ZICOND ? CPUINFO_ZICOND : 0; + left &= ~CPUINFO_ZICOND; +#endif + } + } +#endif /* CONFIG_ASM_HWPROBE_H */ + + if (left) { + struct sigaction sa_old, sa_new; + + memset(&sa_new, 0, sizeof(sa_new)); + sa_new.sa_flags = SA_SIGINFO; + sa_new.sa_sigaction = sigill_handler; + sigaction(SIGILL, &sa_new, &sa_old); + + if (left & CPUINFO_ZBA) { + /* Probe for Zba: add.uw zero,zero,zero. */ + got_sigill = 0; + asm volatile(".insn r 0x3b, 0, 0x04, zero, zero, zero" + : : : "memory"); + info |= got_sigill ? 0 : CPUINFO_ZBA; + left &= ~CPUINFO_ZBA; + } + + if (left & CPUINFO_ZBB) { + /* Probe for Zbb: andn zero,zero,zero. */ + got_sigill = 0; + asm volatile(".insn r 0x33, 7, 0x20, zero, zero, zero" + : : : "memory"); + info |= got_sigill ? 0 : CPUINFO_ZBB; + left &= ~CPUINFO_ZBB; + } + + if (left & CPUINFO_ZICOND) { + /* Probe for Zicond: czero.eqz zero,zero,zero. */ + got_sigill = 0; + asm volatile(".insn r 0x33, 5, 0x07, zero, zero, zero" + : : : "memory"); + info |= got_sigill ? 0 : CPUINFO_ZICOND; + left &= ~CPUINFO_ZICOND; + } + + sigaction(SIGILL, &sa_old, NULL); + assert(left == 0); + } + + info |= CPUINFO_ALWAYS; + cpuinfo = info; + return info; +} diff --git a/util/meson.build b/util/meson.build index 72b505df11..5d8bef9891 100644 --- a/util/meson.build +++ b/util/meson.build @@ -127,4 +127,6 @@ elif cpu == 'loongarch64' util_ss.add(files('cpuinfo-loongarch.c')) elif cpu in ['ppc', 'ppc64'] util_ss.add(files('cpuinfo-ppc.c')) +elif cpu in ['riscv32', 'riscv64'] + util_ss.add(files('cpuinfo-riscv.c')) endif diff --git a/util/vhost-user-server.c b/util/vhost-user-server.c index 3bfb1ad3ec..b19229074a 100644 --- a/util/vhost-user-server.c +++ b/util/vhost-user-server.c @@ -65,6 +65,18 @@ static void vmsg_close_fds(VhostUserMsg *vmsg) static void vmsg_unblock_fds(VhostUserMsg *vmsg) { int i; + + /* + * These messages carry fd used to map memory, not to send/receive messages, + * so this operation is useless. In addition, in some systems this + * operation can fail (e.g. in macOS setting an fd returned by shm_open() + * non-blocking fails with errno = ENOTTY) + */ + if (vmsg->request == VHOST_USER_ADD_MEM_REG || + vmsg->request == VHOST_USER_SET_MEM_TABLE) { + return; + } + for (i = 0; i < vmsg->fd_num; i++) { qemu_socket_set_nonblock(vmsg->fds[i]); } |