aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.editorconfig21
-rw-r--r--.gitmodules34
-rw-r--r--.mailmap1
-rw-r--r--.travis.yml16
-rw-r--r--MAINTAINERS287
-rw-r--r--README4
-rw-r--r--VERSION2
-rw-r--r--accel/kvm/kvm-all.c56
-rw-r--r--accel/tcg/atomic_template.h20
-rw-r--r--accel/tcg/cpu-exec.c2
-rw-r--r--accel/tcg/cputlb.c516
-rw-r--r--accel/tcg/softmmu_template.h64
-rw-r--r--accel/tcg/tcg-all.c2
-rw-r--r--accel/tcg/translate-all.c10
-rw-r--r--accel/tcg/user-exec.c5
-rw-r--r--audio/paaudio.c4
-rw-r--r--backends/hostmem-file.c10
-rw-r--r--block.c92
-rw-r--r--block/Makefile.objs22
-rw-r--r--block/block-backend.c11
-rw-r--r--block/bochs.c17
-rw-r--r--block/cloop.c16
-rw-r--r--block/curl.c8
-rw-r--r--block/dirty-bitmap.c79
-rw-r--r--block/dmg.c16
-rw-r--r--block/file-posix.c141
-rw-r--r--block/gluster.c12
-rw-r--r--block/iscsi.c10
-rw-r--r--block/nbd-client.c10
-rw-r--r--block/qcow.c18
-rw-r--r--block/qcow2-bitmap.c40
-rw-r--r--block/qcow2-refcount.c38
-rw-r--r--block/qcow2.c156
-rw-r--r--block/qcow2.h7
-rw-r--r--block/qed.c4
-rw-r--r--block/quorum.c45
-rw-r--r--block/rbd.c18
-rw-r--r--block/sheepdog.c2
-rw-r--r--block/vdi.c68
-rw-r--r--block/vhdx-endian.c118
-rw-r--r--block/vhdx-log.c4
-rw-r--r--block/vhdx.c18
-rw-r--r--block/vhdx.h12
-rw-r--r--block/vpc.c10
-rw-r--r--block/vvfat.c67
-rw-r--r--blockdev.c195
-rw-r--r--chardev/char-pty.c2
-rw-r--r--chardev/char-socket.c123
-rw-r--r--chardev/char.c12
-rwxr-xr-xconfigure418
-rw-r--r--cpus.c23
-rw-r--r--crypto/Makefile.objs8
-rw-r--r--crypto/block-qcow.c2
-rw-r--r--crypto/init.c23
-rw-r--r--crypto/tlscredsx509.c21
-rw-r--r--crypto/tlssession.c11
-rw-r--r--crypto/xts.c200
-rw-r--r--default-configs/aarch64-softmmu.mak1
-rw-r--r--default-configs/alpha-softmmu.mak2
-rw-r--r--default-configs/hyperv.mak2
-rw-r--r--default-configs/i386-softmmu.mak5
-rw-r--r--default-configs/ppc-softmmu.mak1
-rw-r--r--default-configs/ppc64-softmmu.mak4
-rw-r--r--default-configs/sparc64-softmmu.mak1
-rw-r--r--device-hotplug.c5
-rw-r--r--disas/Makefile.objs1
-rw-r--r--disas/nanomips.cpp22242
-rw-r--r--disas/nanomips.h1099
-rw-r--r--docs/COLO-FT.txt36
-rw-r--r--docs/devel/migration.rst1
-rw-r--r--docs/devel/testing.rst45
-rw-r--r--docs/interop/qcow2.txt38
-rw-r--r--docs/nvdimm.txt5
-rw-r--r--docs/specs/pci-testdev.txt15
-rw-r--r--docs/specs/tpm.txt15
-rw-r--r--exec.c1
-rw-r--r--fsdev/qemu-fsdev-dummy.c2
-rw-r--r--fsdev/qemu-fsdev.c12
-rw-r--r--fsdev/qemu-fsdev.h2
-rw-r--r--hw/9pfs/9p-handle.c6
-rw-r--r--hw/9pfs/9p-local.c4
-rw-r--r--hw/9pfs/9p.c15
-rw-r--r--hw/9pfs/cofile.c6
-rw-r--r--hw/9pfs/xen-9p-backend.c7
-rw-r--r--hw/Makefile.objs3
-rw-r--r--hw/acpi/nvdimm.c16
-rw-r--r--hw/alpha/typhoon.c13
-rw-r--r--hw/arm/Makefile.objs1
-rw-r--r--hw/arm/boot.c18
-rw-r--r--hw/arm/exynos4210.c2
-rw-r--r--hw/arm/microbit.c2
-rw-r--r--hw/arm/musicpal.c5
-rw-r--r--hw/arm/nrf51_soc.c20
-rw-r--r--hw/arm/strongarm.c4
-rw-r--r--hw/arm/sysbus-fdt.c12
-rw-r--r--hw/arm/virt.c4
-rw-r--r--hw/arm/xilinx_zynq.c2
-rw-r--r--hw/arm/xlnx-versal-virt.c494
-rw-r--r--hw/arm/xlnx-versal.c323
-rw-r--r--hw/audio/ac97.c12
-rw-r--r--hw/audio/es1370.c10
-rw-r--r--hw/audio/marvell_88w8618.c14
-rw-r--r--hw/block/fdc.c2
-rw-r--r--hw/block/nvme.c13
-rw-r--r--hw/block/onenand.c24
-rw-r--r--hw/block/vhost-user-blk.c25
-rw-r--r--hw/block/virtio-blk.c4
-rw-r--r--hw/char/Makefile.objs1
-rw-r--r--hw/char/nrf51_uart.c330
-rw-r--r--hw/char/stm32f2xx_usart.c2
-rw-r--r--hw/char/trace-events4
-rw-r--r--hw/core/Makefile.objs3
-rw-r--r--hw/core/hotplug.c10
-rw-r--r--hw/core/machine.c2
-rw-r--r--hw/core/null-machine.c2
-rw-r--r--hw/core/qdev.c16
-rw-r--r--hw/display/cg3.c2
-rw-r--r--hw/display/edid-generate.c2
-rw-r--r--hw/display/qxl.c19
-rw-r--r--hw/display/qxl.h1
-rw-r--r--hw/display/tcx.c2
-rw-r--r--hw/display/vga_int.h1
-rw-r--r--hw/hppa/dino.c7
-rw-r--r--hw/hyperv/Makefile.objs2
-rw-r--r--hw/hyperv/hyperv.c654
-rw-r--r--hw/hyperv/hyperv_testdev.c327
-rw-r--r--hw/i386/acpi-build.c31
-rw-r--r--hw/i386/amd_iommu.c414
-rw-r--r--hw/i386/amd_iommu.h96
-rw-r--r--hw/i386/intel_iommu.c127
-rw-r--r--hw/i386/pc.c11
-rw-r--r--hw/i386/pc_piix.c15
-rw-r--r--hw/i386/pc_q35.c13
-rw-r--r--hw/i386/trace-events14
-rw-r--r--hw/i386/x86-iommu.c33
-rw-r--r--hw/intc/armv7m_nvic.c12
-rw-r--r--hw/intc/ioapic.c8
-rw-r--r--hw/intc/xics.c15
-rw-r--r--hw/intc/xics_kvm.c7
-rw-r--r--hw/isa/Makefile.objs3
-rw-r--r--hw/lm32/milkymist.c5
-rw-r--r--hw/mem/Makefile.objs4
-rw-r--r--hw/mem/memory-device.c103
-rw-r--r--hw/mem/nvdimm.c10
-rw-r--r--hw/mem/pc-dimm.c84
-rw-r--r--hw/mem/trace-events5
-rw-r--r--hw/mips/gt64xxx_pci.c18
-rw-r--r--hw/mips/mips_malta.c13
-rw-r--r--hw/misc/Makefile.objs1
-rw-r--r--hw/misc/edu.c4
-rw-r--r--hw/misc/hyperv_testdev.c174
-rw-r--r--hw/misc/ivshmem.c5
-rw-r--r--hw/misc/macio/pmu.c1
-rw-r--r--hw/misc/pc-testdev.c2
-rw-r--r--hw/misc/pci-testdev.c19
-rw-r--r--hw/net/cadence_gem.c9
-rw-r--r--hw/net/e1000.c16
-rw-r--r--hw/net/etraxfs_eth.c44
-rw-r--r--hw/net/lan9118.c9
-rw-r--r--hw/net/lance.c8
-rw-r--r--hw/net/milkymist-minimac2.c24
-rw-r--r--hw/net/mipsnet.c9
-rw-r--r--hw/net/ne2000.c4
-rw-r--r--hw/net/opencores_eth.c8
-rw-r--r--hw/net/pcnet.c4
-rw-r--r--hw/net/rtl8139.c8
-rw-r--r--hw/net/smc91c111.c8
-rw-r--r--hw/net/stellaris_enet.c15
-rw-r--r--hw/net/trace-events3
-rw-r--r--hw/net/virtio-net.c8
-rw-r--r--hw/net/xgmac.c9
-rw-r--r--hw/nvram/Makefile.objs2
-rw-r--r--hw/pci-bridge/ioh3420.c2
-rw-r--r--hw/pci-bridge/ioh3420.h6
-rw-r--r--hw/pci-bridge/xio3130_downstream.c28
-rw-r--r--hw/pci-bridge/xio3130_downstream.h11
-rw-r--r--hw/pci-bridge/xio3130_upstream.c24
-rw-r--r--hw/pci-bridge/xio3130_upstream.h10
-rw-r--r--hw/pci-host/bonito.c9
-rw-r--r--hw/pci-host/piix.c40
-rw-r--r--hw/pci-host/ppce500.c14
-rw-r--r--hw/pci-host/q35.c33
-rw-r--r--hw/pci/pci_bridge.c2
-rw-r--r--hw/ppc/Makefile.objs3
-rw-r--r--hw/ppc/mac_newworld.c1
-rw-r--r--hw/ppc/pnv_core.c4
-rw-r--r--hw/ppc/pnv_lpc.c8
-rw-r--r--hw/ppc/ppc440_pcix.c14
-rw-r--r--hw/ppc/ppc440_uc.c6
-rw-r--r--hw/ppc/ppc4xx_pci.c14
-rw-r--r--hw/ppc/spapr.c54
-rw-r--r--hw/ppc/spapr_caps.c32
-rw-r--r--hw/ppc/spapr_pci.c9
-rw-r--r--hw/ppc/spapr_rng.c23
-rw-r--r--hw/riscv/sifive_clint.c8
-rw-r--r--hw/riscv/sifive_plic.c4
-rw-r--r--hw/riscv/sifive_u.c4
-rw-r--r--hw/riscv/spike.c12
-rw-r--r--hw/riscv/virt.c7
-rw-r--r--hw/s390x/s390-pci-bus.c25
-rw-r--r--hw/scsi/Makefile.objs2
-rw-r--r--hw/scsi/emulation.c42
-rw-r--r--hw/scsi/lsi53c895a.c19
-rw-r--r--hw/scsi/scsi-disk.c121
-rw-r--r--hw/scsi/scsi-generic.c60
-rw-r--r--hw/scsi/vhost-scsi.c2
-rw-r--r--hw/scsi/virtio-scsi.c11
-rw-r--r--hw/sd/ssi-sd.c2
-rw-r--r--hw/sh4/sh_pci.c20
-rw-r--r--hw/smbios/smbios.c90
-rw-r--r--hw/sparc64/niagara.c4
-rw-r--r--hw/ssi/xilinx_spi.c9
-rw-r--r--hw/timer/aspeed_timer.c3
-rw-r--r--hw/timer/mc146818rtc.c9
-rw-r--r--hw/timer/stm32f2xx_timer.c2
-rw-r--r--hw/timer/sun4v-rtc.c23
-rw-r--r--hw/timer/trace-events6
-rw-r--r--hw/tpm/tpm_emulator.c1
-rw-r--r--hw/tpm/tpm_tis.c2
-rw-r--r--hw/usb/bus.c5
-rw-r--r--hw/usb/ccid-card-emulated.c27
-rw-r--r--hw/usb/hcd-ohci.c6
-rw-r--r--hw/vfio/ap.c2
-rw-r--r--hw/vfio/pci-quirks.c4
-rw-r--r--hw/vfio/pci.c25
-rw-r--r--hw/vfio/platform.c6
-rw-r--r--hw/virtio/virtio-pci.c4
-rw-r--r--hw/virtio/virtio.c2
-rw-r--r--hw/xen/xen_pt.c2
-rw-r--r--hw/xen/xen_pt_config_init.c8
-rw-r--r--include/block/aio.h59
-rw-r--r--include/block/block.h5
-rw-r--r--include/block/block_int.h2
-rw-r--r--include/block/dirty-bitmap.h5
-rw-r--r--include/disas/bfd.h1
-rw-r--r--include/elf.h37
-rw-r--r--include/exec/cpu-defs.h50
-rw-r--r--include/exec/cpu_ldst.h30
-rw-r--r--include/exec/cpu_ldst_template.h25
-rw-r--r--include/exec/cputlb.h2
-rw-r--r--include/exec/exec-all.h8
-rw-r--r--include/exec/memory.h35
-rw-r--r--include/exec/poison.h1
-rw-r--r--include/exec/ram_addr.h1
-rw-r--r--include/fpu/softfloat-macros.h4
-rw-r--r--include/hw/arm/nrf51_soc.h3
-rw-r--r--include/hw/arm/xlnx-versal.h122
-rw-r--r--include/hw/audio/wm8750.h1
-rw-r--r--include/hw/char/nrf51_uart.h78
-rw-r--r--include/hw/hotplug.h11
-rw-r--r--include/hw/hyperv/hyperv-proto.h130
-rw-r--r--include/hw/hyperv/hyperv.h83
-rw-r--r--include/hw/i386/intel_iommu.h59
-rw-r--r--include/hw/i386/pc.h16
-rw-r--r--include/hw/i386/x86-iommu.h66
-rw-r--r--include/hw/intc/arm_gicv3_common.h2
-rw-r--r--include/hw/mem/memory-device.h74
-rw-r--r--include/hw/mem/pc-dimm.h10
-rw-r--r--include/hw/pci/pci_bus.h2
-rw-r--r--include/hw/pci/pci_ids.h2
-rw-r--r--include/hw/ppc/spapr.h7
-rw-r--r--include/hw/scsi/emulation.h16
-rw-r--r--include/hw/scsi/scsi.h1
-rw-r--r--include/hw/vfio/vfio-common.h3
-rw-r--r--include/io/channel-tls.h1
-rw-r--r--include/io/channel.h6
-rw-r--r--include/migration/colo.h11
-rw-r--r--include/net/filter.h5
-rw-r--r--include/qapi/error.h14
-rw-r--r--include/qapi/qmp/qerror.h6
-rw-r--r--include/qemu/atomic128.h153
-rw-r--r--include/qemu/compiler.h11
-rw-r--r--include/qemu/hbitmap.h25
-rw-r--r--include/qemu/option.h2
-rw-r--r--include/qemu/osdep.h12
-rw-r--r--include/qemu/thread.h22
-rw-r--r--include/qemu/timer.h127
-rw-r--r--include/qemu/units.h18
-rw-r--r--include/qom/cpu.h8
-rw-r--r--include/sysemu/block-backend.h6
-rw-r--r--include/sysemu/blockdev.h3
-rw-r--r--include/sysemu/hvf.h4
-rw-r--r--include/sysemu/kvm.h2
-rw-r--r--include/sysemu/numa.h1
-rw-r--r--include/sysemu/replay.h10
-rw-r--r--include/sysemu/tpm.h2
-rw-r--r--include/ui/console.h2
-rw-r--r--io/channel-tls.c5
-rw-r--r--io/channel-websock.c1
-rw-r--r--job.c4
-rw-r--r--linux-headers/asm-powerpc/kvm.h1
-rw-r--r--linux-headers/asm-x86/kvm.h8
-rw-r--r--linux-headers/linux/kvm.h16
-rw-r--r--linux-user/aarch64/cpu_loop.c13
-rw-r--r--linux-user/aarch64/signal.c4
-rw-r--r--linux-user/alpha/cpu_loop.c12
-rw-r--r--linux-user/arm/cpu_loop.c16
-rw-r--r--linux-user/cris/cpu_loop.c16
-rw-r--r--linux-user/elfload.c95
-rw-r--r--linux-user/flatload.c8
-rw-r--r--linux-user/hppa/cpu_loop.c11
-rw-r--r--linux-user/i386/cpu_loop.c16
-rw-r--r--linux-user/ioctls.h46
-rw-r--r--linux-user/m68k/cpu_loop.c17
-rw-r--r--linux-user/m68k/signal.c3
-rw-r--r--linux-user/microblaze/cpu_loop.c16
-rw-r--r--linux-user/mips/cpu_loop.c91
-rw-r--r--linux-user/mips/target_elf.h3
-rw-r--r--linux-user/mips/target_syscall.h6
-rw-r--r--linux-user/mips64/target_syscall.h6
-rw-r--r--linux-user/nios2/cpu_loop.c17
-rw-r--r--linux-user/openrisc/cpu_loop.c11
-rw-r--r--linux-user/ppc/cpu_loop.c15
-rw-r--r--linux-user/qemu.h80
-rw-r--r--linux-user/riscv/cpu_loop.c2
-rw-r--r--linux-user/s390x/cpu_loop.c9
-rw-r--r--linux-user/sh4/cpu_loop.c17
-rw-r--r--linux-user/sh4/signal.c4
-rw-r--r--linux-user/sparc/cpu_loop.c16
-rw-r--r--linux-user/sparc/signal.c22
-rw-r--r--linux-user/strace.c3
-rw-r--r--linux-user/syscall.c280
-rw-r--r--linux-user/syscall_defs.h28
-rw-r--r--linux-user/syscall_types.h68
-rw-r--r--linux-user/xtensa/cpu_loop.c11
-rw-r--r--linux-user/xtensa/target_flat.h10
-rw-r--r--memory.c49
-rw-r--r--memory_mapping.c3
-rw-r--r--migration/Makefile.objs2
-rw-r--r--migration/block-dirty-bitmap.c12
-rw-r--r--migration/colo-comm.c76
-rw-r--r--migration/colo-failover.c2
-rw-r--r--migration/colo.c212
-rw-r--r--migration/migration.c60
-rw-r--r--migration/migration.h2
-rw-r--r--migration/ram.c166
-rw-r--r--migration/ram.h4
-rw-r--r--migration/savevm.c80
-rw-r--r--migration/savevm.h5
-rw-r--r--migration/trace-events3
-rw-r--r--monitor.c50
-rw-r--r--nbd/server.c18
-rw-r--r--net/colo-compare.c115
-rw-r--r--net/colo-compare.h24
-rw-r--r--net/colo.c10
-rw-r--r--net/colo.h11
-rw-r--r--net/filter-rewriter.c167
-rw-r--r--net/filter.c17
-rw-r--r--net/l2tpv3.c25
-rw-r--r--net/net.c26
-rw-r--r--net/slirp.c21
-rw-r--r--net/socket.c4
-rw-r--r--numa.c21
-rw-r--r--pc-bios/README8
-rw-r--r--pc-bios/bios-256k.binbin262144 -> 262144 bytes
-rw-r--r--pc-bios/bios.binbin131072 -> 131072 bytes
-rw-r--r--pc-bios/vgabios-bochs-display.binbin27648 -> 27648 bytes
-rw-r--r--pc-bios/vgabios-cirrus.binbin38400 -> 38400 bytes
-rw-r--r--pc-bios/vgabios-qxl.binbin38912 -> 38912 bytes
-rw-r--r--pc-bios/vgabios-ramfb.binbin28160 -> 28160 bytes
-rw-r--r--pc-bios/vgabios-stdvga.binbin38912 -> 38912 bytes
-rw-r--r--pc-bios/vgabios-virtio.binbin38912 -> 38912 bytes
-rw-r--r--pc-bios/vgabios-vmware.binbin38912 -> 38912 bytes
-rw-r--r--pc-bios/vgabios.binbin38400 -> 38400 bytes
-rw-r--r--po/Makefile2
-rw-r--r--qapi/block-core.json14
-rw-r--r--qapi/char.json3
-rw-r--r--qapi/migration.json80
-rw-r--r--qapi/misc.json5
-rw-r--r--qapi/net.json5
-rw-r--r--qapi/transaction.json2
-rw-r--r--qapi/ui.json17
-rw-r--r--qdev-monitor.c13
-rw-r--r--qemu-deprecated.texi19
-rw-r--r--qemu-img.c5
-rw-r--r--qemu-io-cmds.c4
-rw-r--r--qemu-io.c8
-rw-r--r--qemu-nbd.c14
-rw-r--r--qemu-options.hx46
-rw-r--r--qemu-seccomp.c18
-rw-r--r--qga/Makefile.objs1
-rw-r--r--qga/channel-win32.c3
-rw-r--r--qga/commands-posix.c152
-rw-r--r--qga/commands-win32.c340
-rw-r--r--qga/guest-agent-core.h5
-rw-r--r--qga/installer/qemu-ga.wxs2
-rw-r--r--qga/main.c258
-rw-r--r--qga/qapi-schema.json5
-rw-r--r--qga/service-win32.h4
-rw-r--r--qga/vss-win32.c5
-rw-r--r--qga/vss-win32.h3
-rw-r--r--qga/vss-win32/requester.cpp92
-rw-r--r--qga/vss-win32/requester.h13
-rw-r--r--qobject/block-qdict.c2
-rw-r--r--qom/cpu.c2
-rw-r--r--qom/object_interfaces.c4
-rw-r--r--replay/replay-events.c1
-rw-r--r--replay/replay-internal.c41
-rw-r--r--replay/replay-internal.h2
-rw-r--r--replay/replay-time.c8
-rw-r--r--replay/replay.c9
-rw-r--r--roms/Makefile2
m---------roms/seabios0
-rwxr-xr-xscripts/check-qerror.sh22
-rwxr-xr-xscripts/checkpatch.pl4
-rw-r--r--scripts/coccinelle/tcg_gen_extract.cocci2
-rw-r--r--scripts/coccinelle/use-error_fatal.cocci20
-rwxr-xr-xscripts/decodetree.py68
-rwxr-xr-xscripts/device-crash-test17
-rw-r--r--scripts/dump-guest-memory.py4
-rwxr-xr-xscripts/get_maintainer.pl2
-rwxr-xr-xscripts/make-release1
-rw-r--r--scripts/qemu.py107
-rw-r--r--scripts/qtest.py2
-rw-r--r--slirp/bootp.c45
-rw-r--r--slirp/bootp.h1
-rw-r--r--slirp/ip6_icmp.c9
-rw-r--r--slirp/ip_icmp.c2
-rw-r--r--slirp/libslirp.h1
-rw-r--r--slirp/misc.c55
-rw-r--r--slirp/slirp.c16
-rw-r--r--slirp/slirp.h1
-rw-r--r--slirp/socket.c17
-rw-r--r--slirp/tcp_input.c7
-rw-r--r--slirp/tcp_subr.c7
-rw-r--r--slirp/udp.c6
-rw-r--r--slirp/udp6.c3
-rw-r--r--stubs/cpu-get-icount.c5
-rw-r--r--stubs/replay.c2
-rw-r--r--stubs/tpm.c3
-rw-r--r--target/alpha/cpu.c1
-rw-r--r--target/arm/cpu.c316
-rw-r--r--target/arm/cpu.h270
-rw-r--r--target/arm/cpu64.c148
-rw-r--r--target/arm/helper-a64.c253
-rw-r--r--target/arm/helper.c418
-rw-r--r--target/arm/internals.h79
-rw-r--r--target/arm/kvm.c61
-rw-r--r--target/arm/kvm32.c94
-rw-r--r--target/arm/kvm64.c125
-rw-r--r--target/arm/kvm_arm.h25
-rw-r--r--target/arm/machine.c76
-rw-r--r--target/arm/op_helper.c60
-rw-r--r--target/arm/translate-a64.c761
-rw-r--r--target/arm/translate-sve.c507
-rw-r--r--target/arm/translate.c1445
-rw-r--r--target/arm/translate.h21
-rw-r--r--target/i386/Makefile.objs17
-rw-r--r--target/i386/cpu.c300
-rw-r--r--target/i386/cpu.h11
-rw-r--r--target/i386/hvf/hvf.c9
-rw-r--r--target/i386/hvf/x86_decode.c67
-rw-r--r--target/i386/hvf/x86_decode.h6
-rw-r--r--target/i386/hyperv-proto.h118
-rw-r--r--target/i386/hyperv-stub.c48
-rw-r--r--target/i386/hyperv.c130
-rw-r--r--target/i386/hyperv.h28
-rw-r--r--target/i386/kvm.c189
-rw-r--r--target/i386/machine.c9
-rw-r--r--target/i386/mem_helper.c9
-rw-r--r--target/i386/seg_helper.c4
-rw-r--r--target/i386/translate.c6
-rw-r--r--target/m68k/cpu.h1
-rw-r--r--target/m68k/translate.c6
-rw-r--r--target/mips/cpu.c13
-rw-r--r--target/mips/cpu.h251
-rw-r--r--target/mips/helper.c365
-rw-r--r--target/mips/helper.h3
-rw-r--r--target/mips/internal.h34
-rw-r--r--target/mips/machine.c8
-rw-r--r--target/mips/mips-defs.h83
-rw-r--r--target/mips/op_helper.c88
-rw-r--r--target/mips/translate.c3705
-rw-r--r--target/mips/translate_init.inc.c9
-rw-r--r--target/openrisc/disas.c23
-rw-r--r--target/openrisc/translate.c200
-rw-r--r--target/ppc/cpu.h24
-rw-r--r--target/ppc/fpu_helper.c661
-rw-r--r--target/ppc/helper.h6
-rw-r--r--target/ppc/kvm.c12
-rw-r--r--target/ppc/kvm_ppc.h12
-rw-r--r--target/ppc/mem_helper.c67
-rw-r--r--target/ppc/mmu_helper.c172
-rw-r--r--target/ppc/translate.c280
-rw-r--r--target/ppc/translate/fp-impl.inc.c34
-rw-r--r--target/ppc/translate/fp-ops.inc.c2
-rw-r--r--target/ppc/translate_init.inc.c35
-rw-r--r--target/riscv/Makefile.objs2
-rw-r--r--target/riscv/cpu.c6
-rw-r--r--target/riscv/cpu.h22
-rw-r--r--target/riscv/cpu_bits.h683
-rw-r--r--target/riscv/cpu_helper.c (renamed from target/riscv/helper.c)35
-rw-r--r--target/riscv/op_helper.c34
-rw-r--r--target/riscv/pmp.c2
-rw-r--r--target/riscv/translate.c24
-rw-r--r--target/s390x/mem_helper.c196
-rw-r--r--target/s390x/translate.c45
-rw-r--r--target/unicore32/cpu.c2
-rw-r--r--tcg/tcg-op.c9
-rw-r--r--tcg/tcg-op.h5
-rw-r--r--tcg/tcg.c25
-rw-r--r--tcg/tcg.h20
-rw-r--r--tests/Makefile.include47
-rw-r--r--tests/benchmark-crypto-cipher.c149
-rw-r--r--tests/bios-tables-test.c22
-rw-r--r--tests/boot-serial-test.c19
-rwxr-xr-xtests/check-block.sh6
-rw-r--r--tests/cpu-plug-test.c18
-rw-r--r--tests/crypto-tls-x509-helpers.h3
-rw-r--r--tests/data/acpi/pc/APIC (renamed from tests/acpi-test-data/pc/APIC)bin120 -> 120 bytes
-rw-r--r--tests/data/acpi/pc/APIC.cphp (renamed from tests/acpi-test-data/pc/APIC.cphp)bin160 -> 160 bytes
-rw-r--r--tests/data/acpi/pc/APIC.dimmpxm (renamed from tests/acpi-test-data/pc/APIC.dimmpxm)bin144 -> 144 bytes
-rw-r--r--tests/data/acpi/pc/DSDT (renamed from tests/acpi-test-data/pc/DSDT)bin5131 -> 5131 bytes
-rw-r--r--tests/data/acpi/pc/DSDT.bridge (renamed from tests/acpi-test-data/pc/DSDT.bridge)bin6990 -> 6990 bytes
-rw-r--r--tests/data/acpi/pc/DSDT.cphp (renamed from tests/acpi-test-data/pc/DSDT.cphp)bin5594 -> 5594 bytes
-rw-r--r--tests/data/acpi/pc/DSDT.dimmpxm (renamed from tests/acpi-test-data/pc/DSDT.dimmpxm)bin6790 -> 6790 bytes
-rw-r--r--tests/data/acpi/pc/DSDT.ipmikcs (renamed from tests/acpi-test-data/pc/DSDT.ipmikcs)bin5203 -> 5203 bytes
-rw-r--r--tests/data/acpi/pc/DSDT.memhp (renamed from tests/acpi-test-data/pc/DSDT.memhp)bin6496 -> 6496 bytes
-rw-r--r--tests/data/acpi/pc/DSDT.numamem (renamed from tests/acpi-test-data/pc/DSDT.numamem)bin5137 -> 5137 bytes
-rw-r--r--tests/data/acpi/pc/FACP (renamed from tests/acpi-test-data/pc/FACP)bin116 -> 116 bytes
-rw-r--r--tests/data/acpi/pc/FACS (renamed from tests/acpi-test-data/pc/FACS)bin64 -> 64 bytes
-rw-r--r--tests/data/acpi/pc/HPET (renamed from tests/acpi-test-data/pc/HPET)bin56 -> 56 bytes
-rw-r--r--tests/data/acpi/pc/NFIT.dimmpxm (renamed from tests/acpi-test-data/pc/NFIT.dimmpxm)bin240 -> 240 bytes
-rw-r--r--tests/data/acpi/pc/SLIT.cphp (renamed from tests/acpi-test-data/pc/SLIT.cphp)bin48 -> 48 bytes
-rw-r--r--tests/data/acpi/pc/SLIT.memhp (renamed from tests/acpi-test-data/pc/SLIT.memhp)bin48 -> 48 bytes
-rw-r--r--tests/data/acpi/pc/SRAT.cphp (renamed from tests/acpi-test-data/pc/SRAT.cphp)bin304 -> 304 bytes
-rw-r--r--tests/data/acpi/pc/SRAT.dimmpxm (renamed from tests/acpi-test-data/pc/SRAT.dimmpxm)bin392 -> 392 bytes
-rw-r--r--tests/data/acpi/pc/SRAT.memhp (renamed from tests/acpi-test-data/pc/SRAT.memhp)bin264 -> 264 bytes
-rw-r--r--tests/data/acpi/pc/SRAT.numamem (renamed from tests/acpi-test-data/pc/SRAT.numamem)bin224 -> 224 bytes
-rw-r--r--tests/data/acpi/pc/SSDT.dimmpxm (renamed from tests/acpi-test-data/pc/SSDT.dimmpxm)bin685 -> 685 bytes
-rw-r--r--tests/data/acpi/q35/APIC (renamed from tests/acpi-test-data/q35/APIC)bin120 -> 120 bytes
-rw-r--r--tests/data/acpi/q35/APIC.cphp (renamed from tests/acpi-test-data/q35/APIC.cphp)bin160 -> 160 bytes
-rw-r--r--tests/data/acpi/q35/APIC.dimmpxm (renamed from tests/acpi-test-data/q35/APIC.dimmpxm)bin144 -> 144 bytes
-rw-r--r--tests/data/acpi/q35/DSDT (renamed from tests/acpi-test-data/q35/DSDT)bin7815 -> 7815 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.bridge (renamed from tests/acpi-test-data/q35/DSDT.bridge)bin7832 -> 7832 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.cphp (renamed from tests/acpi-test-data/q35/DSDT.cphp)bin8278 -> 8278 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.dimmpxm (renamed from tests/acpi-test-data/q35/DSDT.dimmpxm)bin9474 -> 9474 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.ipmibt (renamed from tests/acpi-test-data/q35/DSDT.ipmibt)bin7890 -> 7890 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.memhp (renamed from tests/acpi-test-data/q35/DSDT.memhp)bin9180 -> 9180 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.mmio64bin0 -> 8947 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.numamem (renamed from tests/acpi-test-data/q35/DSDT.numamem)bin7821 -> 7821 bytes
-rw-r--r--tests/data/acpi/q35/FACP (renamed from tests/acpi-test-data/q35/FACP)bin244 -> 244 bytes
-rw-r--r--tests/data/acpi/q35/FACS (renamed from tests/acpi-test-data/q35/FACS)bin64 -> 64 bytes
-rw-r--r--tests/data/acpi/q35/HPET (renamed from tests/acpi-test-data/q35/HPET)bin56 -> 56 bytes
-rw-r--r--tests/data/acpi/q35/MCFG (renamed from tests/acpi-test-data/q35/MCFG)bin60 -> 60 bytes
-rw-r--r--tests/data/acpi/q35/NFIT.dimmpxm (renamed from tests/acpi-test-data/q35/NFIT.dimmpxm)bin240 -> 240 bytes
-rw-r--r--tests/data/acpi/q35/SLIT.cphp (renamed from tests/acpi-test-data/q35/SLIT.cphp)bin48 -> 48 bytes
-rw-r--r--tests/data/acpi/q35/SLIT.memhp (renamed from tests/acpi-test-data/q35/SLIT.memhp)bin48 -> 48 bytes
-rw-r--r--tests/data/acpi/q35/SRAT.cphp (renamed from tests/acpi-test-data/q35/SRAT.cphp)bin304 -> 304 bytes
-rw-r--r--tests/data/acpi/q35/SRAT.dimmpxm (renamed from tests/acpi-test-data/q35/SRAT.dimmpxm)bin392 -> 392 bytes
-rw-r--r--tests/data/acpi/q35/SRAT.memhp (renamed from tests/acpi-test-data/q35/SRAT.memhp)bin264 -> 264 bytes
-rw-r--r--tests/data/acpi/q35/SRAT.mmio64bin0 -> 224 bytes
-rw-r--r--tests/data/acpi/q35/SRAT.numamem (renamed from tests/acpi-test-data/q35/SRAT.numamem)bin224 -> 224 bytes
-rw-r--r--tests/data/acpi/q35/SSDT.dimmpxm (renamed from tests/acpi-test-data/q35/SSDT.dimmpxm)bin685 -> 685 bytes
-rwxr-xr-xtests/data/acpi/rebuild-expected-aml.sh (renamed from tests/acpi-test-data/rebuild-expected-aml.sh)2
-rw-r--r--tests/data/hex-loader/test.hex (renamed from tests/hex-loader-check-data/test.hex)0
-rw-r--r--tests/docker/Makefile.include2
-rwxr-xr-xtests/docker/docker.py4
-rw-r--r--tests/docker/dockerfiles/debian-amd64.docker2
-rwxr-xr-xtests/docker/dockerfiles/debian-bootstrap.pre4
-rwxr-xr-xtests/docker/test-mingw3
-rw-r--r--tests/guest-debug/test-gdbstub.py3
-rw-r--r--tests/hexloader-test.c2
-rw-r--r--tests/ide-test.c4
-rw-r--r--tests/libqtest.c26
-rw-r--r--tests/migration-test.c16
-rw-r--r--tests/ptimer-test-stubs.c13
-rwxr-xr-xtests/qemu-iotests/0011
-rwxr-xr-xtests/qemu-iotests/0021
-rwxr-xr-xtests/qemu-iotests/0031
-rwxr-xr-xtests/qemu-iotests/0041
-rwxr-xr-xtests/qemu-iotests/0051
-rwxr-xr-xtests/qemu-iotests/0071
-rwxr-xr-xtests/qemu-iotests/0081
-rwxr-xr-xtests/qemu-iotests/0091
-rwxr-xr-xtests/qemu-iotests/0101
-rwxr-xr-xtests/qemu-iotests/0111
-rwxr-xr-xtests/qemu-iotests/0121
-rwxr-xr-xtests/qemu-iotests/0131
-rwxr-xr-xtests/qemu-iotests/0141
-rwxr-xr-xtests/qemu-iotests/0151
-rwxr-xr-xtests/qemu-iotests/0171
-rwxr-xr-xtests/qemu-iotests/0181
-rwxr-xr-xtests/qemu-iotests/0191
-rwxr-xr-xtests/qemu-iotests/0201
-rwxr-xr-xtests/qemu-iotests/0211
-rwxr-xr-xtests/qemu-iotests/0221
-rwxr-xr-xtests/qemu-iotests/0231
-rwxr-xr-xtests/qemu-iotests/0241
-rwxr-xr-xtests/qemu-iotests/0251
-rwxr-xr-xtests/qemu-iotests/0261
-rwxr-xr-xtests/qemu-iotests/0271
-rwxr-xr-xtests/qemu-iotests/0281
-rwxr-xr-xtests/qemu-iotests/0291
-rwxr-xr-xtests/qemu-iotests/0302
-rwxr-xr-xtests/qemu-iotests/0311
-rwxr-xr-xtests/qemu-iotests/0321
-rwxr-xr-xtests/qemu-iotests/0331
-rwxr-xr-xtests/qemu-iotests/0341
-rwxr-xr-xtests/qemu-iotests/0353
-rwxr-xr-xtests/qemu-iotests/0361
-rwxr-xr-xtests/qemu-iotests/0373
-rwxr-xr-xtests/qemu-iotests/0387
-rwxr-xr-xtests/qemu-iotests/0391
-rwxr-xr-xtests/qemu-iotests/0404
-rwxr-xr-xtests/qemu-iotests/0414
-rwxr-xr-xtests/qemu-iotests/0421
-rwxr-xr-xtests/qemu-iotests/0431
-rwxr-xr-xtests/qemu-iotests/04424
-rwxr-xr-xtests/qemu-iotests/0452
-rwxr-xr-xtests/qemu-iotests/0467
-rwxr-xr-xtests/qemu-iotests/0473
-rwxr-xr-xtests/qemu-iotests/0495
-rw-r--r--tests/qemu-iotests/049.out12
-rwxr-xr-xtests/qemu-iotests/0501
-rwxr-xr-xtests/qemu-iotests/0515
-rwxr-xr-xtests/qemu-iotests/0521
-rwxr-xr-xtests/qemu-iotests/0531
-rwxr-xr-xtests/qemu-iotests/0541
-rwxr-xr-xtests/qemu-iotests/0562
-rwxr-xr-xtests/qemu-iotests/05848
-rwxr-xr-xtests/qemu-iotests/0591
-rwxr-xr-xtests/qemu-iotests/0601
-rwxr-xr-xtests/qemu-iotests/0611
-rwxr-xr-xtests/qemu-iotests/0621
-rwxr-xr-xtests/qemu-iotests/0631
-rwxr-xr-xtests/qemu-iotests/0641
-rwxr-xr-xtests/qemu-iotests/0654
-rwxr-xr-xtests/qemu-iotests/0661
-rwxr-xr-xtests/qemu-iotests/0675
-rwxr-xr-xtests/qemu-iotests/0681
-rwxr-xr-xtests/qemu-iotests/0691
-rwxr-xr-xtests/qemu-iotests/0701
-rwxr-xr-xtests/qemu-iotests/0715
-rwxr-xr-xtests/qemu-iotests/0721
-rwxr-xr-xtests/qemu-iotests/0731
-rwxr-xr-xtests/qemu-iotests/0751
-rwxr-xr-xtests/qemu-iotests/0761
-rwxr-xr-xtests/qemu-iotests/0775
-rwxr-xr-xtests/qemu-iotests/0781
-rwxr-xr-xtests/qemu-iotests/0791
-rwxr-xr-xtests/qemu-iotests/0801
-rwxr-xr-xtests/qemu-iotests/081121
-rw-r--r--tests/qemu-iotests/081.out70
-rwxr-xr-xtests/qemu-iotests/0823
-rw-r--r--tests/qemu-iotests/082.out956
-rwxr-xr-xtests/qemu-iotests/0833
-rw-r--r--tests/qemu-iotests/083.out9
-rwxr-xr-xtests/qemu-iotests/0841
-rwxr-xr-xtests/qemu-iotests/08511
-rwxr-xr-xtests/qemu-iotests/0863
-rwxr-xr-xtests/qemu-iotests/0877
-rwxr-xr-xtests/qemu-iotests/0881
-rwxr-xr-xtests/qemu-iotests/0891
-rwxr-xr-xtests/qemu-iotests/0901
-rwxr-xr-xtests/qemu-iotests/0911
-rwxr-xr-xtests/qemu-iotests/0921
-rwxr-xr-xtests/qemu-iotests/09318
-rwxr-xr-xtests/qemu-iotests/0941
-rwxr-xr-xtests/qemu-iotests/0951
-rwxr-xr-xtests/qemu-iotests/0971
-rwxr-xr-xtests/qemu-iotests/0981
-rwxr-xr-xtests/qemu-iotests/0997
-rwxr-xr-xtests/qemu-iotests/1011
-rwxr-xr-xtests/qemu-iotests/1021
-rwxr-xr-xtests/qemu-iotests/1031
-rwxr-xr-xtests/qemu-iotests/1041
-rwxr-xr-xtests/qemu-iotests/1051
-rwxr-xr-xtests/qemu-iotests/1061
-rwxr-xr-xtests/qemu-iotests/1071
-rwxr-xr-xtests/qemu-iotests/1081
-rwxr-xr-xtests/qemu-iotests/1093
-rwxr-xr-xtests/qemu-iotests/1101
-rwxr-xr-xtests/qemu-iotests/1111
-rwxr-xr-xtests/qemu-iotests/1123
-rwxr-xr-xtests/qemu-iotests/1131
-rwxr-xr-xtests/qemu-iotests/1141
-rwxr-xr-xtests/qemu-iotests/1151
-rwxr-xr-xtests/qemu-iotests/1161
-rwxr-xr-xtests/qemu-iotests/1171
-rwxr-xr-xtests/qemu-iotests/1191
-rwxr-xr-xtests/qemu-iotests/1201
-rwxr-xr-xtests/qemu-iotests/1211
-rwxr-xr-xtests/qemu-iotests/1221
-rwxr-xr-xtests/qemu-iotests/1231
-rwxr-xr-xtests/qemu-iotests/1244
-rwxr-xr-xtests/qemu-iotests/1251
-rwxr-xr-xtests/qemu-iotests/1261
-rwxr-xr-xtests/qemu-iotests/1271
-rwxr-xr-xtests/qemu-iotests/1281
-rwxr-xr-xtests/qemu-iotests/1301
-rwxr-xr-xtests/qemu-iotests/1311
-rwxr-xr-xtests/qemu-iotests/1331
-rwxr-xr-xtests/qemu-iotests/1341
-rwxr-xr-xtests/qemu-iotests/1351
-rwxr-xr-xtests/qemu-iotests/1362
-rwxr-xr-xtests/qemu-iotests/1371
-rwxr-xr-xtests/qemu-iotests/1381
-rwxr-xr-xtests/qemu-iotests/1392
-rwxr-xr-xtests/qemu-iotests/1401
-rwxr-xr-xtests/qemu-iotests/1411
-rwxr-xr-xtests/qemu-iotests/1429
-rwxr-xr-xtests/qemu-iotests/1431
-rwxr-xr-xtests/qemu-iotests/1441
-rwxr-xr-xtests/qemu-iotests/1451
-rwxr-xr-xtests/qemu-iotests/1461
-rwxr-xr-xtests/qemu-iotests/1472
-rwxr-xr-xtests/qemu-iotests/14914
-rwxr-xr-xtests/qemu-iotests/1501
-rwxr-xr-xtests/qemu-iotests/15112
-rwxr-xr-xtests/qemu-iotests/1535
-rwxr-xr-xtests/qemu-iotests/1541
-rwxr-xr-xtests/qemu-iotests/1561
-rwxr-xr-xtests/qemu-iotests/1575
-rwxr-xr-xtests/qemu-iotests/1581
-rwxr-xr-xtests/qemu-iotests/1591
-rwxr-xr-xtests/qemu-iotests/1601
-rwxr-xr-xtests/qemu-iotests/1621
-rwxr-xr-xtests/qemu-iotests/16313
-rwxr-xr-xtests/qemu-iotests/16971
-rw-r--r--tests/qemu-iotests/169.out4
-rwxr-xr-xtests/qemu-iotests/1701
-rwxr-xr-xtests/qemu-iotests/1711
-rwxr-xr-xtests/qemu-iotests/1727
-rwxr-xr-xtests/qemu-iotests/1731
-rwxr-xr-xtests/qemu-iotests/1741
-rwxr-xr-xtests/qemu-iotests/1751
-rwxr-xr-xtests/qemu-iotests/1763
-rwxr-xr-xtests/qemu-iotests/1773
-rwxr-xr-xtests/qemu-iotests/1781
-rwxr-xr-xtests/qemu-iotests/1791
-rwxr-xr-xtests/qemu-iotests/1811
-rwxr-xr-xtests/qemu-iotests/18272
-rw-r--r--tests/qemu-iotests/182.out9
-rwxr-xr-xtests/qemu-iotests/1831
-rwxr-xr-xtests/qemu-iotests/1845
-rwxr-xr-xtests/qemu-iotests/1851
-rwxr-xr-xtests/qemu-iotests/1865
-rwxr-xr-xtests/qemu-iotests/1871
-rwxr-xr-xtests/qemu-iotests/1881
-rwxr-xr-xtests/qemu-iotests/1891
-rwxr-xr-xtests/qemu-iotests/1901
-rwxr-xr-xtests/qemu-iotests/1911
-rwxr-xr-xtests/qemu-iotests/1921
-rw-r--r--tests/qemu-iotests/194.out22
-rwxr-xr-xtests/qemu-iotests/1955
-rwxr-xr-xtests/qemu-iotests/1971
-rwxr-xr-xtests/qemu-iotests/1981
-rwxr-xr-xtests/qemu-iotests/2001
-rw-r--r--tests/qemu-iotests/202.out12
-rw-r--r--tests/qemu-iotests/203.out14
-rwxr-xr-xtests/qemu-iotests/2043
-rw-r--r--tests/qemu-iotests/206.out218
-rwxr-xr-xtests/qemu-iotests/2076
-rw-r--r--tests/qemu-iotests/207.out72
-rw-r--r--tests/qemu-iotests/208.out8
-rw-r--r--tests/qemu-iotests/210.out94
-rw-r--r--tests/qemu-iotests/211.out102
-rw-r--r--tests/qemu-iotests/212.out174
-rw-r--r--tests/qemu-iotests/213.out182
-rwxr-xr-xtests/qemu-iotests/2141
-rwxr-xr-xtests/qemu-iotests/2151
-rw-r--r--tests/qemu-iotests/216.out4
-rwxr-xr-x[-rw-r--r--]tests/qemu-iotests/2180
-rw-r--r--tests/qemu-iotests/218.out20
-rw-r--r--tests/qemu-iotests/219.out526
-rwxr-xr-xtests/qemu-iotests/22096
-rw-r--r--tests/qemu-iotests/220.out54
-rwxr-xr-xtests/qemu-iotests/2211
-rw-r--r--tests/qemu-iotests/222.out24
-rwxr-xr-xtests/qemu-iotests/2235
-rwxr-xr-xtests/qemu-iotests/2251
-rwxr-xr-xtests/qemu-iotests/2261
-rwxr-xr-xtests/qemu-iotests/2275
-rwxr-xr-xtests/qemu-iotests/2291
-rwxr-xr-xtests/qemu-iotests/2311
-rwxr-xr-xtests/qemu-iotests/232146
-rw-r--r--tests/qemu-iotests/232.out59
-rwxr-xr-xtests/qemu-iotests/233112
-rw-r--r--tests/qemu-iotests/233.out40
-rwxr-xr-xtests/qemu-iotests/check62
-rw-r--r--tests/qemu-iotests/common.config6
-rw-r--r--tests/qemu-iotests/common.nbd109
-rw-r--r--tests/qemu-iotests/common.pattern16
-rw-r--r--tests/qemu-iotests/common.qemu10
-rw-r--r--tests/qemu-iotests/common.rc6
-rw-r--r--tests/qemu-iotests/common.tls137
-rw-r--r--tests/qemu-iotests/group3
-rw-r--r--tests/qemu-iotests/iotests.py37
-rwxr-xr-xtests/qemu-iotests/nbd-fault-injector.py12
-rwxr-xr-xtests/qemu-iotests/qcow2.py10
-rwxr-xr-xtests/qemu-iotests/qed.py6
-rw-r--r--tests/qmp-test.c14
-rw-r--r--tests/requirements.txt4
-rw-r--r--tests/tcg/Makefile.include2
-rw-r--r--tests/tcg/Makefile.probe2
-rw-r--r--tests/tcg/README2
-rw-r--r--tests/tcg/mips/mips64-dsp/subq_s_pw.c2
-rw-r--r--tests/tcg/mips/mipsr5900/Makefile30
-rw-r--r--tests/tcg/mips/mipsr5900/div1.c73
-rw-r--r--tests/tcg/mips/mipsr5900/divu1.c48
-rw-r--r--tests/tcg/mips/mipsr5900/mflohi1.c35
-rw-r--r--tests/tcg/mips/mipsr5900/mtlohi1.c40
-rw-r--r--tests/tcg/mips/mipsr5900/mult.c76
-rw-r--r--tests/tcg/mips/mipsr5900/multu.c68
-rw-r--r--tests/tcg/multiarch/linux-test.c4
-rw-r--r--tests/test-char.c125
-rw-r--r--tests/test-crypto-block.c2
-rw-r--r--tests/test-crypto-tlscredsx509.c8
-rw-r--r--tests/test-crypto-xts.c226
-rw-r--r--tests/test-image-locking.c157
-rw-r--r--tests/tpm-tests.c33
-rw-r--r--tests/tpm-util.c52
-rw-r--r--tests/tpm-util.h2
-rwxr-xr-xtests/vm/basevm.py30
-rwxr-xr-xtests/vm/centos1
-rwxr-xr-xtests/vm/freebsd1
-rwxr-xr-xtests/vm/netbsd1
-rwxr-xr-xtests/vm/openbsd1
-rwxr-xr-xtests/vm/ubuntu.i3861
-rw-r--r--tpm.c22
-rw-r--r--ui/curses.c6
-rw-r--r--ui/egl-headless.c2
-rw-r--r--ui/gtk-egl.c17
-rw-r--r--ui/input.c9
-rw-r--r--ui/keymaps.c40
-rw-r--r--ui/keymaps.h2
-rw-r--r--ui/sdl.c6
-rw-r--r--ui/sdl2.c3
-rw-r--r--ui/spice-core.c13
-rw-r--r--ui/spice-display.c26
-rw-r--r--ui/vnc.c19
-rw-r--r--util/aio-posix.c2
-rw-r--r--util/error.c13
-rw-r--r--util/hbitmap.c14
-rw-r--r--util/oslib-posix.c15
-rw-r--r--util/qemu-error.c5
-rw-r--r--util/qemu-option.c32
-rw-r--r--util/qemu-thread-posix.c44
-rw-r--r--util/qemu-timer.c65
-rw-r--r--vl.c289
841 files changed, 46589 insertions, 9154 deletions
diff --git a/.editorconfig b/.editorconfig
index b2022e391a..1582883393 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,4 +1,10 @@
-# http://editorconfig.org
+# EditorConfig is a file format and collection of text editor plugins
+# for maintaining consistent coding styles between different editors
+# and IDEs. Most popular editors support this either natively or via
+# plugin.
+#
+# Check https://editorconfig.org for details.
+
root = true
[*]
@@ -6,10 +12,23 @@ end_of_line = lf
insert_final_newline = true
charset = utf-8
+[*.mak]
+indent_style = tab
+indent_size = 8
+file_type_emacs = makefile
+
[Makefile*]
indent_style = tab
indent_size = 8
+file_type_emacs = makefile
[*.{c,h}]
indent_style = space
indent_size = 4
+
+[*.{vert,frag}]
+file_type_emacs = glsl
+
+[*.json]
+indent_style = space
+file_type_emacs = python
diff --git a/.gitmodules b/.gitmodules
index a48d2a764c..6b91176098 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,51 +1,51 @@
[submodule "roms/seabios"]
path = roms/seabios
- url = git://git.qemu-project.org/seabios.git/
+ url = https://git.qemu.org/git/seabios.git/
[submodule "roms/SLOF"]
path = roms/SLOF
- url = git://git.qemu-project.org/SLOF.git
+ url = https://git.qemu.org/git/SLOF.git
[submodule "roms/ipxe"]
path = roms/ipxe
- url = git://git.qemu-project.org/ipxe.git
+ url = https://git.qemu.org/git/ipxe.git
[submodule "roms/openbios"]
path = roms/openbios
- url = git://git.qemu-project.org/openbios.git
+ url = https://git.qemu.org/git/openbios.git
[submodule "roms/openhackware"]
path = roms/openhackware
- url = git://git.qemu-project.org/openhackware.git
+ url = https://git.qemu.org/git/openhackware.git
[submodule "roms/qemu-palcode"]
path = roms/qemu-palcode
- url = git://git.qemu.org/qemu-palcode.git
+ url = https://git.qemu.org/git/qemu-palcode.git
[submodule "roms/sgabios"]
path = roms/sgabios
- url = git://git.qemu-project.org/sgabios.git
+ url = https://git.qemu.org/git/sgabios.git
[submodule "dtc"]
path = dtc
- url = git://git.qemu-project.org/dtc.git
+ url = https://git.qemu.org/git/dtc.git
[submodule "roms/u-boot"]
path = roms/u-boot
- url = git://git.qemu-project.org/u-boot.git
+ url = https://git.qemu.org/git/u-boot.git
[submodule "roms/skiboot"]
path = roms/skiboot
- url = git://git.qemu.org/skiboot.git
+ url = https://git.qemu.org/git/skiboot.git
[submodule "roms/QemuMacDrivers"]
path = roms/QemuMacDrivers
- url = git://git.qemu.org/QemuMacDrivers.git
+ url = https://git.qemu.org/git/QemuMacDrivers.git
[submodule "ui/keycodemapdb"]
path = ui/keycodemapdb
- url = git://git.qemu.org/keycodemapdb.git
+ url = https://git.qemu.org/git/keycodemapdb.git
[submodule "capstone"]
path = capstone
- url = git://git.qemu.org/capstone.git
+ url = https://git.qemu.org/git/capstone.git
[submodule "roms/seabios-hppa"]
path = roms/seabios-hppa
- url = git://github.com/hdeller/seabios-hppa.git
+ url = https://github.com/hdeller/seabios-hppa.git
[submodule "roms/u-boot-sam460ex"]
path = roms/u-boot-sam460ex
- url = git://git.qemu.org/u-boot-sam460ex.git
+ url = https://git.qemu.org/git/u-boot-sam460ex.git
[submodule "tests/fp/berkeley-testfloat-3"]
path = tests/fp/berkeley-testfloat-3
- url = git://github.com/cota/berkeley-testfloat-3
+ url = https://github.com/cota/berkeley-testfloat-3
[submodule "tests/fp/berkeley-softfloat-3"]
path = tests/fp/berkeley-softfloat-3
- url = git://github.com/cota/berkeley-softfloat-3
+ url = https://github.com/cota/berkeley-softfloat-3
diff --git a/.mailmap b/.mailmap
index 6f2ff22a45..ed8faa5719 100644
--- a/.mailmap
+++ b/.mailmap
@@ -12,6 +12,7 @@ Fabrice Bellard <fabrice@bellard.org> bellard <bellard@c046a42c-6fe2-441c-8c8c-7
James Hogan <jhogan@kernel.org> <james.hogan@imgtec.com>
Jocelyn Mayer <l_indien@magic.fr> j_mayer <j_mayer@c046a42c-6fe2-441c-8c8c-71466251a162>
Paul Brook <paul@codesourcery.com> pbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>
+Yongbok Kim <yongbok.kim@mips.com> <yongbok.kim@imgtec.com>
Aleksandar Markovic <amarkovic@wavecomp.com> <aleksandar.markovic@mips.com>
Aleksandar Markovic <amarkovic@wavecomp.com> <aleksandar.markovic@imgtec.com>
Paul Burton <pburton@wavecomp.com> <paul.burton@mips.com>
diff --git a/.travis.yml b/.travis.yml
index 95be6ec59f..d472fd650b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -107,8 +107,14 @@ matrix:
- env: CONFIG="--disable-tcg"
TEST_CMD=""
compiler: gcc
- - env: CONFIG=""
+ # MacOSX builds
+ - env: CONFIG="--target-list=aarch64-softmmu,arm-softmmu,i386-softmmu,mips-softmmu,mips64-softmmu,ppc64-softmmu,riscv64-softmmu,s390x-softmmu,x86_64-softmmu"
os: osx
+ osx_image: xcode9.4
+ compiler: clang
+ - env: CONFIG="--target-list=i386-softmmu,ppc-softmmu,ppc64-softmmu,m68k-softmmu,x86_64-softmmu"
+ os: osx
+ osx_image: xcode10
compiler: clang
# Python builds
- env: CONFIG="--target-list=x86_64-softmmu"
@@ -117,6 +123,14 @@ matrix:
- env: CONFIG="--target-list=x86_64-softmmu"
python:
- "3.6"
+ # Acceptance (Functional) tests
+ - env: CONFIG="--python=/usr/bin/python3 --target-list=x86_64-softmmu"
+ TEST_CMD="make AVOCADO_SHOW=app check-acceptance"
+ addons:
+ apt:
+ packages:
+ - python3-pip
+ - python3.4-venv
# Using newer GCC with sanitizers
- addons:
apt:
diff --git a/MAINTAINERS b/MAINTAINERS
index 40672c4eba..1032406c56 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12,9 +12,14 @@ consult qemu-devel and not any specific individual privately.
Descriptions of section entries:
M: Mail patches to: FullName <address@domain>
+ Maintainers are looking after a certain area and must be CCed on
+ patches. They are considered the main contact point.
R: Designated reviewer: FullName <address@domain>
These reviewers should be CCed on patches.
+ Reviewers are familiar with the subject matter and provide feedback
+ even though they are not maintainers.
L: Mailing list that is relevant to this area
+ These lists should be CCed on patches.
W: Web-page with status/info
Q: Patchwork web based patch tracking system site
T: SCM tree type and location. Type is one of: git, hg, quilt, stgit.
@@ -74,7 +79,7 @@ S: Maintained
L: qemu-trivial@nongnu.org
K: ^Subject:.*(?i)trivial
T: git git://git.corpit.ru/qemu.git trivial-patches
-T: git git://github.com/vivier/qemu.git trivial-patches
+T: git https://github.com/vivier/qemu.git trivial-patches
Architecture support
--------------------
@@ -98,16 +103,16 @@ F: pc-bios/s390-ccw.img
F: target/s390x/
F: docs/vfio-ap.txt
K: ^Subject:.*(?i)s390x?
-T: git git://github.com/cohuck/qemu.git s390-next
+T: git https://github.com/cohuck/qemu.git s390-next
L: qemu-s390x@nongnu.org
Guest CPU cores (TCG):
----------------------
Overall
L: qemu-devel@nongnu.org
-M: Paolo Bonzini <pbonzini@redhat.com>
M: Peter Crosthwaite <crosthwaite.peter@gmail.com>
M: Richard Henderson <rth@twiddle.net>
+R: Paolo Bonzini <pbonzini@redhat.com>
S: Maintained
F: cpus.c
F: exec.c
@@ -190,6 +195,7 @@ F: disas/microblaze.c
MIPS
M: Aurelien Jarno <aurelien@aurel32.net>
M: Aleksandar Markovic <amarkovic@wavecomp.com>
+R: Stefan Markovic <smarkovic@wavecomp.com>
S: Maintained
F: target/mips/
F: hw/mips/
@@ -202,6 +208,8 @@ F: include/hw/intc/mips_gic.h
F: include/hw/timer/mips_gictimer.h
F: tests/tcg/mips/
F: disas/mips.c
+F: disas/nanomips.h
+F: disas/nanomips.cpp
Moxie
M: Anthony Green <green@moxielogic.com>
@@ -228,7 +236,6 @@ F: tests/tcg/openrisc/
PowerPC
M: David Gibson <david@gibson.dropbear.id.au>
-M: Alexander Graf <agraf@suse.de>
L: qemu-ppc@nongnu.org
S: Maintained
F: target/ppc/
@@ -239,8 +246,10 @@ F: disas/ppc.c
RISC-V
M: Michael Clark <mjc@sifive.com>
M: Palmer Dabbelt <palmer@sifive.com>
+M: Alistair Francis <Alistair.Francis@wdc.com>
M: Sagar Karandikar <sagark@eecs.berkeley.edu>
M: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
+L: qemu-riscv@nongnu.org
S: Maintained
F: target/riscv/
F: hw/riscv/
@@ -249,7 +258,6 @@ F: disas/riscv.c
S390
M: Richard Henderson <rth@twiddle.net>
-M: Alexander Graf <agraf@suse.de>
M: David Hildenbrand <david@redhat.com>
S: Maintained
F: target/s390x/
@@ -293,7 +301,7 @@ F: tests/tcg/x86_64/
F: hw/i386/
F: disas/i386.c
F: docs/qemu-cpu-models.texi
-T: git git://github.com/ehabkost/qemu.git x86-next
+T: git https://github.com/ehabkost/qemu.git x86-next
Xtensa
M: Max Filippov <jcmvbkbc@gmail.com>
@@ -334,18 +342,18 @@ F: target/arm/kvm.c
MIPS
M: James Hogan <jhogan@kernel.org>
+R: Stefan Markovic <smarkovic@wavecomp.com>
S: Maintained
F: target/mips/kvm.c
PPC
-M: Alexander Graf <agraf@suse.de>
+M: David Gibson <david@gibson.dropbear.id.au>
S: Maintained
F: target/ppc/kvm.c
S390
M: Christian Borntraeger <borntraeger@de.ibm.com>
M: Cornelia Huck <cohuck@redhat.com>
-M: Alexander Graf <agraf@suse.de>
S: Maintained
F: target/s390x/kvm.c
F: target/s390x/kvm_s390x.h
@@ -357,8 +365,8 @@ F: hw/intc/s390_flic.c
F: hw/intc/s390_flic_kvm.c
F: include/hw/s390x/s390_flic.h
F: gdb-xml/s390*.xml
-T: git git://github.com/cohuck/qemu.git s390-next
-T: git git://github.com/borntraeger/qemu.git s390-next
+T: git https://github.com/cohuck/qemu.git s390-next
+T: git https://github.com/borntraeger/qemu.git s390-next
L: qemu-s390x@nongnu.org
X86
@@ -434,8 +442,9 @@ ARM Machines
------------
Allwinner-a10
M: Beniamino Galvani <b.galvani@gmail.com>
+M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
-S: Maintained
+S: Odd Fixes
F: hw/*/allwinner*
F: include/hw/*/allwinner*
F: hw/arm/cubieboard.c
@@ -494,40 +503,46 @@ F: tests/test-arm-mptimer.c
Exynos
M: Igor Mitsyanko <i.mitsyanko@gmail.com>
+M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
-S: Maintained
+S: Odd Fixes
F: hw/*/exynos*
F: include/hw/arm/exynos4210.h
Calxeda Highbank
M: Rob Herring <robh@kernel.org>
+M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
-S: Maintained
+S: Odd Fixes
F: hw/arm/highbank.c
F: hw/net/xgmac.c
Canon DIGIC
M: Antony Pavlov <antonynpavlov@gmail.com>
+M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
-S: Maintained
+S: Odd Fixes
F: include/hw/arm/digic.h
F: hw/*/digic*
Gumstix
-M: Philippe Mathieu-Daudé <f4bug@amsat.org>
+M: Peter Maydell <peter.maydell@linaro.org>
+R: Philippe Mathieu-Daudé <f4bug@amsat.org>
L: qemu-devel@nongnu.org
L: qemu-arm@nongnu.org
S: Odd Fixes
F: hw/arm/gumstix.c
-i.MX31
+i.MX31 (kzm)
M: Peter Chubb <peter.chubb@nicta.com.au>
+M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
-S: Odd fixes
-F: hw/*/imx*
-F: include/hw/*/imx*
+S: Odd Fixes
F: hw/arm/kzm.c
-F: include/hw/arm/fsl-imx31.h
+F: hw/*/imx_*
+F: hw/*/*imx31*
+F: include/hw/*/imx_*
+F: include/hw/*/*imx31*
Integrator CP
M: Peter Maydell <peter.maydell@linaro.org>
@@ -536,6 +551,28 @@ S: Maintained
F: hw/arm/integratorcp.c
F: hw/misc/arm_integrator_debug.c
+MCIMX6UL EVK / i.MX6ul
+M: Peter Maydell <peter.maydell@linaro.org>
+R: Jean-Christophe Dubois <jcd@tribudubois.net>
+L: qemu-arm@nongnu.org
+S: Odd Fixes
+F: hw/arm/mcimx6ul-evk.c
+F: hw/arm/fsl-imx6ul.c
+F: hw/misc/imx6ul_ccm.c
+F: include/hw/arm/fsl-imx6ul.h
+F: include/hw/misc/imx6ul_ccm.h
+
+MCIMX7D SABRE / i.MX7
+M: Peter Maydell <peter.maydell@linaro.org>
+R: Andrey Smirnov <andrew.smirnov@gmail.com>
+L: qemu-arm@nongnu.org
+S: Odd Fixes
+F: hw/arm/mcimx7d-sabre.c
+F: hw/arm/fsl-imx7.c
+F: include/hw/arm/fsl-imx7.h
+F: hw/pci-host/designware.c
+F: include/hw/pci-host/designware.h
+
MPS2
M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
@@ -553,22 +590,36 @@ F: include/hw/misc/iotkit-sysinfo.h
Musicpal
M: Jan Kiszka <jan.kiszka@web.de>
+M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
-S: Maintained
+S: Odd Fixes
F: hw/arm/musicpal.c
nSeries
M: Andrzej Zaborowski <balrogg@gmail.com>
+M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
-S: Maintained
+S: Odd Fixes
F: hw/arm/nseries.c
Palm
M: Andrzej Zaborowski <balrogg@gmail.com>
+M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
-S: Maintained
+S: Odd Fixes
F: hw/arm/palm.c
+Raspberry Pi
+M: Peter Maydell <peter.maydell@linaro.org>
+R: Andrew Baumann <Andrew.Baumann@microsoft.com>
+R: Philippe Mathieu-Daudé <f4bug@amsat.org>
+L: qemu-arm@nongnu.org
+S: Odd Fixes
+F: hw/arm/raspi_platform.h
+F: hw/*/bcm283*
+F: include/hw/arm/raspi*
+F: include/hw/*/bcm283*
+
Real View
M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
@@ -580,8 +631,9 @@ F: include/hw/intc/realview_gic.h
PXA2XX
M: Andrzej Zaborowski <balrogg@gmail.com>
+M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
-S: Maintained
+S: Odd Fixes
F: hw/arm/mainstone.c
F: hw/arm/spitz.c
F: hw/arm/tosa.c
@@ -590,12 +642,38 @@ F: hw/*/pxa2xx*
F: hw/misc/mst_fpga.c
F: include/hw/arm/pxa.h
+SABRELITE / i.MX6
+M: Peter Maydell <peter.maydell@linaro.org>
+R: Jean-Christophe Dubois <jcd@tribudubois.net>
+L: qemu-arm@nongnu.org
+S: Odd Fixes
+F: hw/arm/sabrelite.c
+F: hw/arm/fsl-imx6.c
+F: hw/misc/imx6_src.c
+F: hw/ssi/imx_spi.c
+F: include/hw/arm/fsl-imx6.h
+F: include/hw/misc/imx6_src.h
+F: include/hw/ssi/imx_spi.h
+
+Sharp SL-5500 (Collie) PDA
+M: Peter Maydell <peter.maydell@linaro.org>
+L: qemu-arm@nongnu.org
+S: Odd Fixes
+F: hw/arm/collie.c
+F: hw/arm/strongarm*
+
Stellaris
M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
S: Maintained
F: hw/*/stellaris*
+Versatile Express
+M: Peter Maydell <peter.maydell@linaro.org>
+L: qemu-arm@nongnu.org
+S: Maintained
+F: hw/arm/vexpress.c
+
Versatile PB
M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
@@ -603,9 +681,17 @@ S: Maintained
F: hw/*/versatile*
F: hw/misc/arm_sysctl.c
+Virt
+M: Peter Maydell <peter.maydell@linaro.org>
+L: qemu-arm@nongnu.org
+S: Maintained
+F: hw/arm/virt*
+F: include/hw/arm/virt.h
+
Xilinx Zynq
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
M: Alistair Francis <alistair@alistair23.me>
+M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
S: Maintained
F: hw/*/xilinx_*
@@ -617,13 +703,13 @@ X: hw/ssi/xilinx_*
Xilinx ZynqMP
M: Alistair Francis <alistair@alistair23.me>
M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
+M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
S: Maintained
F: hw/*/xlnx*.c
F: include/hw/*/xlnx*.h
ARM ACPI Subsystem
-M: Shannon Zhao <zhaoshenglong@huawei.com>
M: Shannon Zhao <shannon.zhaosl@gmail.com>
L: qemu-arm@nongnu.org
S: Maintained
@@ -631,6 +717,7 @@ F: hw/arm/virt-acpi-build.c
STM32F205
M: Alistair Francis <alistair@alistair23.me>
+M: Peter Maydell <peter.maydell@linaro.org>
S: Maintained
F: hw/arm/stm32f205_soc.c
F: hw/misc/stm32f2xx_syscfg.c
@@ -642,11 +729,13 @@ F: include/hw/*/stm32*.h
Netduino 2
M: Alistair Francis <alistair@alistair23.me>
+M: Peter Maydell <peter.maydell@linaro.org>
S: Maintained
F: hw/arm/netduino2.c
SmartFusion2
M: Subbaraya Sundeep <sundeep.lkml@gmail.com>
+M: Peter Maydell <peter.maydell@linaro.org>
S: Maintained
F: hw/arm/msf2-soc.c
F: hw/misc/msf2-sysreg.c
@@ -659,11 +748,13 @@ F: include/hw/ssi/mss-spi.h
Emcraft M2S-FG484
M: Subbaraya Sundeep <sundeep.lkml@gmail.com>
+M: Peter Maydell <peter.maydell@linaro.org>
S: Maintained
F: hw/arm/msf2-som.c
ASPEED BMCs
M: Cédric Le Goater <clg@kaod.org>
+M: Peter Maydell <peter.maydell@linaro.org>
R: Andrew Jeffery <andrew@aj.id.au>
R: Joel Stanley <joel@jms.id.au>
L: qemu-arm@nongnu.org
@@ -675,6 +766,7 @@ F: include/hw/net/ftgmac100.h
NRF51
M: Joel Stanley <joel@jms.id.au>
+M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
S: Maintained
F: hw/arm/nrf51_soc.c
@@ -734,27 +826,32 @@ MIPS Machines
-------------
Jazz
M: Hervé Poussineau <hpoussin@reactos.org>
+R: Stefan Markovic <smarkovic@wavecomp.com>
S: Maintained
F: hw/mips/mips_jazz.c
Malta
M: Aurelien Jarno <aurelien@aurel32.net>
+R: Stefan Markovic <smarkovic@wavecomp.com>
S: Maintained
F: hw/mips/mips_malta.c
Mipssim
M: Aleksandar Markovic <amarkovic@wavecomp.com>
+R: Stefan Markovic <smarkovic@wavecomp.com>
S: Odd Fixes
F: hw/mips/mips_mipssim.c
F: hw/net/mipsnet.c
R4000
M: Aurelien Jarno <aurelien@aurel32.net>
+R: Stefan Markovic <smarkovic@wavecomp.com>
S: Maintained
F: hw/mips/mips_r4k.c
Fulong 2E
M: Aleksandar Markovic <amarkovic@wavecomp.com>
+R: Stefan Markovic <smarkovic@wavecomp.com>
S: Odd Fixes
F: hw/mips/mips_fulong2e.c
F: hw/isa/vt82c686.c
@@ -763,6 +860,7 @@ F: include/hw/isa/vt82c686.h
Boston
M: Paul Burton <pburton@wavecomp.com>
+R: Stefan Markovic <smarkovic@wavecomp.com>
S: Maintained
F: hw/core/loader-fit.c
F: hw/mips/boston.c
@@ -778,21 +876,21 @@ F: hw/openrisc/openrisc_sim.c
PowerPC Machines
----------------
405
-M: Alexander Graf <agraf@suse.de>
+M: David Gibson <david@gibson.dropbear.id.au>
L: qemu-ppc@nongnu.org
S: Odd Fixes
F: hw/ppc/ppc405_boards.c
Bamboo
-M: Alexander Graf <agraf@suse.de>
+M: David Gibson <david@gibson.dropbear.id.au>
L: qemu-ppc@nongnu.org
S: Odd Fixes
F: hw/ppc/ppc440_bamboo.c
e500
-M: Alexander Graf <agraf@suse.de>
+M: David Gibson <david@gibson.dropbear.id.au>
L: qemu-ppc@nongnu.org
-S: Supported
+S: Odd Fixes
F: hw/ppc/e500.[hc]
F: hw/ppc/e500plat.c
F: include/hw/ppc/ppc_e500.h
@@ -800,16 +898,16 @@ F: include/hw/pci-host/ppce500.h
F: pc-bios/u-boot.e500
mpc8544ds
-M: Alexander Graf <agraf@suse.de>
+M: David Gibson <david@gibson.dropbear.id.au>
L: qemu-ppc@nongnu.org
-S: Supported
+S: Odd Fixes
F: hw/ppc/mpc8544ds.c
F: hw/ppc/mpc8544_guts.c
New World
-M: Alexander Graf <agraf@suse.de>
+M: David Gibson <david@gibson.dropbear.id.au>
L: qemu-ppc@nongnu.org
-S: Maintained
+S: Odd Fixes
F: hw/ppc/mac_newworld.c
F: hw/pci-host/uninorth.c
F: hw/pci-bridge/dec.[hc]
@@ -821,9 +919,9 @@ F: include/hw/misc/mos6522.h
F: include/hw/ppc/mac_dbdma.h
Old World
-M: Alexander Graf <agraf@suse.de>
+M: David Gibson <david@gibson.dropbear.id.au>
L: qemu-ppc@nongnu.org
-S: Maintained
+S: Odd Fixes
F: hw/ppc/mac_oldworld.c
F: hw/pci-host/grackle.c
F: hw/misc/macio/
@@ -848,7 +946,6 @@ F: pc-bios/ppc_rom.bin
sPAPR
M: David Gibson <david@gibson.dropbear.id.au>
-M: Alexander Graf <agraf@suse.de>
L: qemu-ppc@nongnu.org
S: Supported
F: hw/*/spapr*
@@ -931,7 +1028,6 @@ S390 Machines
S390 Virtio-ccw
M: Cornelia Huck <cohuck@redhat.com>
M: Christian Borntraeger <borntraeger@de.ibm.com>
-M: Alexander Graf <agraf@suse.de>
S: Supported
F: hw/char/sclp*.[hc]
F: hw/char/terminal3270.c
@@ -940,17 +1036,24 @@ F: include/hw/s390x/
F: hw/watchdog/wdt_diag288.c
F: include/hw/watchdog/wdt_diag288.h
F: default-configs/s390x-softmmu.mak
-T: git git://github.com/cohuck/qemu.git s390-next
-T: git git://github.com/borntraeger/qemu.git s390-next
+T: git https://github.com/cohuck/qemu.git s390-next
+T: git https://github.com/borntraeger/qemu.git s390-next
L: qemu-s390x@nongnu.org
-S390-ccw Bios
+S390-ccw boot
M: Christian Borntraeger <borntraeger@de.ibm.com>
M: Thomas Huth <thuth@redhat.com>
S: Supported
+F: hw/s390x/ipl.*
F: pc-bios/s390-ccw/
F: pc-bios/s390-ccw.img
-T: git git://github.com/borntraeger/qemu.git s390-next
+T: git https://github.com/borntraeger/qemu.git s390-next
+L: qemu-s390x@nongnu.org
+
+S390 PCI
+M: Collin Walling <walling@linux.ibm.com>
+S: Supported
+F: hw/s390x/s390-pci*
L: qemu-s390x@nongnu.org
UniCore32 Machines
@@ -1020,7 +1123,7 @@ S: Supported
F: hw/core/machine.c
F: hw/core/null-machine.c
F: include/hw/boards.h
-T: git git://github.com/ehabkost/qemu.git machine-next
+T: git https://github.com/ehabkost/qemu.git machine-next
Xtensa Machines
---------------
@@ -1056,7 +1159,7 @@ F: tests/ide-test.c
F: tests/ahci-test.c
F: tests/cdrom-test.c
F: tests/libqos/ahci*
-T: git git://github.com/jnsnow/qemu.git ide
+T: git https://github.com/jnsnow/qemu.git ide
IPMI
M: Corey Minyard <minyard@acm.org>
@@ -1065,7 +1168,7 @@ F: include/hw/ipmi/*
F: hw/ipmi/*
F: hw/smbios/smbios_type_38.c
F: tests/ipmi*
-T: git git://github.com/cminyard/qemu.git master-ipmi-rebase
+T: git https://github.com/cminyard/qemu.git master-ipmi-rebase
Floppy
M: John Snow <jsnow@redhat.com>
@@ -1074,7 +1177,7 @@ S: Supported
F: hw/block/fdc.c
F: include/hw/block/fdc.h
F: tests/fdc-test.c
-T: git git://github.com/jnsnow/qemu.git ide
+T: git https://github.com/jnsnow/qemu.git ide
OMAP
M: Peter Maydell <peter.maydell@linaro.org>
@@ -1113,9 +1216,11 @@ F: hw/i386/acpi-build.[hc]
F: hw/arm/virt-acpi-build.c
F: tests/bios-tables-test.c
F: tests/acpi-utils.[hc]
+F: tests/acpi-test-data/*
+F: tests/acpi-test-data/*/*
ppc4xx
-M: Alexander Graf <agraf@suse.de>
+M: David Gibson <david@gibson.dropbear.id.au>
L: qemu-ppc@nongnu.org
S: Odd Fixes
F: hw/ppc/ppc4*.c
@@ -1124,15 +1229,16 @@ F: include/hw/ppc/ppc4xx.h
F: include/hw/i2c/ppc4xx_i2c.h
ppce500
-M: Alexander Graf <agraf@suse.de>
+M: David Gibson <david@gibson.dropbear.id.au>
L: qemu-ppc@nongnu.org
-S: Supported
+S: Odd Fixes
F: hw/ppc/e500*
F: hw/pci-host/ppce500.c
F: hw/net/fsl_etsec/
Character devices
-M: Paolo Bonzini <pbonzini@redhat.com>
+M: Marc-André Lureau <marcandre.lureau@redhat.com>
+R: Paolo Bonzini <pbonzini@redhat.com>
S: Odd Fixes
F: hw/char/
@@ -1142,7 +1248,7 @@ S: Odd Fixes
F: hw/net/
F: include/hw/net/
F: tests/virtio-net-test.c
-T: git git://github.com/jasowang/qemu.git net
+T: git https://github.com/jasowang/qemu.git net
SCSI
M: Paolo Bonzini <pbonzini@redhat.com>
@@ -1151,7 +1257,7 @@ S: Supported
F: include/hw/scsi/*
F: hw/scsi/*
F: tests/virtio-scsi-test.c
-T: git git://github.com/bonzini/qemu.git scsi-next
+T: git https://github.com/bonzini/qemu.git scsi-next
SSI
M: Peter Crosthwaite <crosthwaite.peter@gmail.com>
@@ -1202,11 +1308,13 @@ F: include/hw/vfio/
vfio-ccw
M: Cornelia Huck <cohuck@redhat.com>
+M: Eric Farman <farman@linux.ibm.com>
+M: Farhan Ali <alifm@linux.ibm.com>
S: Supported
F: hw/vfio/ccw.c
F: hw/s390x/s390-ccw.c
F: include/hw/s390x/s390-ccw.h
-T: git git://github.com/cohuck/qemu.git s390-next
+T: git https://github.com/cohuck/qemu.git s390-next
L: qemu-s390x@nongnu.org
vfio-ap
@@ -1245,7 +1353,7 @@ S: Supported
F: hw/9pfs/
F: fsdev/
F: tests/virtio-9p-test.c
-T: git git://github.com/gkurz/qemu.git 9p-next
+T: git https://github.com/gkurz/qemu.git 9p-next
virtio-blk
M: Stefan Hajnoczi <stefanha@redhat.com>
@@ -1254,16 +1362,16 @@ S: Supported
F: hw/block/virtio-blk.c
F: hw/block/dataplane/*
F: tests/virtio-blk-test.c
-T: git git://github.com/stefanha/qemu.git block
+T: git https://github.com/stefanha/qemu.git block
virtio-ccw
M: Cornelia Huck <cohuck@redhat.com>
-M: Christian Borntraeger <borntraeger@de.ibm.com>
+M: Halil Pasic <pasic@linux.ibm.com>
S: Supported
F: hw/s390x/virtio-ccw*.[hc]
F: hw/s390x/vhost-vsock-ccw.c
-T: git git://github.com/cohuck/qemu.git s390-next
-T: git git://github.com/borntraeger/qemu.git s390-next
+T: git https://github.com/cohuck/qemu.git s390-next
+T: git https://github.com/borntraeger/qemu.git s390-next
L: qemu-s390x@nongnu.org
virtio-input
@@ -1367,7 +1475,7 @@ Intel Hexadecimal Object File Loader
M: Su Hang <suhang16@mails.ucas.ac.cn>
S: Maintained
F: tests/hexloader-test.c
-F: tests/hex-loader-check-data/test.hex
+F: tests/data/hex-loader/test.hex
CHRP NVRAM
M: Thomas Huth <thuth@redhat.com>
@@ -1453,7 +1561,7 @@ F: tests/qemu-iotests/
F: util/qemu-progress.c
F: qobject/block-qdict.c
F: tests/check-block-qdict.c
-T: git git://repo.or.cz/qemu/kevin.git block
+T: git https://repo.or.cz/qemu/kevin.git block
Block I/O path
M: Stefan Hajnoczi <stefanha@redhat.com>
@@ -1467,7 +1575,7 @@ F: migration/block*
F: include/block/aio.h
F: include/block/aio-wait.h
F: scripts/qemugdb/aio.py
-T: git git://github.com/stefanha/qemu.git block
+T: git https://github.com/stefanha/qemu.git block
Block SCSI subsystem
M: Paolo Bonzini <pbonzini@redhat.com>
@@ -1491,7 +1599,7 @@ F: block/commit.c
F: block/stream.c
F: block/mirror.c
F: qapi/job.json
-T: git git://github.com/codyprime/qemu-kvm-jtc.git block
+T: git https://github.com/codyprime/qemu-kvm-jtc.git block
Block QAPI, monitor, command line
M: Markus Armbruster <armbru@redhat.com>
@@ -1500,7 +1608,7 @@ F: blockdev.c
F: block/qapi.c
F: qapi/block*.json
F: qapi/transaction.json
-T: git git://repo.or.cz/qemu/armbru.git block-next
+T: git https://repo.or.cz/qemu/armbru.git block-next
Dirty Bitmaps
M: Fam Zheng <famz@redhat.com>
@@ -1513,12 +1621,12 @@ F: include/qemu/hbitmap.h
F: include/block/dirty-bitmap.h
F: tests/test-hbitmap.c
F: docs/interop/bitmaps.rst
-T: git git://github.com/famz/qemu.git bitmaps
-T: git git://github.com/jnsnow/qemu.git bitmaps
+T: git https://github.com/famz/qemu.git bitmaps
+T: git https://github.com/jnsnow/qemu.git bitmaps
Character device backends
-M: Paolo Bonzini <pbonzini@redhat.com>
M: Marc-André Lureau <marcandre.lureau@redhat.com>
+R: Paolo Bonzini <pbonzini@redhat.com>
S: Maintained
F: chardev/
F: include/chardev/
@@ -1638,7 +1746,7 @@ M: Jason Wang <jasowang@redhat.com>
S: Maintained
F: net/
F: include/net/
-T: git git://github.com/jasowang/qemu.git net
+T: git https://github.com/jasowang/qemu.git net
F: qapi/net.json
Netmap network backend
@@ -1654,7 +1762,7 @@ M: Eduardo Habkost <ehabkost@redhat.com>
S: Maintained
F: numa.c
F: include/sysemu/numa.h
-T: git git://github.com/ehabkost/qemu.git machine-next
+T: git https://github.com/ehabkost/qemu.git machine-next
Host Memory Backends
M: Eduardo Habkost <ehabkost@redhat.com>
@@ -1662,7 +1770,7 @@ M: Igor Mammedov <imammedo@redhat.com>
S: Maintained
F: backends/hostmem*.c
F: include/sysemu/hostmem.h
-T: git git://github.com/ehabkost/qemu.git machine-next
+T: git https://github.com/ehabkost/qemu.git machine-next
Cryptodev Backends
M: Gonglei <arei.gonglei@huawei.com>
@@ -1695,14 +1803,14 @@ F: tests/test-visitor-serialization.c
F: scripts/qapi-gen.py
F: scripts/qapi/*
F: docs/devel/qapi*
-T: git git://repo.or.cz/qemu/armbru.git qapi-next
+T: git https://repo.or.cz/qemu/armbru.git qapi-next
QAPI Schema
M: Eric Blake <eblake@redhat.com>
M: Markus Armbruster <armbru@redhat.com>
S: Supported
F: qapi/*.json
-T: git git://repo.or.cz/qemu/armbru.git qapi-next
+T: git https://repo.or.cz/qemu/armbru.git qapi-next
QObject
M: Markus Armbruster <armbru@redhat.com>
@@ -1716,7 +1824,7 @@ F: tests/check-qnum.c
F: tests/check-qjson.c
F: tests/check-qlist.c
F: tests/check-qstring.c
-T: git git://repo.or.cz/qemu/armbru.git qapi-next
+T: git https://repo.or.cz/qemu/armbru.git qapi-next
QEMU Guest Agent
M: Michael Roth <mdroth@linux.vnet.ibm.com>
@@ -1726,12 +1834,12 @@ F: qemu-ga.texi
F: scripts/qemu-guest-agent/
F: tests/test-qga.c
F: docs/interop/qemu-ga-ref.texi
-T: git git://github.com/mdroth/qemu.git qga
+T: git https://github.com/mdroth/qemu.git qga
QOM
M: Andreas Färber <afaerber@suse.de>
S: Supported
-T: git git://github.com/afaerber/qemu-cpu.git qom-next
+T: git https://github.com/afaerber/qemu-cpu.git qom-next
F: include/qom/
X: include/qom/cpu.h
F: qom/
@@ -1748,12 +1856,12 @@ F: docs/devel/*qmp-*
F: scripts/qmp/
F: tests/qmp-test.c
F: tests/qmp-cmd-test.c
-T: git git://repo.or.cz/qemu/armbru.git qapi-next
+T: git https://repo.or.cz/qemu/armbru.git qapi-next
qtest
-M: Paolo Bonzini <pbonzini@redhat.com>
M: Thomas Huth <thuth@redhat.com>
M: Laurent Vivier <lvivier@redhat.com>
+R: Paolo Bonzini <pbonzini@redhat.com>
S: Maintained
F: qtest.c
F: tests/libqtest.*
@@ -1791,10 +1899,10 @@ F: qemu-option-trace.texi
F: scripts/tracetool.py
F: scripts/tracetool/
F: docs/devel/tracing.txt
-T: git git://github.com/stefanha/qemu.git tracing
+T: git https://github.com/stefanha/qemu.git tracing
TPM
-M: Stefan Berger <stefanb@linux.vnet.ibm.com>
+M: Stefan Berger <stefanb@linux.ibm.com>
S: Maintained
F: tpm.c
F: stubs/tpm.c
@@ -1804,7 +1912,7 @@ F: include/sysemu/tpm*
F: qapi/tpm.json
F: backends/tpm.c
F: tests/*tpm*
-T: git git://github.com/stefanberger/qemu-tpm.git tpm-next
+T: git https://github.com/stefanberger/qemu-tpm.git tpm-next
Checkpatch
S: Odd Fixes
@@ -1860,7 +1968,6 @@ F: tests/test-io-*
Sockets
M: Daniel P. Berrange <berrange@redhat.com>
M: Gerd Hoffmann <kraxel@redhat.com>
-M: Paolo Bonzini <pbonzini@redhat.com>
S: Maintained
F: include/qemu/sockets.h
F: util/qemu-sockets.c
@@ -1976,6 +2083,7 @@ F: disas/i386.c
MIPS target
M: Aurelien Jarno <aurelien@aurel32.net>
+R: Stefan Markovic <smarkovic@wavecomp.com>
S: Maintained
F: tcg/mips/
F: disas/mips.c
@@ -1987,7 +2095,6 @@ F: tcg/ppc/
F: disas/ppc.c
S390 target
-M: Alexander Graf <agraf@suse.de>
M: Richard Henderson <rth@twiddle.net>
S: Maintained
F: tcg/s390/
@@ -2020,23 +2127,22 @@ M: Jeff Cody <jcody@redhat.com>
L: qemu-block@nongnu.org
S: Supported
F: block/rbd.c
-T: git git://github.com/codyprime/qemu-kvm-jtc.git block
+T: git https://github.com/codyprime/qemu-kvm-jtc.git block
Sheepdog
M: Liu Yuan <namei.unix@gmail.com>
M: Jeff Cody <jcody@redhat.com>
L: qemu-block@nongnu.org
-L: sheepdog@lists.wpkg.org
S: Supported
F: block/sheepdog.c
-T: git git://github.com/codyprime/qemu-kvm-jtc.git block
+T: git https://github.com/codyprime/qemu-kvm-jtc.git block
VHDX
M: Jeff Cody <jcody@redhat.com>
L: qemu-block@nongnu.org
S: Supported
F: block/vhdx*
-T: git git://github.com/codyprime/qemu-kvm-jtc.git block
+T: git https://github.com/codyprime/qemu-kvm-jtc.git block
VDI
M: Stefan Weil <sw@weilnetz.de>
@@ -2049,13 +2155,12 @@ M: Ronnie Sahlberg <ronniesahlberg@gmail.com>
M: Paolo Bonzini <pbonzini@redhat.com>
M: Peter Lieven <pl@kamp.de>
L: qemu-block@nongnu.org
-S: Supported
+S: Odd Fixes
F: block/iscsi.c
F: block/iscsi-opts.c
Network Block Device (NBD)
M: Eric Blake <eblake@redhat.com>
-M: Paolo Bonzini <pbonzini@redhat.com>
L: qemu-block@nongnu.org
S: Maintained
F: block/nbd*
@@ -2064,7 +2169,7 @@ F: include/block/nbd*
F: qemu-nbd.*
F: blockdev-nbd.c
F: docs/interop/nbd.txt
-T: git git://repo.or.cz/qemu/ericb.git nbd
+T: git https://repo.or.cz/qemu/ericb.git nbd
NFS
M: Jeff Cody <jcody@redhat.com>
@@ -2072,7 +2177,7 @@ M: Peter Lieven <pl@kamp.de>
L: qemu-block@nongnu.org
S: Maintained
F: block/nfs.c
-T: git git://github.com/codyprime/qemu-kvm-jtc.git block
+T: git https://github.com/codyprime/qemu-kvm-jtc.git block
SSH
M: Richard W.M. Jones <rjones@redhat.com>
@@ -2080,21 +2185,21 @@ M: Jeff Cody <jcody@redhat.com>
L: qemu-block@nongnu.org
S: Supported
F: block/ssh.c
-T: git git://github.com/codyprime/qemu-kvm-jtc.git block
+T: git https://github.com/codyprime/qemu-kvm-jtc.git block
CURL
M: Jeff Cody <jcody@redhat.com>
L: qemu-block@nongnu.org
S: Supported
F: block/curl.c
-T: git git://github.com/codyprime/qemu-kvm-jtc.git block
+T: git https://github.com/codyprime/qemu-kvm-jtc.git block
GLUSTER
M: Jeff Cody <jcody@redhat.com>
L: qemu-block@nongnu.org
S: Supported
F: block/gluster.c
-T: git git://github.com/codyprime/qemu-kvm-jtc.git block
+T: git https://github.com/codyprime/qemu-kvm-jtc.git block
Null Block Driver
M: Fam Zheng <famz@redhat.com>
diff --git a/README b/README
index 49a9fd09cd..441c33eb2f 100644
--- a/README
+++ b/README
@@ -54,7 +54,7 @@ Submitting patches
The QEMU source code is maintained under the GIT version control system.
- git clone git://git.qemu.org/qemu.git
+ git clone https://git.qemu.org/git/qemu.git
When submitting patches, one common approach is to use 'git
format-patch' and/or 'git send-email' to format & send the mail to the
@@ -70,7 +70,7 @@ the QEMU website
The QEMU website is also maintained under source control.
- git clone git://git.qemu.org/qemu-web.git
+ git clone https://git.qemu.org/git/qemu-web.git
https://www.qemu.org/2017/02/04/the-new-qemu-website-is-up/
A 'git-publish' utility was created to make above process less
diff --git a/VERSION b/VERSION
index 929fd9fc83..3af1c224ad 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.0.50
+3.0.91
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index de12f78eb8..4880a05399 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -79,6 +79,7 @@ struct KVMState
int fd;
int vmfd;
int coalesced_mmio;
+ int coalesced_pio;
struct kvm_coalesced_mmio_ring *coalesced_mmio_ring;
bool coalesced_flush_in_progress;
int vcpu_events;
@@ -560,6 +561,45 @@ static void kvm_uncoalesce_mmio_region(MemoryListener *listener,
}
}
+static void kvm_coalesce_pio_add(MemoryListener *listener,
+ MemoryRegionSection *section,
+ hwaddr start, hwaddr size)
+{
+ KVMState *s = kvm_state;
+
+ if (s->coalesced_pio) {
+ struct kvm_coalesced_mmio_zone zone;
+
+ zone.addr = start;
+ zone.size = size;
+ zone.pio = 1;
+
+ (void)kvm_vm_ioctl(s, KVM_REGISTER_COALESCED_MMIO, &zone);
+ }
+}
+
+static void kvm_coalesce_pio_del(MemoryListener *listener,
+ MemoryRegionSection *section,
+ hwaddr start, hwaddr size)
+{
+ KVMState *s = kvm_state;
+
+ if (s->coalesced_pio) {
+ struct kvm_coalesced_mmio_zone zone;
+
+ zone.addr = start;
+ zone.size = size;
+ zone.pio = 1;
+
+ (void)kvm_vm_ioctl(s, KVM_UNREGISTER_COALESCED_MMIO, &zone);
+ }
+}
+
+static MemoryListener kvm_coalesced_pio_listener = {
+ .coalesced_io_add = kvm_coalesce_pio_add,
+ .coalesced_io_del = kvm_coalesce_pio_del,
+};
+
int kvm_check_extension(KVMState *s, unsigned int extension)
{
int ret;
@@ -1616,6 +1656,8 @@ static int kvm_init(MachineState *ms)
}
s->coalesced_mmio = kvm_check_extension(s, KVM_CAP_COALESCED_MMIO);
+ s->coalesced_pio = s->coalesced_mmio &&
+ kvm_check_extension(s, KVM_CAP_COALESCED_PIO);
#ifdef KVM_CAP_VCPU_EVENTS
s->vcpu_events = kvm_check_extension(s, KVM_CAP_VCPU_EVENTS);
@@ -1686,13 +1728,15 @@ static int kvm_init(MachineState *ms)
s->memory_listener.listener.eventfd_add = kvm_mem_ioeventfd_add;
s->memory_listener.listener.eventfd_del = kvm_mem_ioeventfd_del;
}
- s->memory_listener.listener.coalesced_mmio_add = kvm_coalesce_mmio_region;
- s->memory_listener.listener.coalesced_mmio_del = kvm_uncoalesce_mmio_region;
+ s->memory_listener.listener.coalesced_io_add = kvm_coalesce_mmio_region;
+ s->memory_listener.listener.coalesced_io_del = kvm_uncoalesce_mmio_region;
kvm_memory_listener_register(s, &s->memory_listener,
&address_space_memory, 0);
memory_listener_register(&kvm_io_listener,
&address_space_io);
+ memory_listener_register(&kvm_coalesced_pio_listener,
+ &address_space_io);
s->many_ioeventfds = kvm_check_many_ioeventfds();
@@ -1778,7 +1822,13 @@ void kvm_flush_coalesced_mmio_buffer(void)
ent = &ring->coalesced_mmio[ring->first];
- cpu_physical_memory_write(ent->phys_addr, ent->data, ent->len);
+ if (ent->pio == 1) {
+ address_space_rw(&address_space_io, ent->phys_addr,
+ MEMTXATTRS_UNSPECIFIED, ent->data,
+ ent->len, true);
+ } else {
+ cpu_physical_memory_write(ent->phys_addr, ent->data, ent->len);
+ }
smp_wmb();
ring->first = (ring->first + 1) % KVM_COALESCED_MMIO_MAX;
}
diff --git a/accel/tcg/atomic_template.h b/accel/tcg/atomic_template.h
index d751bcba48..efde12fdb2 100644
--- a/accel/tcg/atomic_template.h
+++ b/accel/tcg/atomic_template.h
@@ -100,19 +100,24 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
DATA_TYPE ret;
ATOMIC_TRACE_RMW;
+#if DATA_SIZE == 16
+ ret = atomic16_cmpxchg(haddr, cmpv, newv);
+#else
ret = atomic_cmpxchg__nocheck(haddr, cmpv, newv);
+#endif
ATOMIC_MMU_CLEANUP;
return ret;
}
#if DATA_SIZE >= 16
+#if HAVE_ATOMIC128
ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr EXTRA_ARGS)
{
ATOMIC_MMU_DECLS;
DATA_TYPE val, *haddr = ATOMIC_MMU_LOOKUP;
ATOMIC_TRACE_LD;
- __atomic_load(haddr, &val, __ATOMIC_RELAXED);
+ val = atomic16_read(haddr);
ATOMIC_MMU_CLEANUP;
return val;
}
@@ -124,9 +129,10 @@ void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr,
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
ATOMIC_TRACE_ST;
- __atomic_store(haddr, &val, __ATOMIC_RELAXED);
+ atomic16_set(haddr, val);
ATOMIC_MMU_CLEANUP;
}
+#endif
#else
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr,
ABI_TYPE val EXTRA_ARGS)
@@ -228,19 +234,24 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
DATA_TYPE ret;
ATOMIC_TRACE_RMW;
+#if DATA_SIZE == 16
+ ret = atomic16_cmpxchg(haddr, BSWAP(cmpv), BSWAP(newv));
+#else
ret = atomic_cmpxchg__nocheck(haddr, BSWAP(cmpv), BSWAP(newv));
+#endif
ATOMIC_MMU_CLEANUP;
return BSWAP(ret);
}
#if DATA_SIZE >= 16
+#if HAVE_ATOMIC128
ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr EXTRA_ARGS)
{
ATOMIC_MMU_DECLS;
DATA_TYPE val, *haddr = ATOMIC_MMU_LOOKUP;
ATOMIC_TRACE_LD;
- __atomic_load(haddr, &val, __ATOMIC_RELAXED);
+ val = atomic16_read(haddr);
ATOMIC_MMU_CLEANUP;
return BSWAP(val);
}
@@ -253,9 +264,10 @@ void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr,
ATOMIC_TRACE_ST;
val = BSWAP(val);
- __atomic_store(haddr, &val, __ATOMIC_RELAXED);
+ atomic16_set(haddr, val);
ATOMIC_MMU_CLEANUP;
}
+#endif
#else
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr,
ABI_TYPE val EXTRA_ARGS)
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index 6bcb6d99bd..870027d435 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -416,7 +416,7 @@ static inline TranslationBlock *tb_find(CPUState *cpu,
}
#endif
/* See if we can patch the calling TB. */
- if (last_tb && !qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
+ if (last_tb) {
tb_add_jump(last_tb, tb_exit, tb);
}
return tb;
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index f4702ce91f..af6bd8ccf9 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -32,6 +32,7 @@
#include "exec/log.h"
#include "exec/helper-proto.h"
#include "qemu/atomic.h"
+#include "qemu/atomic128.h"
/* DEBUG defines, enable DEBUG_TLB_LOG to log to the CPU_LOG_MMU target */
/* #define DEBUG_TLB */
@@ -58,9 +59,9 @@
} \
} while (0)
-#define assert_cpu_is_self(this_cpu) do { \
+#define assert_cpu_is_self(cpu) do { \
if (DEBUG_TLB_GATE) { \
- g_assert(!cpu->created || qemu_cpu_is_self(cpu)); \
+ g_assert(!(cpu)->created || qemu_cpu_is_self(cpu)); \
} \
} while (0)
@@ -73,6 +74,16 @@ QEMU_BUILD_BUG_ON(sizeof(target_ulong) > sizeof(run_on_cpu_data));
QEMU_BUILD_BUG_ON(NB_MMU_MODES > 16);
#define ALL_MMUIDX_BITS ((1 << NB_MMU_MODES) - 1)
+void tlb_init(CPUState *cpu)
+{
+ CPUArchState *env = cpu->env_ptr;
+
+ qemu_spin_init(&env->tlb_c.lock);
+
+ /* Ensure that cpu_reset performs a full flush. */
+ env->tlb_c.dirty = ALL_MMUIDX_BITS;
+}
+
/* flush_all_helper: run fn across all cpus
*
* If the wait flag is set then the src cpu's helper will be queued as
@@ -92,128 +103,89 @@ static void flush_all_helper(CPUState *src, run_on_cpu_func fn,
}
}
-size_t tlb_flush_count(void)
+void tlb_flush_counts(size_t *pfull, size_t *ppart, size_t *pelide)
{
CPUState *cpu;
- size_t count = 0;
+ size_t full = 0, part = 0, elide = 0;
CPU_FOREACH(cpu) {
CPUArchState *env = cpu->env_ptr;
- count += atomic_read(&env->tlb_flush_count);
- }
- return count;
-}
-
-/* This is OK because CPU architectures generally permit an
- * implementation to drop entries from the TLB at any time, so
- * flushing more entries than required is only an efficiency issue,
- * not a correctness issue.
- */
-static void tlb_flush_nocheck(CPUState *cpu)
-{
- CPUArchState *env = cpu->env_ptr;
-
- /* The QOM tests will trigger tlb_flushes without setting up TCG
- * so we bug out here in that case.
- */
- if (!tcg_enabled()) {
- return;
- }
-
- assert_cpu_is_self(cpu);
- atomic_set(&env->tlb_flush_count, env->tlb_flush_count + 1);
- tlb_debug("(count: %zu)\n", tlb_flush_count());
-
- memset(env->tlb_table, -1, sizeof(env->tlb_table));
- memset(env->tlb_v_table, -1, sizeof(env->tlb_v_table));
- cpu_tb_jmp_cache_clear(cpu);
-
- env->vtlb_index = 0;
- env->tlb_flush_addr = -1;
- env->tlb_flush_mask = 0;
-
- atomic_mb_set(&cpu->pending_tlb_flush, 0);
-}
-
-static void tlb_flush_global_async_work(CPUState *cpu, run_on_cpu_data data)
-{
- tlb_flush_nocheck(cpu);
-}
-
-void tlb_flush(CPUState *cpu)
-{
- if (cpu->created && !qemu_cpu_is_self(cpu)) {
- if (atomic_mb_read(&cpu->pending_tlb_flush) != ALL_MMUIDX_BITS) {
- atomic_mb_set(&cpu->pending_tlb_flush, ALL_MMUIDX_BITS);
- async_run_on_cpu(cpu, tlb_flush_global_async_work,
- RUN_ON_CPU_NULL);
- }
- } else {
- tlb_flush_nocheck(cpu);
+ full += atomic_read(&env->tlb_c.full_flush_count);
+ part += atomic_read(&env->tlb_c.part_flush_count);
+ elide += atomic_read(&env->tlb_c.elide_flush_count);
}
+ *pfull = full;
+ *ppart = part;
+ *pelide = elide;
}
-void tlb_flush_all_cpus(CPUState *src_cpu)
-{
- const run_on_cpu_func fn = tlb_flush_global_async_work;
- flush_all_helper(src_cpu, fn, RUN_ON_CPU_NULL);
- fn(src_cpu, RUN_ON_CPU_NULL);
-}
-
-void tlb_flush_all_cpus_synced(CPUState *src_cpu)
+static void tlb_flush_one_mmuidx_locked(CPUArchState *env, int mmu_idx)
{
- const run_on_cpu_func fn = tlb_flush_global_async_work;
- flush_all_helper(src_cpu, fn, RUN_ON_CPU_NULL);
- async_safe_run_on_cpu(src_cpu, fn, RUN_ON_CPU_NULL);
+ memset(env->tlb_table[mmu_idx], -1, sizeof(env->tlb_table[0]));
+ memset(env->tlb_v_table[mmu_idx], -1, sizeof(env->tlb_v_table[0]));
+ env->tlb_d[mmu_idx].large_page_addr = -1;
+ env->tlb_d[mmu_idx].large_page_mask = -1;
+ env->tlb_d[mmu_idx].vindex = 0;
}
static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data)
{
CPUArchState *env = cpu->env_ptr;
- unsigned long mmu_idx_bitmask = data.host_int;
- int mmu_idx;
+ uint16_t asked = data.host_int;
+ uint16_t all_dirty, work, to_clean;
assert_cpu_is_self(cpu);
- tlb_debug("start: mmu_idx:0x%04lx\n", mmu_idx_bitmask);
+ tlb_debug("mmu_idx:0x%04" PRIx16 "\n", asked);
- for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
+ qemu_spin_lock(&env->tlb_c.lock);
- if (test_bit(mmu_idx, &mmu_idx_bitmask)) {
- tlb_debug("%d\n", mmu_idx);
+ all_dirty = env->tlb_c.dirty;
+ to_clean = asked & all_dirty;
+ all_dirty &= ~to_clean;
+ env->tlb_c.dirty = all_dirty;
- memset(env->tlb_table[mmu_idx], -1, sizeof(env->tlb_table[0]));
- memset(env->tlb_v_table[mmu_idx], -1, sizeof(env->tlb_v_table[0]));
- }
+ for (work = to_clean; work != 0; work &= work - 1) {
+ int mmu_idx = ctz32(work);
+ tlb_flush_one_mmuidx_locked(env, mmu_idx);
}
+ qemu_spin_unlock(&env->tlb_c.lock);
+
cpu_tb_jmp_cache_clear(cpu);
- tlb_debug("done\n");
+ if (to_clean == ALL_MMUIDX_BITS) {
+ atomic_set(&env->tlb_c.full_flush_count,
+ env->tlb_c.full_flush_count + 1);
+ } else {
+ atomic_set(&env->tlb_c.part_flush_count,
+ env->tlb_c.part_flush_count + ctpop16(to_clean));
+ if (to_clean != asked) {
+ atomic_set(&env->tlb_c.elide_flush_count,
+ env->tlb_c.elide_flush_count +
+ ctpop16(asked & ~to_clean));
+ }
+ }
}
void tlb_flush_by_mmuidx(CPUState *cpu, uint16_t idxmap)
{
tlb_debug("mmu_idx: 0x%" PRIx16 "\n", idxmap);
- if (!qemu_cpu_is_self(cpu)) {
- uint16_t pending_flushes = idxmap;
- pending_flushes &= ~atomic_mb_read(&cpu->pending_tlb_flush);
-
- if (pending_flushes) {
- tlb_debug("reduced mmu_idx: 0x%" PRIx16 "\n", pending_flushes);
-
- atomic_or(&cpu->pending_tlb_flush, pending_flushes);
- async_run_on_cpu(cpu, tlb_flush_by_mmuidx_async_work,
- RUN_ON_CPU_HOST_INT(pending_flushes));
- }
+ if (cpu->created && !qemu_cpu_is_self(cpu)) {
+ async_run_on_cpu(cpu, tlb_flush_by_mmuidx_async_work,
+ RUN_ON_CPU_HOST_INT(idxmap));
} else {
- tlb_flush_by_mmuidx_async_work(cpu,
- RUN_ON_CPU_HOST_INT(idxmap));
+ tlb_flush_by_mmuidx_async_work(cpu, RUN_ON_CPU_HOST_INT(idxmap));
}
}
+void tlb_flush(CPUState *cpu)
+{
+ tlb_flush_by_mmuidx(cpu, ALL_MMUIDX_BITS);
+}
+
void tlb_flush_by_mmuidx_all_cpus(CPUState *src_cpu, uint16_t idxmap)
{
const run_on_cpu_func fn = tlb_flush_by_mmuidx_async_work;
@@ -224,8 +196,12 @@ void tlb_flush_by_mmuidx_all_cpus(CPUState *src_cpu, uint16_t idxmap)
fn(src_cpu, RUN_ON_CPU_HOST_INT(idxmap));
}
-void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
- uint16_t idxmap)
+void tlb_flush_all_cpus(CPUState *src_cpu)
+{
+ tlb_flush_by_mmuidx_all_cpus(src_cpu, ALL_MMUIDX_BITS);
+}
+
+void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *src_cpu, uint16_t idxmap)
{
const run_on_cpu_func fn = tlb_flush_by_mmuidx_async_work;
@@ -235,70 +211,55 @@ void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
async_safe_run_on_cpu(src_cpu, fn, RUN_ON_CPU_HOST_INT(idxmap));
}
+void tlb_flush_all_cpus_synced(CPUState *src_cpu)
+{
+ tlb_flush_by_mmuidx_all_cpus_synced(src_cpu, ALL_MMUIDX_BITS);
+}
+
static inline bool tlb_hit_page_anyprot(CPUTLBEntry *tlb_entry,
target_ulong page)
{
return tlb_hit_page(tlb_entry->addr_read, page) ||
- tlb_hit_page(tlb_entry->addr_write, page) ||
+ tlb_hit_page(tlb_addr_write(tlb_entry), page) ||
tlb_hit_page(tlb_entry->addr_code, page);
}
-static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong page)
+/* Called with tlb_c.lock held */
+static inline void tlb_flush_entry_locked(CPUTLBEntry *tlb_entry,
+ target_ulong page)
{
if (tlb_hit_page_anyprot(tlb_entry, page)) {
memset(tlb_entry, -1, sizeof(*tlb_entry));
}
}
-static inline void tlb_flush_vtlb_page(CPUArchState *env, int mmu_idx,
- target_ulong page)
+/* Called with tlb_c.lock held */
+static inline void tlb_flush_vtlb_page_locked(CPUArchState *env, int mmu_idx,
+ target_ulong page)
{
int k;
+
+ assert_cpu_is_self(ENV_GET_CPU(env));
for (k = 0; k < CPU_VTLB_SIZE; k++) {
- tlb_flush_entry(&env->tlb_v_table[mmu_idx][k], page);
+ tlb_flush_entry_locked(&env->tlb_v_table[mmu_idx][k], page);
}
}
-static void tlb_flush_page_async_work(CPUState *cpu, run_on_cpu_data data)
+static void tlb_flush_page_locked(CPUArchState *env, int midx,
+ target_ulong page)
{
- CPUArchState *env = cpu->env_ptr;
- target_ulong addr = (target_ulong) data.target_ptr;
- int i;
- int mmu_idx;
-
- assert_cpu_is_self(cpu);
-
- tlb_debug("page :" TARGET_FMT_lx "\n", addr);
+ target_ulong lp_addr = env->tlb_d[midx].large_page_addr;
+ target_ulong lp_mask = env->tlb_d[midx].large_page_mask;
/* Check if we need to flush due to large pages. */
- if ((addr & env->tlb_flush_mask) == env->tlb_flush_addr) {
- tlb_debug("forcing full flush ("
+ if ((page & lp_mask) == lp_addr) {
+ tlb_debug("forcing full flush midx %d ("
TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
- env->tlb_flush_addr, env->tlb_flush_mask);
-
- tlb_flush(cpu);
- return;
- }
-
- addr &= TARGET_PAGE_MASK;
- i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
- tlb_flush_entry(&env->tlb_table[mmu_idx][i], addr);
- tlb_flush_vtlb_page(env, mmu_idx, addr);
- }
-
- tb_flush_jmp_cache(cpu, addr);
-}
-
-void tlb_flush_page(CPUState *cpu, target_ulong addr)
-{
- tlb_debug("page :" TARGET_FMT_lx "\n", addr);
-
- if (!qemu_cpu_is_self(cpu)) {
- async_run_on_cpu(cpu, tlb_flush_page_async_work,
- RUN_ON_CPU_TARGET_PTR(addr));
+ midx, lp_addr, lp_mask);
+ tlb_flush_one_mmuidx_locked(env, midx);
} else {
- tlb_flush_page_async_work(cpu, RUN_ON_CPU_TARGET_PTR(addr));
+ tlb_flush_entry_locked(tlb_entry(env, midx, page), page);
+ tlb_flush_vtlb_page_locked(env, midx, page);
}
}
@@ -314,47 +275,24 @@ static void tlb_flush_page_by_mmuidx_async_work(CPUState *cpu,
target_ulong addr_and_mmuidx = (target_ulong) data.target_ptr;
target_ulong addr = addr_and_mmuidx & TARGET_PAGE_MASK;
unsigned long mmu_idx_bitmap = addr_and_mmuidx & ALL_MMUIDX_BITS;
- int page = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
int mmu_idx;
assert_cpu_is_self(cpu);
- tlb_debug("page:%d addr:"TARGET_FMT_lx" mmu_idx:0x%lx\n",
- page, addr, mmu_idx_bitmap);
+ tlb_debug("page addr:" TARGET_FMT_lx " mmu_map:0x%lx\n",
+ addr, mmu_idx_bitmap);
+ qemu_spin_lock(&env->tlb_c.lock);
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
if (test_bit(mmu_idx, &mmu_idx_bitmap)) {
- tlb_flush_entry(&env->tlb_table[mmu_idx][page], addr);
- tlb_flush_vtlb_page(env, mmu_idx, addr);
+ tlb_flush_page_locked(env, mmu_idx, addr);
}
}
+ qemu_spin_unlock(&env->tlb_c.lock);
tb_flush_jmp_cache(cpu, addr);
}
-static void tlb_check_page_and_flush_by_mmuidx_async_work(CPUState *cpu,
- run_on_cpu_data data)
-{
- CPUArchState *env = cpu->env_ptr;
- target_ulong addr_and_mmuidx = (target_ulong) data.target_ptr;
- target_ulong addr = addr_and_mmuidx & TARGET_PAGE_MASK;
- unsigned long mmu_idx_bitmap = addr_and_mmuidx & ALL_MMUIDX_BITS;
-
- tlb_debug("addr:"TARGET_FMT_lx" mmu_idx: %04lx\n", addr, mmu_idx_bitmap);
-
- /* Check if we need to flush due to large pages. */
- if ((addr & env->tlb_flush_mask) == env->tlb_flush_addr) {
- tlb_debug("forced full flush ("
- TARGET_FMT_lx "/" TARGET_FMT_lx ")\n",
- env->tlb_flush_addr, env->tlb_flush_mask);
-
- tlb_flush_by_mmuidx_async_work(cpu,
- RUN_ON_CPU_HOST_INT(mmu_idx_bitmap));
- } else {
- tlb_flush_page_by_mmuidx_async_work(cpu, data);
- }
-}
-
void tlb_flush_page_by_mmuidx(CPUState *cpu, target_ulong addr, uint16_t idxmap)
{
target_ulong addr_and_mmu_idx;
@@ -366,18 +304,23 @@ void tlb_flush_page_by_mmuidx(CPUState *cpu, target_ulong addr, uint16_t idxmap)
addr_and_mmu_idx |= idxmap;
if (!qemu_cpu_is_self(cpu)) {
- async_run_on_cpu(cpu, tlb_check_page_and_flush_by_mmuidx_async_work,
+ async_run_on_cpu(cpu, tlb_flush_page_by_mmuidx_async_work,
RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx));
} else {
- tlb_check_page_and_flush_by_mmuidx_async_work(
+ tlb_flush_page_by_mmuidx_async_work(
cpu, RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx));
}
}
+void tlb_flush_page(CPUState *cpu, target_ulong addr)
+{
+ tlb_flush_page_by_mmuidx(cpu, addr, ALL_MMUIDX_BITS);
+}
+
void tlb_flush_page_by_mmuidx_all_cpus(CPUState *src_cpu, target_ulong addr,
uint16_t idxmap)
{
- const run_on_cpu_func fn = tlb_check_page_and_flush_by_mmuidx_async_work;
+ const run_on_cpu_func fn = tlb_flush_page_by_mmuidx_async_work;
target_ulong addr_and_mmu_idx;
tlb_debug("addr: "TARGET_FMT_lx" mmu_idx:%"PRIx16"\n", addr, idxmap);
@@ -390,11 +333,16 @@ void tlb_flush_page_by_mmuidx_all_cpus(CPUState *src_cpu, target_ulong addr,
fn(src_cpu, RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx));
}
+void tlb_flush_page_all_cpus(CPUState *src, target_ulong addr)
+{
+ tlb_flush_page_by_mmuidx_all_cpus(src, addr, ALL_MMUIDX_BITS);
+}
+
void tlb_flush_page_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
- target_ulong addr,
- uint16_t idxmap)
+ target_ulong addr,
+ uint16_t idxmap)
{
- const run_on_cpu_func fn = tlb_check_page_and_flush_by_mmuidx_async_work;
+ const run_on_cpu_func fn = tlb_flush_page_by_mmuidx_async_work;
target_ulong addr_and_mmu_idx;
tlb_debug("addr: "TARGET_FMT_lx" mmu_idx:%"PRIx16"\n", addr, idxmap);
@@ -407,21 +355,9 @@ void tlb_flush_page_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
async_safe_run_on_cpu(src_cpu, fn, RUN_ON_CPU_TARGET_PTR(addr_and_mmu_idx));
}
-void tlb_flush_page_all_cpus(CPUState *src, target_ulong addr)
+void tlb_flush_page_all_cpus_synced(CPUState *src, target_ulong addr)
{
- const run_on_cpu_func fn = tlb_flush_page_async_work;
-
- flush_all_helper(src, fn, RUN_ON_CPU_TARGET_PTR(addr));
- fn(src, RUN_ON_CPU_TARGET_PTR(addr));
-}
-
-void tlb_flush_page_all_cpus_synced(CPUState *src,
- target_ulong addr)
-{
- const run_on_cpu_func fn = tlb_flush_page_async_work;
-
- flush_all_helper(src, fn, RUN_ON_CPU_TARGET_PTR(addr));
- async_safe_run_on_cpu(src, fn, RUN_ON_CPU_TARGET_PTR(addr));
+ tlb_flush_page_by_mmuidx_all_cpus_synced(src, addr, ALL_MMUIDX_BITS);
}
/* update the TLBs so that writes to code in the virtual page 'addr'
@@ -450,72 +386,44 @@ void tlb_unprotect_code(ram_addr_t ram_addr)
* most usual is detecting writes to code regions which may invalidate
* generated code.
*
- * Because we want other vCPUs to respond to changes straight away we
- * update the te->addr_write field atomically. If the TLB entry has
- * been changed by the vCPU in the mean time we skip the update.
+ * Other vCPUs might be reading their TLBs during guest execution, so we update
+ * te->addr_write with atomic_set. We don't need to worry about this for
+ * oversized guests as MTTCG is disabled for them.
*
- * As this function uses atomic accesses we also need to ensure
- * updates to tlb_entries follow the same access rules. We don't need
- * to worry about this for oversized guests as MTTCG is disabled for
- * them.
+ * Called with tlb_c.lock held.
*/
-
-static void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, uintptr_t start,
- uintptr_t length)
+static void tlb_reset_dirty_range_locked(CPUTLBEntry *tlb_entry,
+ uintptr_t start, uintptr_t length)
{
-#if TCG_OVERSIZED_GUEST
uintptr_t addr = tlb_entry->addr_write;
if ((addr & (TLB_INVALID_MASK | TLB_MMIO | TLB_NOTDIRTY)) == 0) {
addr &= TARGET_PAGE_MASK;
addr += tlb_entry->addend;
if ((addr - start) < length) {
+#if TCG_OVERSIZED_GUEST
tlb_entry->addr_write |= TLB_NOTDIRTY;
- }
- }
#else
- /* paired with atomic_mb_set in tlb_set_page_with_attrs */
- uintptr_t orig_addr = atomic_mb_read(&tlb_entry->addr_write);
- uintptr_t addr = orig_addr;
-
- if ((addr & (TLB_INVALID_MASK | TLB_MMIO | TLB_NOTDIRTY)) == 0) {
- addr &= TARGET_PAGE_MASK;
- addr += atomic_read(&tlb_entry->addend);
- if ((addr - start) < length) {
- uintptr_t notdirty_addr = orig_addr | TLB_NOTDIRTY;
- atomic_cmpxchg(&tlb_entry->addr_write, orig_addr, notdirty_addr);
+ atomic_set(&tlb_entry->addr_write,
+ tlb_entry->addr_write | TLB_NOTDIRTY);
+#endif
}
}
-#endif
}
-/* For atomic correctness when running MTTCG we need to use the right
- * primitives when copying entries */
-static inline void copy_tlb_helper(CPUTLBEntry *d, CPUTLBEntry *s,
- bool atomic_set)
+/*
+ * Called with tlb_c.lock held.
+ * Called only from the vCPU context, i.e. the TLB's owner thread.
+ */
+static inline void copy_tlb_helper_locked(CPUTLBEntry *d, const CPUTLBEntry *s)
{
-#if TCG_OVERSIZED_GUEST
*d = *s;
-#else
- if (atomic_set) {
- d->addr_read = s->addr_read;
- d->addr_code = s->addr_code;
- atomic_set(&d->addend, atomic_read(&s->addend));
- /* Pairs with flag setting in tlb_reset_dirty_range */
- atomic_mb_set(&d->addr_write, atomic_read(&s->addr_write));
- } else {
- d->addr_read = s->addr_read;
- d->addr_write = atomic_read(&s->addr_write);
- d->addr_code = s->addr_code;
- d->addend = atomic_read(&s->addend);
- }
-#endif
}
/* This is a cross vCPU call (i.e. another vCPU resetting the flags of
- * the target vCPU). As such care needs to be taken that we don't
- * dangerously race with another vCPU update. The only thing actually
- * updated is the target TLB entry ->addr_write flags.
+ * the target vCPU).
+ * We must take tlb_c.lock to avoid racing with another vCPU update. The only
+ * thing actually updated is the target TLB entry ->addr_write flags.
*/
void tlb_reset_dirty(CPUState *cpu, ram_addr_t start1, ram_addr_t length)
{
@@ -524,22 +432,26 @@ void tlb_reset_dirty(CPUState *cpu, ram_addr_t start1, ram_addr_t length)
int mmu_idx;
env = cpu->env_ptr;
+ qemu_spin_lock(&env->tlb_c.lock);
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
unsigned int i;
for (i = 0; i < CPU_TLB_SIZE; i++) {
- tlb_reset_dirty_range(&env->tlb_table[mmu_idx][i],
- start1, length);
+ tlb_reset_dirty_range_locked(&env->tlb_table[mmu_idx][i], start1,
+ length);
}
for (i = 0; i < CPU_VTLB_SIZE; i++) {
- tlb_reset_dirty_range(&env->tlb_v_table[mmu_idx][i],
- start1, length);
+ tlb_reset_dirty_range_locked(&env->tlb_v_table[mmu_idx][i], start1,
+ length);
}
}
+ qemu_spin_unlock(&env->tlb_c.lock);
}
-static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, target_ulong vaddr)
+/* Called with tlb_c.lock held */
+static inline void tlb_set_dirty1_locked(CPUTLBEntry *tlb_entry,
+ target_ulong vaddr)
{
if (tlb_entry->addr_write == (vaddr | TLB_NOTDIRTY)) {
tlb_entry->addr_write = vaddr;
@@ -551,46 +463,47 @@ static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, target_ulong vaddr)
void tlb_set_dirty(CPUState *cpu, target_ulong vaddr)
{
CPUArchState *env = cpu->env_ptr;
- int i;
int mmu_idx;
assert_cpu_is_self(cpu);
vaddr &= TARGET_PAGE_MASK;
- i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+ qemu_spin_lock(&env->tlb_c.lock);
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
- tlb_set_dirty1(&env->tlb_table[mmu_idx][i], vaddr);
+ tlb_set_dirty1_locked(tlb_entry(env, mmu_idx, vaddr), vaddr);
}
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
int k;
for (k = 0; k < CPU_VTLB_SIZE; k++) {
- tlb_set_dirty1(&env->tlb_v_table[mmu_idx][k], vaddr);
+ tlb_set_dirty1_locked(&env->tlb_v_table[mmu_idx][k], vaddr);
}
}
+ qemu_spin_unlock(&env->tlb_c.lock);
}
/* Our TLB does not support large pages, so remember the area covered by
large pages and trigger a full TLB flush if these are invalidated. */
-static void tlb_add_large_page(CPUArchState *env, target_ulong vaddr,
- target_ulong size)
+static void tlb_add_large_page(CPUArchState *env, int mmu_idx,
+ target_ulong vaddr, target_ulong size)
{
- target_ulong mask = ~(size - 1);
+ target_ulong lp_addr = env->tlb_d[mmu_idx].large_page_addr;
+ target_ulong lp_mask = ~(size - 1);
- if (env->tlb_flush_addr == (target_ulong)-1) {
- env->tlb_flush_addr = vaddr & mask;
- env->tlb_flush_mask = mask;
- return;
- }
- /* Extend the existing region to include the new page.
- This is a compromise between unnecessary flushes and the cost
- of maintaining a full variable size TLB. */
- mask &= env->tlb_flush_mask;
- while (((env->tlb_flush_addr ^ vaddr) & mask) != 0) {
- mask <<= 1;
+ if (lp_addr == (target_ulong)-1) {
+ /* No previous large page. */
+ lp_addr = vaddr;
+ } else {
+ /* Extend the existing region to include the new page.
+ This is a compromise between unnecessary flushes and
+ the cost of maintaining a full variable size TLB. */
+ lp_mask &= env->tlb_d[mmu_idx].large_page_mask;
+ while (((lp_addr ^ vaddr) & lp_mask) != 0) {
+ lp_mask <<= 1;
+ }
}
- env->tlb_flush_addr &= mask;
- env->tlb_flush_mask = mask;
+ env->tlb_d[mmu_idx].large_page_addr = lp_addr & lp_mask;
+ env->tlb_d[mmu_idx].large_page_mask = lp_mask;
}
/* Add a new TLB entry. At most one entry for a given virtual address
@@ -617,12 +530,10 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
assert_cpu_is_self(cpu);
- if (size < TARGET_PAGE_SIZE) {
+ if (size <= TARGET_PAGE_SIZE) {
sz = TARGET_PAGE_SIZE;
} else {
- if (size > TARGET_PAGE_SIZE) {
- tlb_add_large_page(env, vaddr, size);
- }
+ tlb_add_large_page(env, mmu_idx, vaddr, size);
sz = size;
}
vaddr_page = vaddr & TARGET_PAGE_MASK;
@@ -654,26 +565,38 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
addend = (uintptr_t)memory_region_get_ram_ptr(section->mr) + xlat;
}
- /* Make sure there's no cached translation for the new page. */
- tlb_flush_vtlb_page(env, mmu_idx, vaddr_page);
-
code_address = address;
iotlb = memory_region_section_get_iotlb(cpu, section, vaddr_page,
paddr_page, xlat, prot, &address);
- index = (vaddr_page >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- te = &env->tlb_table[mmu_idx][index];
+ index = tlb_index(env, mmu_idx, vaddr_page);
+ te = tlb_entry(env, mmu_idx, vaddr_page);
+
+ /*
+ * Hold the TLB lock for the rest of the function. We could acquire/release
+ * the lock several times in the function, but it is faster to amortize the
+ * acquisition cost by acquiring it just once. Note that this leads to
+ * a longer critical section, but this is not a concern since the TLB lock
+ * is unlikely to be contended.
+ */
+ qemu_spin_lock(&env->tlb_c.lock);
+
+ /* Note that the tlb is no longer clean. */
+ env->tlb_c.dirty |= 1 << mmu_idx;
+
+ /* Make sure there's no cached translation for the new page. */
+ tlb_flush_vtlb_page_locked(env, mmu_idx, vaddr_page);
/*
* Only evict the old entry to the victim tlb if it's for a
* different page; otherwise just overwrite the stale data.
*/
if (!tlb_hit_page_anyprot(te, vaddr_page)) {
- unsigned vidx = env->vtlb_index++ % CPU_VTLB_SIZE;
+ unsigned vidx = env->tlb_d[mmu_idx].vindex++ % CPU_VTLB_SIZE;
CPUTLBEntry *tv = &env->tlb_v_table[mmu_idx][vidx];
/* Evict the old entry into the victim tlb. */
- copy_tlb_helper(tv, te, true);
+ copy_tlb_helper_locked(tv, te);
env->iotlb_v[mmu_idx][vidx] = env->iotlb[mmu_idx][index];
}
@@ -725,9 +648,8 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
}
}
- /* Pairs with flag setting in tlb_reset_dirty_range */
- copy_tlb_helper(te, &tn, true);
- /* atomic_mb_set(&te->addr_write, write_address); */
+ copy_tlb_helper_locked(te, &tn);
+ qemu_spin_unlock(&env->tlb_c.lock);
}
/* Add a new TLB entry, but without specifying the memory
@@ -773,16 +695,16 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
* repeat the MMU check here. This tlb_fill() call might
* longjump out if this access should cause a guest exception.
*/
- int index;
+ CPUTLBEntry *entry;
target_ulong tlb_addr;
tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
- index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- tlb_addr = env->tlb_table[mmu_idx][index].addr_read;
+ entry = tlb_entry(env, mmu_idx, addr);
+ tlb_addr = entry->addr_read;
if (!(tlb_addr & ~(TARGET_PAGE_MASK | TLB_RECHECK))) {
/* RAM access */
- uintptr_t haddr = addr + env->tlb_table[mmu_idx][index].addend;
+ uintptr_t haddr = addr + entry->addend;
return ldn_p((void *)haddr, size);
}
@@ -840,16 +762,16 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
* repeat the MMU check here. This tlb_fill() call might
* longjump out if this access should cause a guest exception.
*/
- int index;
+ CPUTLBEntry *entry;
target_ulong tlb_addr;
tlb_fill(cpu, addr, size, MMU_DATA_STORE, mmu_idx, retaddr);
- index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
+ entry = tlb_entry(env, mmu_idx, addr);
+ tlb_addr = tlb_addr_write(entry);
if (!(tlb_addr & ~(TARGET_PAGE_MASK | TLB_RECHECK))) {
/* RAM access */
- uintptr_t haddr = addr + env->tlb_table[mmu_idx][index].addend;
+ uintptr_t haddr = addr + entry->addend;
stn_p((void *)haddr, size, val);
return;
@@ -891,17 +813,28 @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
size_t elt_ofs, target_ulong page)
{
size_t vidx;
+
+ assert_cpu_is_self(ENV_GET_CPU(env));
for (vidx = 0; vidx < CPU_VTLB_SIZE; ++vidx) {
CPUTLBEntry *vtlb = &env->tlb_v_table[mmu_idx][vidx];
- target_ulong cmp = *(target_ulong *)((uintptr_t)vtlb + elt_ofs);
+ target_ulong cmp;
+
+ /* elt_ofs might correspond to .addr_write, so use atomic_read */
+#if TCG_OVERSIZED_GUEST
+ cmp = *(target_ulong *)((uintptr_t)vtlb + elt_ofs);
+#else
+ cmp = atomic_read((target_ulong *)((uintptr_t)vtlb + elt_ofs));
+#endif
if (cmp == page) {
/* Found entry in victim tlb, swap tlb and iotlb. */
CPUTLBEntry tmptlb, *tlb = &env->tlb_table[mmu_idx][index];
- copy_tlb_helper(&tmptlb, tlb, false);
- copy_tlb_helper(tlb, vtlb, true);
- copy_tlb_helper(vtlb, &tmptlb, true);
+ qemu_spin_lock(&env->tlb_c.lock);
+ copy_tlb_helper_locked(&tmptlb, tlb);
+ copy_tlb_helper_locked(tlb, vtlb);
+ copy_tlb_helper_locked(vtlb, &tmptlb);
+ qemu_spin_unlock(&env->tlb_c.lock);
CPUIOTLBEntry tmpio, *io = &env->iotlb[mmu_idx][index];
CPUIOTLBEntry *vio = &env->iotlb_v[mmu_idx][vidx];
@@ -924,20 +857,19 @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
*/
tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
{
- int mmu_idx, index;
+ uintptr_t mmu_idx = cpu_mmu_index(env, true);
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
void *p;
- index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- mmu_idx = cpu_mmu_index(env, true);
- if (unlikely(!tlb_hit(env->tlb_table[mmu_idx][index].addr_code, addr))) {
+ if (unlikely(!tlb_hit(entry->addr_code, addr))) {
if (!VICTIM_TLB_HIT(addr_code, addr)) {
tlb_fill(ENV_GET_CPU(env), addr, 0, MMU_INST_FETCH, mmu_idx, 0);
}
- assert(tlb_hit(env->tlb_table[mmu_idx][index].addr_code, addr));
+ assert(tlb_hit(entry->addr_code, addr));
}
- if (unlikely(env->tlb_table[mmu_idx][index].addr_code &
- (TLB_RECHECK | TLB_MMIO))) {
+ if (unlikely(entry->addr_code & (TLB_RECHECK | TLB_MMIO))) {
/*
* Return -1 if we can't translate and execute from an entire
* page of RAM here, which will cause us to execute by loading
@@ -949,7 +881,7 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
return -1;
}
- p = (void *)((uintptr_t)addr + env->tlb_table[mmu_idx][index].addend);
+ p = (void *)((uintptr_t)addr + entry->addend);
return qemu_ram_addr_from_host_nofail(p);
}
@@ -962,10 +894,10 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
void probe_write(CPUArchState *env, target_ulong addr, int size, int mmu_idx,
uintptr_t retaddr)
{
- int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
- if (!tlb_hit(tlb_addr, addr)) {
+ if (!tlb_hit(tlb_addr_write(entry), addr)) {
/* TLB entry is for a different page */
if (!VICTIM_TLB_HIT(addr_write, addr)) {
tlb_fill(ENV_GET_CPU(env), addr, size, MMU_DATA_STORE,
@@ -981,9 +913,9 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
NotDirtyInfo *ndi)
{
size_t mmu_idx = get_mmuidx(oi);
- size_t index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- CPUTLBEntry *tlbe = &env->tlb_table[mmu_idx][index];
- target_ulong tlb_addr = tlbe->addr_write;
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
+ CPUTLBEntry *tlbe = tlb_entry(env, mmu_idx, addr);
+ target_ulong tlb_addr = tlb_addr_write(tlbe);
TCGMemOp mop = get_memop(oi);
int a_bits = get_alignment_bits(mop);
int s_bits = mop & MO_SIZE;
@@ -1014,7 +946,7 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
tlb_fill(ENV_GET_CPU(env), addr, 1 << s_bits, MMU_DATA_STORE,
mmu_idx, retaddr);
}
- tlb_addr = tlbe->addr_write & ~TLB_INVALID_MASK;
+ tlb_addr = tlb_addr_write(tlbe) & ~TLB_INVALID_MASK;
}
/* Notice an IO access or a needs-MMU-lookup access */
@@ -1101,7 +1033,7 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
#include "atomic_template.h"
#endif
-#ifdef CONFIG_ATOMIC128
+#if HAVE_CMPXCHG128 || HAVE_ATOMIC128
#define DATA_SIZE 16
#include "atomic_template.h"
#endif
diff --git a/accel/tcg/softmmu_template.h b/accel/tcg/softmmu_template.h
index f060a693d4..b0adea045e 100644
--- a/accel/tcg/softmmu_template.h
+++ b/accel/tcg/softmmu_template.h
@@ -111,9 +111,10 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- unsigned mmu_idx = get_mmuidx(oi);
- int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- target_ulong tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
+ uintptr_t mmu_idx = get_mmuidx(oi);
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
+ target_ulong tlb_addr = entry->ADDR_READ;
unsigned a_bits = get_alignment_bits(get_memop(oi));
uintptr_t haddr;
DATA_TYPE res;
@@ -129,7 +130,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr,
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, READ_ACCESS_TYPE,
mmu_idx, retaddr);
}
- tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
+ tlb_addr = entry->ADDR_READ;
}
/* Handle an IO access. */
@@ -166,7 +167,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr,
return res;
}
- haddr = addr + env->tlb_table[mmu_idx][index].addend;
+ haddr = addr + entry->addend;
#if DATA_SIZE == 1
res = glue(glue(ld, LSUFFIX), _p)((uint8_t *)haddr);
#else
@@ -179,9 +180,10 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr,
WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- unsigned mmu_idx = get_mmuidx(oi);
- int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- target_ulong tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
+ uintptr_t mmu_idx = get_mmuidx(oi);
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
+ target_ulong tlb_addr = entry->ADDR_READ;
unsigned a_bits = get_alignment_bits(get_memop(oi));
uintptr_t haddr;
DATA_TYPE res;
@@ -197,7 +199,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr,
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, READ_ACCESS_TYPE,
mmu_idx, retaddr);
}
- tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
+ tlb_addr = entry->ADDR_READ;
}
/* Handle an IO access. */
@@ -234,7 +236,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr,
return res;
}
- haddr = addr + env->tlb_table[mmu_idx][index].addend;
+ haddr = addr + entry->addend;
res = glue(glue(ld, LSUFFIX), _be_p)((uint8_t *)haddr);
return res;
}
@@ -275,9 +277,10 @@ static inline void glue(io_write, SUFFIX)(CPUArchState *env,
void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- unsigned mmu_idx = get_mmuidx(oi);
- int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
+ uintptr_t mmu_idx = get_mmuidx(oi);
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
+ target_ulong tlb_addr = tlb_addr_write(entry);
unsigned a_bits = get_alignment_bits(get_memop(oi));
uintptr_t haddr;
@@ -292,7 +295,7 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, MMU_DATA_STORE,
mmu_idx, retaddr);
}
- tlb_addr = env->tlb_table[mmu_idx][index].addr_write & ~TLB_INVALID_MASK;
+ tlb_addr = tlb_addr_write(entry) & ~TLB_INVALID_MASK;
}
/* Handle an IO access. */
@@ -313,16 +316,16 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
if (DATA_SIZE > 1
&& unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
>= TARGET_PAGE_SIZE)) {
- int i, index2;
- target_ulong page2, tlb_addr2;
+ int i;
+ target_ulong page2;
+ CPUTLBEntry *entry2;
do_unaligned_access:
/* Ensure the second page is in the TLB. Note that the first page
is already guaranteed to be filled, and that the second page
cannot evict the first. */
page2 = (addr + DATA_SIZE) & TARGET_PAGE_MASK;
- index2 = (page2 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- tlb_addr2 = env->tlb_table[mmu_idx][index2].addr_write;
- if (!tlb_hit_page(tlb_addr2, page2)
+ entry2 = tlb_entry(env, mmu_idx, page2);
+ if (!tlb_hit_page(tlb_addr_write(entry2), page2)
&& !VICTIM_TLB_HIT(addr_write, page2)) {
tlb_fill(ENV_GET_CPU(env), page2, DATA_SIZE, MMU_DATA_STORE,
mmu_idx, retaddr);
@@ -340,7 +343,7 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
return;
}
- haddr = addr + env->tlb_table[mmu_idx][index].addend;
+ haddr = addr + entry->addend;
#if DATA_SIZE == 1
glue(glue(st, SUFFIX), _p)((uint8_t *)haddr, val);
#else
@@ -352,9 +355,10 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
TCGMemOpIdx oi, uintptr_t retaddr)
{
- unsigned mmu_idx = get_mmuidx(oi);
- int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
+ uintptr_t mmu_idx = get_mmuidx(oi);
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
+ target_ulong tlb_addr = tlb_addr_write(entry);
unsigned a_bits = get_alignment_bits(get_memop(oi));
uintptr_t haddr;
@@ -369,7 +373,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, MMU_DATA_STORE,
mmu_idx, retaddr);
}
- tlb_addr = env->tlb_table[mmu_idx][index].addr_write & ~TLB_INVALID_MASK;
+ tlb_addr = tlb_addr_write(entry) & ~TLB_INVALID_MASK;
}
/* Handle an IO access. */
@@ -390,16 +394,16 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
if (DATA_SIZE > 1
&& unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
>= TARGET_PAGE_SIZE)) {
- int i, index2;
- target_ulong page2, tlb_addr2;
+ int i;
+ target_ulong page2;
+ CPUTLBEntry *entry2;
do_unaligned_access:
/* Ensure the second page is in the TLB. Note that the first page
is already guaranteed to be filled, and that the second page
cannot evict the first. */
page2 = (addr + DATA_SIZE) & TARGET_PAGE_MASK;
- index2 = (page2 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
- tlb_addr2 = env->tlb_table[mmu_idx][index2].addr_write;
- if (!tlb_hit_page(tlb_addr2, page2)
+ entry2 = tlb_entry(env, mmu_idx, page2);
+ if (!tlb_hit_page(tlb_addr_write(entry2), page2)
&& !VICTIM_TLB_HIT(addr_write, page2)) {
tlb_fill(ENV_GET_CPU(env), page2, DATA_SIZE, MMU_DATA_STORE,
mmu_idx, retaddr);
@@ -417,7 +421,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
return;
}
- haddr = addr + env->tlb_table[mmu_idx][index].addend;
+ haddr = addr + entry->addend;
glue(glue(st, SUFFIX), _be_p)((uint8_t *)haddr, val);
}
#endif /* DATA_SIZE > 1 */
diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c
index 56dbb56a16..3d25bdcc17 100644
--- a/accel/tcg/tcg-all.c
+++ b/accel/tcg/tcg-all.c
@@ -51,7 +51,7 @@ static void tcg_handle_interrupt(CPUState *cpu, int mask)
if (!qemu_cpu_is_self(cpu)) {
qemu_cpu_kick(cpu);
} else {
- cpu->icount_decr.u16.high = -1;
+ atomic_set(&cpu->icount_decr.u16.high, -1);
if (use_icount &&
!cpu->can_do_io
&& (mask & ~old_mask) != 0) {
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index ad5c758246..639f0b2728 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -2290,7 +2290,7 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
{
struct tb_tree_stats tst = {};
struct qht_stats hst;
- size_t nb_tbs;
+ size_t nb_tbs, flush_full, flush_part, flush_elide;
tcg_tb_foreach(tb_tree_stats_iter, &tst);
nb_tbs = tst.nb_tbs;
@@ -2326,7 +2326,11 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
cpu_fprintf(f, "TB flush count %u\n",
atomic_read(&tb_ctx.tb_flush_count));
cpu_fprintf(f, "TB invalidate count %zu\n", tcg_tb_phys_invalidate_count());
- cpu_fprintf(f, "TLB flush count %zu\n", tlb_flush_count());
+
+ tlb_flush_counts(&flush_full, &flush_part, &flush_elide);
+ cpu_fprintf(f, "TLB full flushes %zu\n", flush_full);
+ cpu_fprintf(f, "TLB partial flushes %zu\n", flush_part);
+ cpu_fprintf(f, "TLB elided flushes %zu\n", flush_elide);
tcg_dump_info(f, cpu_fprintf);
}
@@ -2341,7 +2345,7 @@ void cpu_interrupt(CPUState *cpu, int mask)
{
g_assert(qemu_mutex_iothread_locked());
cpu->interrupt_request |= mask;
- cpu->icount_decr.u16.high = -1;
+ atomic_set(&cpu->icount_decr.u16.high, -1);
}
/*
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index 26a3ffbba1..cd75829cf2 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -25,6 +25,7 @@
#include "exec/cpu_ldst.h"
#include "translate-all.h"
#include "exec/helper-proto.h"
+#include "qemu/atomic128.h"
#undef EAX
#undef ECX
@@ -615,7 +616,7 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
/* The following is only callable from other helpers, and matches up
with the softmmu version. */
-#ifdef CONFIG_ATOMIC128
+#if HAVE_ATOMIC128 || HAVE_CMPXCHG128
#undef EXTRA_ARGS
#undef ATOMIC_NAME
@@ -628,4 +629,4 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
#define DATA_SIZE 16
#include "atomic_template.h"
-#endif /* CONFIG_ATOMIC128 */
+#endif
diff --git a/audio/paaudio.c b/audio/paaudio.c
index 949769774d..4c100bc318 100644
--- a/audio/paaudio.c
+++ b/audio/paaudio.c
@@ -227,7 +227,7 @@ static void *qpa_thread_out (void *arg)
}
}
- decr = to_mix = audio_MIN (pa->live, pa->g->conf.samples >> 2);
+ decr = to_mix = audio_MIN(pa->live, pa->g->conf.samples >> 5);
rpos = pa->rpos;
if (audio_pt_unlock(&pa->pt, __func__)) {
@@ -319,7 +319,7 @@ static void *qpa_thread_in (void *arg)
}
}
- incr = to_grab = audio_MIN (pa->dead, pa->g->conf.samples >> 2);
+ incr = to_grab = audio_MIN(pa->dead, pa->g->conf.samples >> 5);
wpos = pa->wpos;
if (audio_pt_unlock(&pa->pt, __func__)) {
diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c
index e64074954f..639c8d4307 100644
--- a/backends/hostmem-file.c
+++ b/backends/hostmem-file.c
@@ -145,20 +145,26 @@ static void file_memory_backend_set_pmem(Object *o, bool value, Error **errp)
HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o);
if (host_memory_backend_mr_inited(backend)) {
+ char *path = object_get_canonical_path_component(o);
+
error_setg(errp, "cannot change property 'pmem' of %s '%s'",
object_get_typename(o),
- object_get_canonical_path_component(o));
+ path);
+ g_free(path);
return;
}
#ifndef CONFIG_LIBPMEM
if (value) {
Error *local_err = NULL;
+ char *path = object_get_canonical_path_component(o);
+
error_setg(&local_err,
"Lack of libpmem support while setting the 'pmem=on'"
" of %s '%s'. We can't ensure data persistence.",
object_get_typename(o),
- object_get_canonical_path_component(o));
+ path);
+ g_free(path);
error_propagate(errp, local_err);
return;
}
diff --git a/block.c b/block.c
index 7710b399a3..3feac08535 100644
--- a/block.c
+++ b/block.c
@@ -266,22 +266,41 @@ int bdrv_can_set_read_only(BlockDriverState *bs, bool read_only,
return 0;
}
-/* TODO Remove (deprecated since 2.11)
- * Block drivers are not supposed to automatically change bs->read_only.
- * Instead, they should just check whether they can provide what the user
- * explicitly requested and error out if read-write is requested, but they can
- * only provide read-only access. */
-int bdrv_set_read_only(BlockDriverState *bs, bool read_only, Error **errp)
+/*
+ * Called by a driver that can only provide a read-only image.
+ *
+ * Returns 0 if the node is already read-only or it could switch the node to
+ * read-only because BDRV_O_AUTO_RDONLY is set.
+ *
+ * Returns -EACCES if the node is read-write and BDRV_O_AUTO_RDONLY is not set
+ * or bdrv_can_set_read_only() forbids making the node read-only. If @errmsg
+ * is not NULL, it is used as the error message for the Error object.
+ */
+int bdrv_apply_auto_read_only(BlockDriverState *bs, const char *errmsg,
+ Error **errp)
{
int ret = 0;
- ret = bdrv_can_set_read_only(bs, read_only, false, errp);
+ if (!(bs->open_flags & BDRV_O_RDWR)) {
+ return 0;
+ }
+ if (!(bs->open_flags & BDRV_O_AUTO_RDONLY)) {
+ goto fail;
+ }
+
+ ret = bdrv_can_set_read_only(bs, true, false, NULL);
if (ret < 0) {
- return ret;
+ goto fail;
}
- bs->read_only = read_only;
+ bs->read_only = true;
+ bs->open_flags &= ~BDRV_O_RDWR;
+
return 0;
+
+fail:
+ error_setg(errp, "%s", errmsg ?: "Image is read-only");
+ return -EACCES;
}
void bdrv_get_full_backing_filename_from_filename(const char *backed,
@@ -923,6 +942,7 @@ static void bdrv_inherited_options(int *child_flags, QDict *child_options,
/* Inherit the read-only option from the parent if it's not set */
qdict_copy_default(child_options, parent_options, BDRV_OPT_READ_ONLY);
+ qdict_copy_default(child_options, parent_options, BDRV_OPT_AUTO_READ_ONLY);
/* Our block drivers take care to send flushes and respect unmap policy,
* so we can default to enable both on lower layers regardless of the
@@ -1046,6 +1066,7 @@ static void bdrv_backing_options(int *child_flags, QDict *child_options,
/* backing files always opened read-only */
qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "on");
+ qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
flags &= ~BDRV_O_COPY_ON_READ;
/* snapshot=on is handled on the top layer */
@@ -1135,6 +1156,10 @@ static void update_flags_from_options(int *flags, QemuOpts *opts)
*flags |= BDRV_O_RDWR;
}
+ assert(qemu_opt_find(opts, BDRV_OPT_AUTO_READ_ONLY));
+ if (qemu_opt_get_bool_del(opts, BDRV_OPT_AUTO_READ_ONLY, false)) {
+ *flags |= BDRV_O_AUTO_RDONLY;
+ }
}
static void update_options_from_flags(QDict *options, int flags)
@@ -1149,6 +1174,10 @@ static void update_options_from_flags(QDict *options, int flags)
if (!qdict_haskey(options, BDRV_OPT_READ_ONLY)) {
qdict_put_bool(options, BDRV_OPT_READ_ONLY, !(flags & BDRV_O_RDWR));
}
+ if (!qdict_haskey(options, BDRV_OPT_AUTO_READ_ONLY)) {
+ qdict_put_bool(options, BDRV_OPT_AUTO_READ_ONLY,
+ flags & BDRV_O_AUTO_RDONLY);
+ }
}
static void bdrv_assign_node_name(BlockDriverState *bs,
@@ -1322,12 +1351,17 @@ QemuOptsList bdrv_runtime_opts = {
.help = "Node is opened in read-only mode",
},
{
+ .name = BDRV_OPT_AUTO_READ_ONLY,
+ .type = QEMU_OPT_BOOL,
+ .help = "Node can become read-only if opening read-write fails",
+ },
+ {
.name = "detect-zeroes",
.type = QEMU_OPT_STRING,
.help = "try to optimize zero writes (off, on, unmap)",
},
{
- .name = "discard",
+ .name = BDRV_OPT_DISCARD,
.type = QEMU_OPT_STRING,
.help = "discard operation (ignore/off, unmap/on)",
},
@@ -1432,7 +1466,7 @@ static int bdrv_open_common(BlockDriverState *bs, BlockBackend *file,
}
}
- discard = qemu_opt_get(opts, "discard");
+ discard = qemu_opt_get(opts, BDRV_OPT_DISCARD);
if (discard != NULL) {
if (bdrv_parse_discard_flags(discard, &bs->open_flags) != 0) {
error_setg(errp, "Invalid discard option");
@@ -2479,6 +2513,8 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off");
qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off");
qdict_set_default_str(qdict, BDRV_OPT_READ_ONLY, "off");
+ qdict_set_default_str(qdict, BDRV_OPT_AUTO_READ_ONLY, "off");
+
}
bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, errp);
@@ -3165,6 +3201,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
QDict *orig_reopen_opts;
char *discard = NULL;
bool read_only;
+ bool drv_prepared = false;
assert(reopen_state != NULL);
assert(reopen_state->bs->drv != NULL);
@@ -3186,7 +3223,7 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
update_flags_from_options(&reopen_state->flags, opts);
- discard = qemu_opt_get_del(opts, "discard");
+ discard = qemu_opt_get_del(opts, BDRV_OPT_DISCARD);
if (discard != NULL) {
if (bdrv_parse_discard_flags(discard, &reopen_state->flags) != 0) {
error_setg(errp, "Invalid discard option");
@@ -3249,6 +3286,8 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
goto error;
}
+ drv_prepared = true;
+
/* Options that are not handled are only okay if they are unchanged
* compared to the old state. It is expected that some options are only
* used for the initial open, but not reopen (e.g. filename) */
@@ -3314,6 +3353,15 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_state, BlockReopenQueue *queue,
reopen_state->options = qobject_ref(orig_reopen_opts);
error:
+ if (ret < 0 && drv_prepared) {
+ /* drv->bdrv_reopen_prepare() has succeeded, so we need to
+ * call drv->bdrv_reopen_abort() before signaling an error
+ * (bdrv_reopen_multiple() will not call bdrv_reopen_abort()
+ * when the respective bdrv_reopen_prepare() has failed) */
+ if (drv->bdrv_reopen_abort) {
+ drv->bdrv_reopen_abort(reopen_state);
+ }
+ }
qemu_opts_del(opts);
qobject_unref(orig_reopen_opts);
g_free(discard);
@@ -4403,6 +4451,7 @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs,
uint64_t perm, shared_perm;
Error *local_err = NULL;
int ret;
+ BdrvDirtyBitmap *bm;
if (!bs->drv) {
return;
@@ -4452,6 +4501,12 @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs,
}
}
+ for (bm = bdrv_dirty_bitmap_next(bs, NULL); bm;
+ bm = bdrv_dirty_bitmap_next(bs, bm))
+ {
+ bdrv_dirty_bitmap_set_migration(bm, false);
+ }
+
ret = refresh_total_sectors(bs, bs->total_sectors);
if (ret < 0) {
bs->open_flags |= BDRV_O_INACTIVE;
@@ -4566,10 +4621,6 @@ static int bdrv_inactivate_recurse(BlockDriverState *bs,
}
}
- /* At this point persistent bitmaps should be already stored by the format
- * driver */
- bdrv_release_persistent_dirty_bitmaps(bs);
-
return 0;
}
@@ -4697,9 +4748,9 @@ bool bdrv_op_is_blocked(BlockDriverState *bs, BlockOpType op, Error **errp)
assert((int) op >= 0 && op < BLOCK_OP_TYPE_MAX);
if (!QLIST_EMPTY(&bs->op_blockers[op])) {
blocker = QLIST_FIRST(&bs->op_blockers[op]);
- error_propagate(errp, error_copy(blocker->reason));
- error_prepend(errp, "Node '%s' is busy: ",
- bdrv_get_device_or_node_name(bs));
+ error_propagate_prepend(errp, error_copy(blocker->reason),
+ "Node '%s' is busy: ",
+ bdrv_get_device_or_node_name(bs));
return true;
}
return false;
@@ -4803,9 +4854,6 @@ void bdrv_img_create(const char *filename, const char *fmt,
if (options) {
qemu_opts_do_parse(opts, options, NULL, &local_err);
if (local_err) {
- error_report_err(local_err);
- local_err = NULL;
- error_setg(errp, "Invalid options for file format '%s'", fmt);
goto out;
}
}
diff --git a/block/Makefile.objs b/block/Makefile.objs
index c8337bf186..46d585cfd0 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -1,10 +1,18 @@
-block-obj-y += raw-format.o qcow.o vdi.o vmdk.o cloop.o bochs.o vpc.o vvfat.o dmg.o
+block-obj-y += raw-format.o vmdk.o vpc.o
+block-obj-$(CONFIG_QCOW1) += qcow.o
+block-obj-$(CONFIG_VDI) += vdi.o
+block-obj-$(CONFIG_CLOOP) += cloop.o
+block-obj-$(CONFIG_BOCHS) += bochs.o
+block-obj-$(CONFIG_VVFAT) += vvfat.o
+block-obj-$(CONFIG_DMG) += dmg.o
+
block-obj-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o qcow2-bitmap.o
-block-obj-y += qed.o qed-l2-cache.o qed-table.o qed-cluster.o
-block-obj-y += qed-check.o
+block-obj-$(CONFIG_QED) += qed.o qed-l2-cache.o qed-table.o qed-cluster.o
+block-obj-$(CONFIG_QED) += qed-check.o
block-obj-y += vhdx.o vhdx-endian.o vhdx-log.o
block-obj-y += quorum.o
-block-obj-y += parallels.o blkdebug.o blkverify.o blkreplay.o
+block-obj-y += blkdebug.o blkverify.o blkreplay.o
+block-obj-$(CONFIG_PARALLELS) += parallels.o
block-obj-y += blklogwrites.o
block-obj-y += block-backend.o snapshot.o qapi.o
block-obj-$(CONFIG_WIN32) += file-win32.o win32-aio.o
@@ -14,7 +22,8 @@ block-obj-y += null.o mirror.o commit.o io.o create.o
block-obj-y += throttle-groups.o
block-obj-$(CONFIG_LINUX) += nvme.o
-block-obj-y += nbd.o nbd-client.o sheepdog.o
+block-obj-y += nbd.o nbd-client.o
+block-obj-$(CONFIG_SHEEPDOG) += sheepdog.o
block-obj-$(CONFIG_LIBISCSI) += iscsi.o
block-obj-$(if $(CONFIG_LIBISCSI),y,n) += iscsi-opts.o
block-obj-$(CONFIG_LIBNFS) += nfs.o
@@ -45,7 +54,8 @@ gluster.o-libs := $(GLUSTERFS_LIBS)
vxhs.o-libs := $(VXHS_LIBS)
ssh.o-cflags := $(LIBSSH2_CFLAGS)
ssh.o-libs := $(LIBSSH2_LIBS)
-block-obj-$(if $(CONFIG_BZIP2),m,n) += dmg-bz2.o
+block-obj-dmg-bz2-$(CONFIG_BZIP2) += dmg-bz2.o
+block-obj-$(if $(CONFIG_DMG),m,n) += $(block-obj-dmg-bz2-y)
dmg-bz2.o-libs := $(BZIP2_LIBS)
qcow.o-libs := -lz
linux-aio.o-libs := -laio
diff --git a/block/block-backend.c b/block/block-backend.c
index dc0cd57724..60d37a0c3d 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -918,7 +918,8 @@ char *blk_get_attached_dev_id(BlockBackend *blk)
} else if (dev->id) {
return g_strdup(dev->id);
}
- return object_get_canonical_path(OBJECT(dev));
+
+ return object_get_canonical_path(OBJECT(dev)) ?: g_strdup("");
}
/*
@@ -1708,7 +1709,7 @@ void blk_error_action(BlockBackend *blk, BlockErrorAction action,
}
}
-int blk_is_read_only(BlockBackend *blk)
+bool blk_is_read_only(BlockBackend *blk)
{
BlockDriverState *bs = blk_bs(blk);
@@ -1719,18 +1720,18 @@ int blk_is_read_only(BlockBackend *blk)
}
}
-int blk_is_sg(BlockBackend *blk)
+bool blk_is_sg(BlockBackend *blk)
{
BlockDriverState *bs = blk_bs(blk);
if (!bs) {
- return 0;
+ return false;
}
return bdrv_is_sg(bs);
}
-int blk_enable_write_cache(BlockBackend *blk)
+bool blk_enable_write_cache(BlockBackend *blk)
{
return blk->enable_write_cache;
}
diff --git a/block/bochs.c b/block/bochs.c
index 50c630047b..22e7d44211 100644
--- a/block/bochs.c
+++ b/block/bochs.c
@@ -105,23 +105,18 @@ static int bochs_open(BlockDriverState *bs, QDict *options, int flags,
struct bochs_header bochs;
int ret;
+ /* No write support yet */
+ ret = bdrv_apply_auto_read_only(bs, NULL, errp);
+ if (ret < 0) {
+ return ret;
+ }
+
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
false, errp);
if (!bs->file) {
return -EINVAL;
}
- if (!bdrv_is_read_only(bs)) {
- error_report("Opening bochs images without an explicit read-only=on "
- "option is deprecated. Future versions will refuse to "
- "open the image instead of automatically marking the "
- "image read-only.");
- ret = bdrv_set_read_only(bs, true, errp); /* no write support yet */
- if (ret < 0) {
- return ret;
- }
- }
-
ret = bdrv_pread(bs->file, 0, &bochs, sizeof(bochs));
if (ret < 0) {
return ret;
diff --git a/block/cloop.c b/block/cloop.c
index 2be68987bd..df2b85f723 100644
--- a/block/cloop.c
+++ b/block/cloop.c
@@ -67,23 +67,17 @@ static int cloop_open(BlockDriverState *bs, QDict *options, int flags,
uint32_t offsets_size, max_compressed_block_size = 1, i;
int ret;
+ ret = bdrv_apply_auto_read_only(bs, NULL, errp);
+ if (ret < 0) {
+ return ret;
+ }
+
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
false, errp);
if (!bs->file) {
return -EINVAL;
}
- if (!bdrv_is_read_only(bs)) {
- error_report("Opening cloop images without an explicit read-only=on "
- "option is deprecated. Future versions will refuse to "
- "open the image instead of automatically marking the "
- "image read-only.");
- ret = bdrv_set_read_only(bs, true, errp);
- if (ret < 0) {
- return ret;
- }
- }
-
/* read header */
ret = bdrv_pread(bs->file, 128, &s->block_size, 4);
if (ret < 0) {
diff --git a/block/curl.c b/block/curl.c
index fabb2b4da7..db5d2bd8ef 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -684,10 +684,10 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
const char *protocol_delimiter;
int ret;
-
- if (flags & BDRV_O_RDWR) {
- error_setg(errp, "curl block device does not support writes");
- return -EROFS;
+ ret = bdrv_apply_auto_read_only(bs, "curl driver does not support writes",
+ errp);
+ if (ret < 0) {
+ return ret;
}
if (!libcurl_initialized) {
diff --git a/block/dirty-bitmap.c b/block/dirty-bitmap.c
index c9b8a6fd52..89fd1d7f8b 100644
--- a/block/dirty-bitmap.c
+++ b/block/dirty-bitmap.c
@@ -55,6 +55,10 @@ struct BdrvDirtyBitmap {
and this bitmap must remain unchanged while
this flag is set. */
bool persistent; /* bitmap must be saved to owner disk image */
+ bool migration; /* Bitmap is selected for migration, it should
+ not be stored on the next inactivation
+ (persistent flag doesn't matter until next
+ invalidation).*/
QLIST_ENTRY(BdrvDirtyBitmap) list;
};
@@ -176,6 +180,12 @@ bool bdrv_dirty_bitmap_frozen(BdrvDirtyBitmap *bitmap)
return bitmap->successor;
}
+/* Both conditions disallow user-modification via QMP. */
+bool bdrv_dirty_bitmap_user_locked(BdrvDirtyBitmap *bitmap) {
+ return bdrv_dirty_bitmap_frozen(bitmap) ||
+ bdrv_dirty_bitmap_qmp_locked(bitmap);
+}
+
void bdrv_dirty_bitmap_set_qmp_locked(BdrvDirtyBitmap *bitmap, bool qmp_locked)
{
qemu_mutex_lock(bitmap->mutex);
@@ -314,7 +324,7 @@ BdrvDirtyBitmap *bdrv_reclaim_dirty_bitmap_locked(BlockDriverState *bs,
return NULL;
}
- if (!hbitmap_merge(parent->bitmap, successor->bitmap)) {
+ if (!hbitmap_merge(parent->bitmap, successor->bitmap, parent->bitmap)) {
error_setg(errp, "Merging of parent and successor bitmap failed");
return NULL;
}
@@ -384,26 +394,6 @@ void bdrv_release_named_dirty_bitmaps(BlockDriverState *bs)
}
/**
- * Release all persistent dirty bitmaps attached to a BDS (for use in
- * bdrv_inactivate_recurse()).
- * There must not be any frozen bitmaps attached.
- * This function does not remove persistent bitmaps from the storage.
- * Called with BQL taken.
- */
-void bdrv_release_persistent_dirty_bitmaps(BlockDriverState *bs)
-{
- BdrvDirtyBitmap *bm, *next;
-
- bdrv_dirty_bitmaps_lock(bs);
- QLIST_FOREACH_SAFE(bm, &bs->dirty_bitmaps, list, next) {
- if (bdrv_dirty_bitmap_get_persistance(bm)) {
- bdrv_release_dirty_bitmap_locked(bm);
- }
- }
- bdrv_dirty_bitmaps_unlock(bs);
-}
-
-/**
* Remove persistent dirty bitmap from the storage if it exists.
* Absence of bitmap is not an error, because we have the following scenario:
* BdrvDirtyBitmap can have .persistent = true but not yet saved and have no
@@ -619,7 +609,6 @@ void bdrv_reset_dirty_bitmap(BdrvDirtyBitmap *bitmap,
void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out)
{
- assert(bdrv_dirty_bitmap_enabled(bitmap));
assert(!bdrv_dirty_bitmap_readonly(bitmap));
bdrv_dirty_bitmap_lock(bitmap);
if (!out) {
@@ -633,12 +622,12 @@ void bdrv_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap **out)
bdrv_dirty_bitmap_unlock(bitmap);
}
-void bdrv_undo_clear_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *in)
+void bdrv_restore_dirty_bitmap(BdrvDirtyBitmap *bitmap, HBitmap *backup)
{
HBitmap *tmp = bitmap->bitmap;
assert(bdrv_dirty_bitmap_enabled(bitmap));
assert(!bdrv_dirty_bitmap_readonly(bitmap));
- bitmap->bitmap = in;
+ bitmap->bitmap = backup;
hbitmap_free(tmp);
}
@@ -756,16 +745,24 @@ void bdrv_dirty_bitmap_set_persistance(BdrvDirtyBitmap *bitmap, bool persistent)
qemu_mutex_unlock(bitmap->mutex);
}
+/* Called with BQL taken. */
+void bdrv_dirty_bitmap_set_migration(BdrvDirtyBitmap *bitmap, bool migration)
+{
+ qemu_mutex_lock(bitmap->mutex);
+ bitmap->migration = migration;
+ qemu_mutex_unlock(bitmap->mutex);
+}
+
bool bdrv_dirty_bitmap_get_persistance(BdrvDirtyBitmap *bitmap)
{
- return bitmap->persistent;
+ return bitmap->persistent && !bitmap->migration;
}
bool bdrv_has_changed_persistent_bitmaps(BlockDriverState *bs)
{
BdrvDirtyBitmap *bm;
QLIST_FOREACH(bm, &bs->dirty_bitmaps, list) {
- if (bm->persistent && !bm->readonly) {
+ if (bm->persistent && !bm->readonly && !bm->migration) {
return true;
}
}
@@ -791,19 +788,41 @@ int64_t bdrv_dirty_bitmap_next_zero(BdrvDirtyBitmap *bitmap, uint64_t offset)
}
void bdrv_merge_dirty_bitmap(BdrvDirtyBitmap *dest, const BdrvDirtyBitmap *src,
- Error **errp)
+ HBitmap **backup, Error **errp)
{
+ bool ret;
+
/* only bitmaps from one bds are supported */
assert(dest->mutex == src->mutex);
qemu_mutex_lock(dest->mutex);
- assert(bdrv_dirty_bitmap_enabled(dest));
- assert(!bdrv_dirty_bitmap_readonly(dest));
+ if (bdrv_dirty_bitmap_user_locked(dest)) {
+ error_setg(errp, "Bitmap '%s' is currently in use by another"
+ " operation and cannot be modified", dest->name);
+ goto out;
+ }
+
+ if (bdrv_dirty_bitmap_readonly(dest)) {
+ error_setg(errp, "Bitmap '%s' is readonly and cannot be modified",
+ dest->name);
+ goto out;
+ }
- if (!hbitmap_merge(dest->bitmap, src->bitmap)) {
+ if (!hbitmap_can_merge(dest->bitmap, src->bitmap)) {
error_setg(errp, "Bitmaps are incompatible and can't be merged");
+ goto out;
+ }
+
+ if (backup) {
+ *backup = dest->bitmap;
+ dest->bitmap = hbitmap_alloc(dest->size, hbitmap_granularity(*backup));
+ ret = hbitmap_merge(*backup, src->bitmap, dest->bitmap);
+ } else {
+ ret = hbitmap_merge(dest->bitmap, src->bitmap, dest->bitmap);
}
+ assert(ret);
+out:
qemu_mutex_unlock(dest->mutex);
}
diff --git a/block/dmg.c b/block/dmg.c
index c9b3c519c4..1d9283ba2f 100644
--- a/block/dmg.c
+++ b/block/dmg.c
@@ -413,23 +413,17 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags,
int64_t offset;
int ret;
+ ret = bdrv_apply_auto_read_only(bs, NULL, errp);
+ if (ret < 0) {
+ return ret;
+ }
+
bs->file = bdrv_open_child(NULL, options, "file", bs, &child_file,
false, errp);
if (!bs->file) {
return -EINVAL;
}
- if (!bdrv_is_read_only(bs)) {
- error_report("Opening dmg images without an explicit read-only=on "
- "option is deprecated. Future versions will refuse to "
- "open the image instead of automatically marking the "
- "image read-only.");
- ret = bdrv_set_read_only(bs, true, errp);
- if (ret < 0) {
- return ret;
- }
- }
-
block_module_load_one("dmg-bz2");
s->n_chunks = 0;
diff --git a/block/file-posix.c b/block/file-posix.c
index 2da3a76355..07bbdab953 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -142,7 +142,6 @@ do { \
typedef struct BDRVRawState {
int fd;
- int lock_fd;
bool use_lock;
int type;
int open_flags;
@@ -152,6 +151,11 @@ typedef struct BDRVRawState {
uint64_t perm;
uint64_t shared_perm;
+ /* The perms bits whose corresponding bytes are already locked in
+ * s->fd. */
+ uint64_t locked_perm;
+ uint64_t locked_shared_perm;
+
#ifdef CONFIG_XFS
bool is_xfs:1;
#endif
@@ -205,7 +209,7 @@ static int cdrom_reopen(BlockDriverState *bs);
#endif
#if defined(__NetBSD__)
-static int raw_normalize_devicepath(const char **filename)
+static int raw_normalize_devicepath(const char **filename, Error **errp)
{
static char namebuf[PATH_MAX];
const char *dp, *fname;
@@ -214,8 +218,7 @@ static int raw_normalize_devicepath(const char **filename)
fname = *filename;
dp = strrchr(fname, '/');
if (lstat(fname, &sb) < 0) {
- fprintf(stderr, "%s: stat failed: %s\n",
- fname, strerror(errno));
+ error_setg_errno(errp, errno, "%s: stat failed", fname);
return -errno;
}
@@ -229,14 +232,13 @@ static int raw_normalize_devicepath(const char **filename)
snprintf(namebuf, PATH_MAX, "%.*s/r%s",
(int)(dp - fname), fname, dp + 1);
}
- fprintf(stderr, "%s is a block device", fname);
*filename = namebuf;
- fprintf(stderr, ", using %s\n", *filename);
+ warn_report("%s is a block device, using %s", fname, *filename);
return 0;
}
#else
-static int raw_normalize_devicepath(const char **filename)
+static int raw_normalize_devicepath(const char **filename, Error **errp)
{
return 0;
}
@@ -461,9 +463,8 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
filename = qemu_opt_get(opts, "filename");
- ret = raw_normalize_devicepath(&filename);
+ ret = raw_normalize_devicepath(&filename, errp);
if (ret != 0) {
- error_setg_errno(errp, -ret, "Could not normalize device path");
goto fail;
}
@@ -492,11 +493,10 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
case ON_OFF_AUTO_ON:
s->use_lock = true;
if (!qemu_has_ofd_lock()) {
- fprintf(stderr,
- "File lock requested but OFD locking syscall is "
- "unavailable, falling back to POSIX file locks.\n"
- "Due to the implementation, locks can be lost "
- "unexpectedly.\n");
+ warn_report("File lock requested but OFD locking syscall is "
+ "unavailable, falling back to POSIX file locks");
+ error_printf("Due to the implementation, locks can be lost "
+ "unexpectedly.\n");
}
break;
case ON_OFF_AUTO_OFF:
@@ -527,9 +527,22 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
s->fd = -1;
fd = qemu_open(filename, s->open_flags, 0644);
- if (fd < 0) {
- ret = -errno;
- error_setg_errno(errp, errno, "Could not open '%s'", filename);
+ ret = fd < 0 ? -errno : 0;
+
+ if (ret == -EACCES || ret == -EROFS) {
+ /* Try to degrade to read-only, but if it doesn't work, still use the
+ * normal error message. */
+ if (bdrv_apply_auto_read_only(bs, NULL, NULL) == 0) {
+ bdrv_flags &= ~BDRV_O_RDWR;
+ raw_parse_flags(bdrv_flags, &s->open_flags);
+ assert(!(s->open_flags & O_CREAT));
+ fd = qemu_open(filename, s->open_flags);
+ ret = fd < 0 ? -errno : 0;
+ }
+ }
+
+ if (ret < 0) {
+ error_setg_errno(errp, -ret, "Could not open '%s'", filename);
if (ret == -EROFS) {
ret = -EACCES;
}
@@ -537,18 +550,6 @@ static int raw_open_common(BlockDriverState *bs, QDict *options,
}
s->fd = fd;
- s->lock_fd = -1;
- if (s->use_lock) {
- fd = qemu_open(filename, s->open_flags);
- if (fd < 0) {
- ret = -errno;
- error_setg_errno(errp, errno, "Could not open '%s' for locking",
- filename);
- qemu_close(s->fd);
- goto fail;
- }
- s->lock_fd = fd;
- }
s->perm = 0;
s->shared_perm = BLK_PERM_ALL;
@@ -680,43 +681,72 @@ typedef enum {
* file; if @unlock == true, also unlock the unneeded bytes.
* @shared_perm_lock_bits is the mask of all permissions that are NOT shared.
*/
-static int raw_apply_lock_bytes(int fd,
+static int raw_apply_lock_bytes(BDRVRawState *s, int fd,
uint64_t perm_lock_bits,
uint64_t shared_perm_lock_bits,
bool unlock, Error **errp)
{
int ret;
int i;
+ uint64_t locked_perm, locked_shared_perm;
+
+ if (s) {
+ locked_perm = s->locked_perm;
+ locked_shared_perm = s->locked_shared_perm;
+ } else {
+ /*
+ * We don't have the previous bits, just lock/unlock for each of the
+ * requested bits.
+ */
+ if (unlock) {
+ locked_perm = BLK_PERM_ALL;
+ locked_shared_perm = BLK_PERM_ALL;
+ } else {
+ locked_perm = 0;
+ locked_shared_perm = 0;
+ }
+ }
PERM_FOREACH(i) {
int off = RAW_LOCK_PERM_BASE + i;
- if (perm_lock_bits & (1ULL << i)) {
+ uint64_t bit = (1ULL << i);
+ if ((perm_lock_bits & bit) && !(locked_perm & bit)) {
ret = qemu_lock_fd(fd, off, 1, false);
if (ret) {
error_setg(errp, "Failed to lock byte %d", off);
return ret;
+ } else if (s) {
+ s->locked_perm |= bit;
}
- } else if (unlock) {
+ } else if (unlock && (locked_perm & bit) && !(perm_lock_bits & bit)) {
ret = qemu_unlock_fd(fd, off, 1);
if (ret) {
error_setg(errp, "Failed to unlock byte %d", off);
return ret;
+ } else if (s) {
+ s->locked_perm &= ~bit;
}
}
}
PERM_FOREACH(i) {
int off = RAW_LOCK_SHARED_BASE + i;
- if (shared_perm_lock_bits & (1ULL << i)) {
+ uint64_t bit = (1ULL << i);
+ if ((shared_perm_lock_bits & bit) && !(locked_shared_perm & bit)) {
ret = qemu_lock_fd(fd, off, 1, false);
if (ret) {
error_setg(errp, "Failed to lock byte %d", off);
return ret;
+ } else if (s) {
+ s->locked_shared_perm |= bit;
}
- } else if (unlock) {
+ } else if (unlock && (locked_shared_perm & bit) &&
+ !(shared_perm_lock_bits & bit)) {
ret = qemu_unlock_fd(fd, off, 1);
if (ret) {
error_setg(errp, "Failed to unlock byte %d", off);
return ret;
+ } else if (s) {
+ s->locked_shared_perm &= ~bit;
}
}
}
@@ -780,15 +810,13 @@ static int raw_handle_perm_lock(BlockDriverState *bs,
return 0;
}
- assert(s->lock_fd > 0);
-
switch (op) {
case RAW_PL_PREPARE:
- ret = raw_apply_lock_bytes(s->lock_fd, s->perm | new_perm,
+ ret = raw_apply_lock_bytes(s, s->fd, s->perm | new_perm,
~s->shared_perm | ~new_shared,
false, errp);
if (!ret) {
- ret = raw_check_lock_bytes(s->lock_fd, new_perm, new_shared, errp);
+ ret = raw_check_lock_bytes(s->fd, new_perm, new_shared, errp);
if (!ret) {
return 0;
}
@@ -799,23 +827,23 @@ static int raw_handle_perm_lock(BlockDriverState *bs,
op = RAW_PL_ABORT;
/* fall through to unlock bytes. */
case RAW_PL_ABORT:
- raw_apply_lock_bytes(s->lock_fd, s->perm, ~s->shared_perm,
+ raw_apply_lock_bytes(s, s->fd, s->perm, ~s->shared_perm,
true, &local_err);
if (local_err) {
/* Theoretically the above call only unlocks bytes and it cannot
* fail. Something weird happened, report it.
*/
- error_report_err(local_err);
+ warn_report_err(local_err);
}
break;
case RAW_PL_COMMIT:
- raw_apply_lock_bytes(s->lock_fd, new_perm, ~new_shared,
+ raw_apply_lock_bytes(s, s->fd, new_perm, ~new_shared,
true, &local_err);
if (local_err) {
/* Theoretically the above call only unlocks bytes and it cannot
* fail. Something weird happened, report it.
*/
- error_report_err(local_err);
+ warn_report_err(local_err);
}
break;
}
@@ -892,10 +920,8 @@ static int raw_reopen_prepare(BDRVReopenState *state,
/* If we cannot use fcntl, or fcntl failed, fall back to qemu_open() */
if (rs->fd == -1) {
const char *normalized_filename = state->bs->filename;
- ret = raw_normalize_devicepath(&normalized_filename);
- if (ret < 0) {
- error_setg_errno(errp, -ret, "Could not normalize device path");
- } else {
+ ret = raw_normalize_devicepath(&normalized_filename, errp);
+ if (ret >= 0) {
assert(!(rs->open_flags & O_CREAT));
rs->fd = qemu_open(normalized_filename, rs->open_flags);
if (rs->fd == -1) {
@@ -926,10 +952,18 @@ static void raw_reopen_commit(BDRVReopenState *state)
{
BDRVRawReopenState *rs = state->opaque;
BDRVRawState *s = state->bs->opaque;
+ Error *local_err = NULL;
s->check_cache_dropped = rs->check_cache_dropped;
s->open_flags = rs->open_flags;
+ /* Copy locks to the new fd before closing the old one. */
+ raw_apply_lock_bytes(NULL, rs->fd, s->locked_perm,
+ s->locked_shared_perm, false, &local_err);
+ if (local_err) {
+ /* shouldn't fail in a sane host, but report it just in case. */
+ error_report_err(local_err);
+ }
qemu_close(s->fd);
s->fd = rs->fd;
@@ -1775,7 +1809,7 @@ static int aio_worker(void *arg)
ret = handle_aiocb_truncate(aiocb);
break;
default:
- fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type);
+ error_report("invalid aio request (0x%x)", aiocb->aio_type);
ret = -EINVAL;
break;
}
@@ -1922,10 +1956,6 @@ static void raw_close(BlockDriverState *bs)
qemu_close(s->fd);
s->fd = -1;
}
- if (s->lock_fd >= 0) {
- qemu_close(s->lock_fd);
- s->lock_fd = -1;
- }
}
/**
@@ -2213,7 +2243,7 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp)
shared = BLK_PERM_ALL & ~BLK_PERM_RESIZE;
/* Step one: Take locks */
- result = raw_apply_lock_bytes(fd, perm, ~shared, false, errp);
+ result = raw_apply_lock_bytes(NULL, fd, perm, ~shared, false, errp);
if (result < 0) {
goto out_close;
}
@@ -2257,13 +2287,13 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp)
}
out_unlock:
- raw_apply_lock_bytes(fd, 0, 0, true, &local_err);
+ raw_apply_lock_bytes(NULL, fd, 0, 0, true, &local_err);
if (local_err) {
/* The above call should not fail, and if it does, that does
* not mean the whole creation operation has failed. So
* report it the user for their convenience, but do not report
* it to the caller. */
- error_report_err(local_err);
+ warn_report_err(local_err);
}
out_close:
@@ -3128,9 +3158,8 @@ static int coroutine_fn hdev_co_create_opts(const char *filename, QemuOpts *opts
(void)has_prefix;
- ret = raw_normalize_devicepath(&filename);
+ ret = raw_normalize_devicepath(&filename, errp);
if (ret < 0) {
- error_setg_errno(errp, -ret, "Could not normalize device path");
return ret;
}
diff --git a/block/gluster.c b/block/gluster.c
index 4fd55a9cc5..5e300c96c8 100644
--- a/block/gluster.c
+++ b/block/gluster.c
@@ -849,8 +849,16 @@ static int qemu_gluster_open(BlockDriverState *bs, QDict *options,
qemu_gluster_parse_flags(bdrv_flags, &open_flags);
s->fd = glfs_open(s->glfs, gconf->path, open_flags);
- if (!s->fd) {
- ret = -errno;
+ ret = s->fd ? 0 : -errno;
+
+ if (ret == -EACCES || ret == -EROFS) {
+ /* Try to degrade to read-only, but if it doesn't work, still use the
+ * normal error message. */
+ if (bdrv_apply_auto_read_only(bs, NULL, NULL) == 0) {
+ open_flags = (open_flags & ~O_RDWR) | O_RDONLY;
+ s->fd = glfs_open(s->glfs, gconf->path, open_flags);
+ ret = s->fd ? 0 : -errno;
+ }
}
s->supports_seek_data = qemu_gluster_test_seek(s->fd);
diff --git a/block/iscsi.c b/block/iscsi.c
index bb69faf34a..727dee50bf 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -1844,7 +1844,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
iscsi_set_timeout(iscsi, timeout);
#else
if (timeout) {
- error_report("iSCSI: ignoring timeout value for libiscsi <1.15.0");
+ warn_report("iSCSI: ignoring timeout value for libiscsi <1.15.0");
}
#endif
@@ -1878,9 +1878,11 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
/* Check the write protect flag of the LUN if we want to write */
if (iscsilun->type == TYPE_DISK && (flags & BDRV_O_RDWR) &&
iscsilun->write_protected) {
- error_setg(errp, "Cannot open a write protected LUN as read-write");
- ret = -EACCES;
- goto out;
+ ret = bdrv_apply_auto_read_only(bs, "LUN is write protected", errp);
+ if (ret < 0) {
+ goto out;
+ }
+ flags &= ~BDRV_O_RDWR;
}
iscsi_readcapacity_sync(iscsilun, &local_err);
diff --git a/block/nbd-client.c b/block/nbd-client.c
index 9686ecbd5e..76e9ca3abe 100644
--- a/block/nbd-client.c
+++ b/block/nbd-client.c
@@ -992,11 +992,11 @@ int nbd_client_init(BlockDriverState *bs,
logout("Failed to negotiate with the NBD server\n");
return ret;
}
- if (client->info.flags & NBD_FLAG_READ_ONLY &&
- !bdrv_is_read_only(bs)) {
- error_setg(errp,
- "request for write access conflicts with read-only export");
- return -EACCES;
+ if (client->info.flags & NBD_FLAG_READ_ONLY) {
+ ret = bdrv_apply_auto_read_only(bs, "NBD export is read-only", errp);
+ if (ret < 0) {
+ return ret;
+ }
}
if (client->info.flags & NBD_FLAG_SEND_FUA) {
bs->supported_write_flags = BDRV_REQ_FUA;
diff --git a/block/qcow.c b/block/qcow.c
index 385d935258..4518cb4c35 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -140,14 +140,14 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
if (ret < 0) {
goto fail;
}
- be32_to_cpus(&header.magic);
- be32_to_cpus(&header.version);
- be64_to_cpus(&header.backing_file_offset);
- be32_to_cpus(&header.backing_file_size);
- be32_to_cpus(&header.mtime);
- be64_to_cpus(&header.size);
- be32_to_cpus(&header.crypt_method);
- be64_to_cpus(&header.l1_table_offset);
+ header.magic = be32_to_cpu(header.magic);
+ header.version = be32_to_cpu(header.version);
+ header.backing_file_offset = be64_to_cpu(header.backing_file_offset);
+ header.backing_file_size = be32_to_cpu(header.backing_file_size);
+ header.mtime = be32_to_cpu(header.mtime);
+ header.size = be64_to_cpu(header.size);
+ header.crypt_method = be32_to_cpu(header.crypt_method);
+ header.l1_table_offset = be64_to_cpu(header.l1_table_offset);
if (header.magic != QCOW_MAGIC) {
error_setg(errp, "Image not in qcow format");
@@ -270,7 +270,7 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags,
}
for(i = 0;i < s->l1_size; i++) {
- be64_to_cpus(&s->l1_table[i]);
+ s->l1_table[i] = be64_to_cpu(s->l1_table[i]);
}
/* alloc L2 cache (max. 64k * 16 * 8 = 8 MB) */
diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c
index ba978ad2aa..accebef4cf 100644
--- a/block/qcow2-bitmap.c
+++ b/block/qcow2-bitmap.c
@@ -118,7 +118,7 @@ static inline void bitmap_table_to_be(uint64_t *bitmap_table, size_t size)
size_t i;
for (i = 0; i < size; ++i) {
- cpu_to_be64s(&bitmap_table[i]);
+ bitmap_table[i] = cpu_to_be64(bitmap_table[i]);
}
}
@@ -231,7 +231,7 @@ static int bitmap_table_load(BlockDriverState *bs, Qcow2BitmapTable *tb,
}
for (i = 0; i < tb->size; ++i) {
- be64_to_cpus(&table[i]);
+ table[i] = be64_to_cpu(table[i]);
ret = check_table_entry(table[i], s->cluster_size);
if (ret < 0) {
goto fail;
@@ -394,20 +394,20 @@ fail:
static inline void bitmap_dir_entry_to_cpu(Qcow2BitmapDirEntry *entry)
{
- be64_to_cpus(&entry->bitmap_table_offset);
- be32_to_cpus(&entry->bitmap_table_size);
- be32_to_cpus(&entry->flags);
- be16_to_cpus(&entry->name_size);
- be32_to_cpus(&entry->extra_data_size);
+ entry->bitmap_table_offset = be64_to_cpu(entry->bitmap_table_offset);
+ entry->bitmap_table_size = be32_to_cpu(entry->bitmap_table_size);
+ entry->flags = be32_to_cpu(entry->flags);
+ entry->name_size = be16_to_cpu(entry->name_size);
+ entry->extra_data_size = be32_to_cpu(entry->extra_data_size);
}
static inline void bitmap_dir_entry_to_be(Qcow2BitmapDirEntry *entry)
{
- cpu_to_be64s(&entry->bitmap_table_offset);
- cpu_to_be32s(&entry->bitmap_table_size);
- cpu_to_be32s(&entry->flags);
- cpu_to_be16s(&entry->name_size);
- cpu_to_be32s(&entry->extra_data_size);
+ entry->bitmap_table_offset = cpu_to_be64(entry->bitmap_table_offset);
+ entry->bitmap_table_size = cpu_to_be32(entry->bitmap_table_size);
+ entry->flags = cpu_to_be32(entry->flags);
+ entry->name_size = cpu_to_be16(entry->name_size);
+ entry->extra_data_size = cpu_to_be32(entry->extra_data_size);
}
static inline int calc_dir_entry_size(size_t name_size, size_t extra_data_size)
@@ -1418,6 +1418,22 @@ void qcow2_store_persistent_dirty_bitmaps(BlockDriverState *bs, Error **errp)
g_free(tb);
}
+ QSIMPLEQ_FOREACH(bm, bm_list, entry) {
+ /* For safety, we remove bitmap after storing.
+ * We may be here in two cases:
+ * 1. bdrv_close. It's ok to drop bitmap.
+ * 2. inactivation. It means migration without 'dirty-bitmaps'
+ * capability, so bitmaps are not marked with
+ * BdrvDirtyBitmap.migration flags. It's not bad to drop them too,
+ * and reload on invalidation.
+ */
+ if (bm->dirty_bitmap == NULL) {
+ continue;
+ }
+
+ bdrv_release_dirty_bitmap(bs, bm->dirty_bitmap);
+ }
+
bitmap_list_free(bm_list);
return;
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 3c539f02e5..1c63ac244a 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -31,7 +31,8 @@
#include "qemu/bswap.h"
#include "qemu/cutils.h"
-static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size);
+static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size,
+ uint64_t max);
static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
int64_t offset, int64_t length, uint64_t addend,
bool decrease, enum qcow2_discard_type type);
@@ -362,7 +363,7 @@ static int alloc_refcount_block(BlockDriverState *bs,
}
/* Allocate the refcount block itself and mark it as used */
- int64_t new_block = alloc_clusters_noref(bs, s->cluster_size);
+ int64_t new_block = alloc_clusters_noref(bs, s->cluster_size, INT64_MAX);
if (new_block < 0) {
return new_block;
}
@@ -954,7 +955,8 @@ int qcow2_update_cluster_refcount(BlockDriverState *bs,
/* return < 0 if error */
-static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size)
+static int64_t alloc_clusters_noref(BlockDriverState *bs, uint64_t size,
+ uint64_t max)
{
BDRVQcow2State *s = bs->opaque;
uint64_t i, nb_clusters, refcount;
@@ -979,9 +981,9 @@ retry:
}
/* Make sure that all offsets in the "allocated" range are representable
- * in an int64_t */
+ * in the requested max */
if (s->free_cluster_index > 0 &&
- s->free_cluster_index - 1 > (INT64_MAX >> s->cluster_bits))
+ s->free_cluster_index - 1 > (max >> s->cluster_bits))
{
return -EFBIG;
}
@@ -1001,7 +1003,7 @@ int64_t qcow2_alloc_clusters(BlockDriverState *bs, uint64_t size)
BLKDBG_EVENT(bs->file, BLKDBG_CLUSTER_ALLOC);
do {
- offset = alloc_clusters_noref(bs, size);
+ offset = alloc_clusters_noref(bs, size, QCOW_MAX_CLUSTER_OFFSET);
if (offset < 0) {
return offset;
}
@@ -1083,7 +1085,11 @@ int64_t qcow2_alloc_bytes(BlockDriverState *bs, int size)
free_in_cluster = s->cluster_size - offset_into_cluster(s, offset);
do {
if (!offset || free_in_cluster < size) {
- int64_t new_cluster = alloc_clusters_noref(bs, s->cluster_size);
+ int64_t new_cluster;
+
+ new_cluster = alloc_clusters_noref(bs, s->cluster_size,
+ MIN(s->cluster_offset_mask,
+ QCOW_MAX_CLUSTER_OFFSET));
if (new_cluster < 0) {
return new_cluster;
}
@@ -2719,15 +2725,17 @@ int qcow2_check_metadata_overlap(BlockDriverState *bs, int ign, int64_t offset,
}
static const char *metadata_ol_names[] = {
- [QCOW2_OL_MAIN_HEADER_BITNR] = "qcow2_header",
- [QCOW2_OL_ACTIVE_L1_BITNR] = "active L1 table",
- [QCOW2_OL_ACTIVE_L2_BITNR] = "active L2 table",
- [QCOW2_OL_REFCOUNT_TABLE_BITNR] = "refcount table",
- [QCOW2_OL_REFCOUNT_BLOCK_BITNR] = "refcount block",
- [QCOW2_OL_SNAPSHOT_TABLE_BITNR] = "snapshot table",
- [QCOW2_OL_INACTIVE_L1_BITNR] = "inactive L1 table",
- [QCOW2_OL_INACTIVE_L2_BITNR] = "inactive L2 table",
+ [QCOW2_OL_MAIN_HEADER_BITNR] = "qcow2_header",
+ [QCOW2_OL_ACTIVE_L1_BITNR] = "active L1 table",
+ [QCOW2_OL_ACTIVE_L2_BITNR] = "active L2 table",
+ [QCOW2_OL_REFCOUNT_TABLE_BITNR] = "refcount table",
+ [QCOW2_OL_REFCOUNT_BLOCK_BITNR] = "refcount block",
+ [QCOW2_OL_SNAPSHOT_TABLE_BITNR] = "snapshot table",
+ [QCOW2_OL_INACTIVE_L1_BITNR] = "inactive L1 table",
+ [QCOW2_OL_INACTIVE_L2_BITNR] = "inactive L2 table",
+ [QCOW2_OL_BITMAP_DIRECTORY_BITNR] = "bitmap directory",
};
+QEMU_BUILD_BUG_ON(QCOW2_OL_MAX_BITNR != ARRAY_SIZE(metadata_ol_names));
/*
* First performs a check for metadata overlaps (through
diff --git a/block/qcow2.c b/block/qcow2.c
index 7277feda13..991d6ac91b 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -210,8 +210,8 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
"pread fail from offset %" PRIu64, offset);
return 1;
}
- be32_to_cpus(&ext.magic);
- be32_to_cpus(&ext.len);
+ ext.magic = be32_to_cpu(ext.magic);
+ ext.len = be32_to_cpu(ext.len);
offset += sizeof(ext);
#ifdef DEBUG_EXT
printf("ext.magic = 0x%x\n", ext.magic);
@@ -279,8 +279,8 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
"Unable to read CRYPTO header extension");
return ret;
}
- be64_to_cpus(&s->crypto_header.offset);
- be64_to_cpus(&s->crypto_header.length);
+ s->crypto_header.offset = be64_to_cpu(s->crypto_header.offset);
+ s->crypto_header.length = be64_to_cpu(s->crypto_header.length);
if ((s->crypto_header.offset % s->cluster_size) != 0) {
error_setg(errp, "Encryption header offset '%" PRIu64 "' is "
@@ -342,9 +342,11 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
return -EINVAL;
}
- be32_to_cpus(&bitmaps_ext.nb_bitmaps);
- be64_to_cpus(&bitmaps_ext.bitmap_directory_size);
- be64_to_cpus(&bitmaps_ext.bitmap_directory_offset);
+ bitmaps_ext.nb_bitmaps = be32_to_cpu(bitmaps_ext.nb_bitmaps);
+ bitmaps_ext.bitmap_directory_size =
+ be64_to_cpu(bitmaps_ext.bitmap_directory_size);
+ bitmaps_ext.bitmap_directory_offset =
+ be64_to_cpu(bitmaps_ext.bitmap_directory_offset);
if (bitmaps_ext.nb_bitmaps > QCOW2_MAX_BITMAPS) {
error_setg(errp,
@@ -1153,26 +1155,26 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
uint64_t ext_end;
uint64_t l1_vm_state_index;
bool update_header = false;
- bool header_updated = false;
ret = bdrv_pread(bs->file, 0, &header, sizeof(header));
if (ret < 0) {
error_setg_errno(errp, -ret, "Could not read qcow2 header");
goto fail;
}
- be32_to_cpus(&header.magic);
- be32_to_cpus(&header.version);
- be64_to_cpus(&header.backing_file_offset);
- be32_to_cpus(&header.backing_file_size);
- be64_to_cpus(&header.size);
- be32_to_cpus(&header.cluster_bits);
- be32_to_cpus(&header.crypt_method);
- be64_to_cpus(&header.l1_table_offset);
- be32_to_cpus(&header.l1_size);
- be64_to_cpus(&header.refcount_table_offset);
- be32_to_cpus(&header.refcount_table_clusters);
- be64_to_cpus(&header.snapshots_offset);
- be32_to_cpus(&header.nb_snapshots);
+ header.magic = be32_to_cpu(header.magic);
+ header.version = be32_to_cpu(header.version);
+ header.backing_file_offset = be64_to_cpu(header.backing_file_offset);
+ header.backing_file_size = be32_to_cpu(header.backing_file_size);
+ header.size = be64_to_cpu(header.size);
+ header.cluster_bits = be32_to_cpu(header.cluster_bits);
+ header.crypt_method = be32_to_cpu(header.crypt_method);
+ header.l1_table_offset = be64_to_cpu(header.l1_table_offset);
+ header.l1_size = be32_to_cpu(header.l1_size);
+ header.refcount_table_offset = be64_to_cpu(header.refcount_table_offset);
+ header.refcount_table_clusters =
+ be32_to_cpu(header.refcount_table_clusters);
+ header.snapshots_offset = be64_to_cpu(header.snapshots_offset);
+ header.nb_snapshots = be32_to_cpu(header.nb_snapshots);
if (header.magic != QCOW_MAGIC) {
error_setg(errp, "Image is not in qcow2 format");
@@ -1208,11 +1210,12 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
header.refcount_order = 4;
header.header_length = 72;
} else {
- be64_to_cpus(&header.incompatible_features);
- be64_to_cpus(&header.compatible_features);
- be64_to_cpus(&header.autoclear_features);
- be32_to_cpus(&header.refcount_order);
- be32_to_cpus(&header.header_length);
+ header.incompatible_features =
+ be64_to_cpu(header.incompatible_features);
+ header.compatible_features = be64_to_cpu(header.compatible_features);
+ header.autoclear_features = be64_to_cpu(header.autoclear_features);
+ header.refcount_order = be32_to_cpu(header.refcount_order);
+ header.header_length = be32_to_cpu(header.header_length);
if (header.header_length < 104) {
error_setg(errp, "qcow2 header too short");
@@ -1401,7 +1404,7 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
goto fail;
}
for(i = 0;i < s->l1_size; i++) {
- be64_to_cpus(&s->l1_table[i]);
+ s->l1_table[i] = be64_to_cpu(s->l1_table[i]);
}
}
@@ -1492,23 +1495,70 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options,
s->autoclear_features &= QCOW2_AUTOCLEAR_MASK;
}
- if (s->dirty_bitmaps_loaded) {
- /* It's some kind of reopen. There are no known cases where we need to
- * reload bitmaps in such a situation, so it's safer to skip them.
- *
- * Moreover, if we have some readonly bitmaps and we are reopening for
- * rw we should reopen bitmaps correspondingly.
- */
- if (bdrv_has_readonly_bitmaps(bs) &&
- !bdrv_is_read_only(bs) && !(bdrv_get_flags(bs) & BDRV_O_INACTIVE))
- {
- qcow2_reopen_bitmaps_rw_hint(bs, &header_updated, &local_err);
- }
- } else {
- header_updated = qcow2_load_dirty_bitmaps(bs, &local_err);
- s->dirty_bitmaps_loaded = true;
+ /* == Handle persistent dirty bitmaps ==
+ *
+ * We want load dirty bitmaps in three cases:
+ *
+ * 1. Normal open of the disk in active mode, not related to invalidation
+ * after migration.
+ *
+ * 2. Invalidation of the target vm after pre-copy phase of migration, if
+ * bitmaps are _not_ migrating through migration channel, i.e.
+ * 'dirty-bitmaps' capability is disabled.
+ *
+ * 3. Invalidation of source vm after failed or canceled migration.
+ * This is a very interesting case. There are two possible types of
+ * bitmaps:
+ *
+ * A. Stored on inactivation and removed. They should be loaded from the
+ * image.
+ *
+ * B. Not stored: not-persistent bitmaps and bitmaps, migrated through
+ * the migration channel (with dirty-bitmaps capability).
+ *
+ * On the other hand, there are two possible sub-cases:
+ *
+ * 3.1 disk was changed by somebody else while were inactive. In this
+ * case all in-RAM dirty bitmaps (both persistent and not) are
+ * definitely invalid. And we don't have any method to determine
+ * this.
+ *
+ * Simple and safe thing is to just drop all the bitmaps of type B on
+ * inactivation. But in this case we lose bitmaps in valid 4.2 case.
+ *
+ * On the other hand, resuming source vm, if disk was already changed
+ * is a bad thing anyway: not only bitmaps, the whole vm state is
+ * out of sync with disk.
+ *
+ * This means, that user or management tool, who for some reason
+ * decided to resume source vm, after disk was already changed by
+ * target vm, should at least drop all dirty bitmaps by hand.
+ *
+ * So, we can ignore this case for now, but TODO: "generation"
+ * extension for qcow2, to determine, that image was changed after
+ * last inactivation. And if it is changed, we will drop (or at least
+ * mark as 'invalid' all the bitmaps of type B, both persistent
+ * and not).
+ *
+ * 3.2 disk was _not_ changed while were inactive. Bitmaps may be saved
+ * to disk ('dirty-bitmaps' capability disabled), or not saved
+ * ('dirty-bitmaps' capability enabled), but we don't need to care
+ * of: let's load bitmaps as always: stored bitmaps will be loaded,
+ * and not stored has flag IN_USE=1 in the image and will be skipped
+ * on loading.
+ *
+ * One remaining possible case when we don't want load bitmaps:
+ *
+ * 4. Open disk in inactive mode in target vm (bitmaps are migrating or
+ * will be loaded on invalidation, no needs try loading them before)
+ */
+
+ if (!(bdrv_get_flags(bs) & BDRV_O_INACTIVE)) {
+ /* It's case 1, 2 or 3.2. Or 3.1 which is BUG in management layer. */
+ bool header_updated = qcow2_load_dirty_bitmaps(bs, &local_err);
+
+ update_header = update_header && !header_updated;
}
- update_header = update_header && !header_updated;
if (local_err != NULL) {
error_propagate(errp, local_err);
ret = -EINVAL;
@@ -1627,7 +1677,7 @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
if (bs->encrypted) {
/* Encryption works on a sector granularity */
- bs->bl.request_alignment = BDRV_SECTOR_SIZE;
+ bs->bl.request_alignment = qcrypto_block_get_sector_size(s->crypto);
}
bs->bl.pwrite_zeroes_alignment = s->cluster_size;
bs->bl.pdiscard_alignment = s->cluster_size;
@@ -2123,9 +2173,9 @@ static int qcow2_inactivate(BlockDriverState *bs)
qcow2_store_persistent_dirty_bitmaps(bs, &local_err);
if (local_err != NULL) {
result = -EINVAL;
- error_report_err(local_err);
- error_report("Persistent bitmaps are lost for node '%s'",
- bdrv_get_device_or_node_name(bs));
+ error_reportf_err(local_err, "Lost persistent bitmaps during "
+ "inactivation of node '%s': ",
+ bdrv_get_device_or_node_name(bs));
}
ret = qcow2_cache_flush(bs, s->l2_table_cache);
@@ -2208,8 +2258,8 @@ static void coroutine_fn qcow2_co_invalidate_cache(BlockDriverState *bs,
qemu_co_mutex_unlock(&s->lock);
qobject_unref(options);
if (local_err) {
- error_propagate(errp, local_err);
- error_prepend(errp, "Could not reopen qcow2 layer: ");
+ error_propagate_prepend(errp, local_err,
+ "Could not reopen qcow2 layer: ");
bs->drv = NULL;
return;
} else if (ret < 0) {
@@ -2346,13 +2396,13 @@ int qcow2_update_header(BlockDriverState *bs)
/* Full disk encryption header pointer extension */
if (s->crypto_header.offset != 0) {
- cpu_to_be64s(&s->crypto_header.offset);
- cpu_to_be64s(&s->crypto_header.length);
+ s->crypto_header.offset = cpu_to_be64(s->crypto_header.offset);
+ s->crypto_header.length = cpu_to_be64(s->crypto_header.length);
ret = header_ext_add(buf, QCOW2_EXT_MAGIC_CRYPTO_HEADER,
&s->crypto_header, sizeof(s->crypto_header),
buflen);
- be64_to_cpus(&s->crypto_header.offset);
- be64_to_cpus(&s->crypto_header.length);
+ s->crypto_header.offset = be64_to_cpu(s->crypto_header.offset);
+ s->crypto_header.length = be64_to_cpu(s->crypto_header.length);
if (ret < 0) {
goto fail;
}
diff --git a/block/qcow2.h b/block/qcow2.h
index ba430316b9..8662b68575 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -42,6 +42,12 @@
#define QCOW_MAX_CRYPT_CLUSTERS 32
#define QCOW_MAX_SNAPSHOTS 65536
+/* Field widths in qcow2 mean normal cluster offsets cannot reach
+ * 64PB; depending on cluster size, compressed clusters can have a
+ * smaller limit (64PB for up to 16k clusters, then ramps down to
+ * 512TB for 2M clusters). */
+#define QCOW_MAX_CLUSTER_OFFSET ((1ULL << 56) - 1)
+
/* 8 MB refcount table is enough for 2 PB images at 64k cluster size
* (128 GB for 512 byte clusters, 2 EB for 2 MB clusters) */
#define QCOW_MAX_REFTABLE_SIZE S_8MiB
@@ -300,7 +306,6 @@ typedef struct BDRVQcow2State {
uint32_t nb_bitmaps;
uint64_t bitmap_directory_size;
uint64_t bitmap_directory_offset;
- bool dirty_bitmaps_loaded;
int flags;
int qcow_version;
diff --git a/block/qed.c b/block/qed.c
index 689ea9d4d5..9377c0b7ad 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -1606,8 +1606,8 @@ static void coroutine_fn bdrv_qed_co_invalidate_cache(BlockDriverState *bs,
ret = bdrv_qed_do_open(bs, NULL, bs->open_flags, &local_err);
qemu_co_mutex_unlock(&s->table_lock);
if (local_err) {
- error_propagate(errp, local_err);
- error_prepend(errp, "Could not reopen qed layer: ");
+ error_propagate_prepend(errp, local_err,
+ "Could not reopen qed layer: ");
return;
} else if (ret < 0) {
error_setg_errno(errp, -ret, "Could not reopen qed layer");
diff --git a/block/quorum.c b/block/quorum.c
index eb526cc0f1..16b3c8067c 100644
--- a/block/quorum.c
+++ b/block/quorum.c
@@ -437,23 +437,7 @@ static bool quorum_iovec_compare(QEMUIOVector *a, QEMUIOVector *b)
return true;
}
-static void GCC_FMT_ATTR(2, 3) quorum_err(QuorumAIOCB *acb,
- const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- fprintf(stderr, "quorum: offset=%" PRIu64 " bytes=%" PRIu64 " ",
- acb->offset, acb->bytes);
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
- va_end(ap);
- exit(1);
-}
-
-static bool quorum_compare(QuorumAIOCB *acb,
- QEMUIOVector *a,
- QEMUIOVector *b)
+static bool quorum_compare(QuorumAIOCB *acb, QEMUIOVector *a, QEMUIOVector *b)
{
BDRVQuorumState *s = acb->bs->opaque;
ssize_t offset;
@@ -462,8 +446,10 @@ static bool quorum_compare(QuorumAIOCB *acb,
if (s->is_blkverify) {
offset = qemu_iovec_compare(a, b);
if (offset != -1) {
- quorum_err(acb, "contents mismatch at offset %" PRIu64,
- acb->offset + offset);
+ fprintf(stderr, "quorum: offset=%" PRIu64 " bytes=%" PRIu64
+ " contents mismatch at offset %" PRIu64 "\n",
+ acb->offset, acb->bytes, acb->offset + offset);
+ exit(1);
}
return true;
}
@@ -926,13 +912,12 @@ static int quorum_open(BlockDriverState *bs, QDict *options, int flags,
s->read_pattern = ret;
if (s->read_pattern == QUORUM_READ_PATTERN_QUORUM) {
- /* is the driver in blkverify mode */
- if (qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false) &&
- s->num_children == 2 && s->threshold == 2) {
- s->is_blkverify = true;
- } else if (qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false)) {
- fprintf(stderr, "blkverify mode is set by setting blkverify=on "
- "and using two files with vote_threshold=2\n");
+ s->is_blkverify = qemu_opt_get_bool(opts, QUORUM_OPT_BLKVERIFY, false);
+ if (s->is_blkverify && (s->num_children != 2 || s->threshold != 2)) {
+ error_setg(&local_err, "blkverify=on can only be set if there are "
+ "exactly two files and vote-threshold is 2");
+ ret = -EINVAL;
+ goto exit;
}
s->rewrite_corrupted = qemu_opt_get_bool(opts, QUORUM_OPT_REWRITE,
@@ -1007,6 +992,11 @@ static void quorum_add_child(BlockDriverState *bs, BlockDriverState *child_bs,
char indexstr[32];
int ret;
+ if (s->is_blkverify) {
+ error_setg(errp, "Cannot add a child to a quorum in blkverify mode");
+ return;
+ }
+
assert(s->num_children <= INT_MAX / sizeof(BdrvChild *));
if (s->num_children == INT_MAX / sizeof(BdrvChild *) ||
s->next_child_index == UINT_MAX) {
@@ -1061,6 +1051,9 @@ static void quorum_del_child(BlockDriverState *bs, BdrvChild *child,
return;
}
+ /* We know now that num_children > threshold, so blkverify must be false */
+ assert(!s->is_blkverify);
+
bdrv_drained_begin(bs);
/* We can safely remove this child now */
diff --git a/block/rbd.c b/block/rbd.c
index 014c68d629..8a1a9f4b6e 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -750,8 +750,8 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
/* Take care whenever deciding to actually deprecate; once this ability
* is removed, we will not be able to open any images with legacy-styled
* backing image strings. */
- error_report("RBD options encoded in the filename as keyvalue pairs "
- "is deprecated");
+ warn_report("RBD options encoded in the filename as keyvalue pairs "
+ "is deprecated");
}
/* Remove the processed options from the QDict (the visitor processes
@@ -780,16 +780,10 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
/* If we are using an rbd snapshot, we must be r/o, otherwise
* leave as-is */
if (s->snap != NULL) {
- if (!bdrv_is_read_only(bs)) {
- error_report("Opening rbd snapshots without an explicit "
- "read-only=on option is deprecated. Future versions "
- "will refuse to open the image instead of "
- "automatically marking the image read-only.");
- r = bdrv_set_read_only(bs, true, &local_err);
- if (r < 0) {
- error_propagate(errp, local_err);
- goto failed_open;
- }
+ r = bdrv_apply_auto_read_only(bs, "rbd snapshots are read-only", errp);
+ if (r < 0) {
+ rbd_close(s->image);
+ goto failed_open;
}
}
diff --git a/block/sheepdog.c b/block/sheepdog.c
index b229a664d9..0125df9d49 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -572,7 +572,7 @@ static int connect_to_sdog(BDRVSheepdogState *s, Error **errp)
if (s->addr->type == SOCKET_ADDRESS_TYPE_INET && fd >= 0) {
int ret = socket_set_nodelay(fd);
if (ret < 0) {
- error_report("%s", strerror(errno));
+ warn_report("can't set TCP_NODELAY: %s", strerror(errno));
}
}
diff --git a/block/vdi.c b/block/vdi.c
index 6555cffb88..2380daa583 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -85,7 +85,7 @@
#define BLOCK_OPT_STATIC "static"
#define SECTOR_SIZE 512
-#define DEFAULT_CLUSTER_SIZE (1 * MiB)
+#define DEFAULT_CLUSTER_SIZE S_1MiB
#if defined(CONFIG_VDI_DEBUG)
#define VDI_DEBUG 1
@@ -187,22 +187,22 @@ typedef struct {
static void vdi_header_to_cpu(VdiHeader *header)
{
- le32_to_cpus(&header->signature);
- le32_to_cpus(&header->version);
- le32_to_cpus(&header->header_size);
- le32_to_cpus(&header->image_type);
- le32_to_cpus(&header->image_flags);
- le32_to_cpus(&header->offset_bmap);
- le32_to_cpus(&header->offset_data);
- le32_to_cpus(&header->cylinders);
- le32_to_cpus(&header->heads);
- le32_to_cpus(&header->sectors);
- le32_to_cpus(&header->sector_size);
- le64_to_cpus(&header->disk_size);
- le32_to_cpus(&header->block_size);
- le32_to_cpus(&header->block_extra);
- le32_to_cpus(&header->blocks_in_image);
- le32_to_cpus(&header->blocks_allocated);
+ header->signature = le32_to_cpu(header->signature);
+ header->version = le32_to_cpu(header->version);
+ header->header_size = le32_to_cpu(header->header_size);
+ header->image_type = le32_to_cpu(header->image_type);
+ header->image_flags = le32_to_cpu(header->image_flags);
+ header->offset_bmap = le32_to_cpu(header->offset_bmap);
+ header->offset_data = le32_to_cpu(header->offset_data);
+ header->cylinders = le32_to_cpu(header->cylinders);
+ header->heads = le32_to_cpu(header->heads);
+ header->sectors = le32_to_cpu(header->sectors);
+ header->sector_size = le32_to_cpu(header->sector_size);
+ header->disk_size = le64_to_cpu(header->disk_size);
+ header->block_size = le32_to_cpu(header->block_size);
+ header->block_extra = le32_to_cpu(header->block_extra);
+ header->blocks_in_image = le32_to_cpu(header->blocks_in_image);
+ header->blocks_allocated = le32_to_cpu(header->blocks_allocated);
qemu_uuid_bswap(&header->uuid_image);
qemu_uuid_bswap(&header->uuid_last_snap);
qemu_uuid_bswap(&header->uuid_link);
@@ -211,22 +211,22 @@ static void vdi_header_to_cpu(VdiHeader *header)
static void vdi_header_to_le(VdiHeader *header)
{
- cpu_to_le32s(&header->signature);
- cpu_to_le32s(&header->version);
- cpu_to_le32s(&header->header_size);
- cpu_to_le32s(&header->image_type);
- cpu_to_le32s(&header->image_flags);
- cpu_to_le32s(&header->offset_bmap);
- cpu_to_le32s(&header->offset_data);
- cpu_to_le32s(&header->cylinders);
- cpu_to_le32s(&header->heads);
- cpu_to_le32s(&header->sectors);
- cpu_to_le32s(&header->sector_size);
- cpu_to_le64s(&header->disk_size);
- cpu_to_le32s(&header->block_size);
- cpu_to_le32s(&header->block_extra);
- cpu_to_le32s(&header->blocks_in_image);
- cpu_to_le32s(&header->blocks_allocated);
+ header->signature = cpu_to_le32(header->signature);
+ header->version = cpu_to_le32(header->version);
+ header->header_size = cpu_to_le32(header->header_size);
+ header->image_type = cpu_to_le32(header->image_type);
+ header->image_flags = cpu_to_le32(header->image_flags);
+ header->offset_bmap = cpu_to_le32(header->offset_bmap);
+ header->offset_data = cpu_to_le32(header->offset_data);
+ header->cylinders = cpu_to_le32(header->cylinders);
+ header->heads = cpu_to_le32(header->heads);
+ header->sectors = cpu_to_le32(header->sectors);
+ header->sector_size = cpu_to_le32(header->sector_size);
+ header->disk_size = cpu_to_le64(header->disk_size);
+ header->block_size = cpu_to_le32(header->block_size);
+ header->block_extra = cpu_to_le32(header->block_extra);
+ header->blocks_in_image = cpu_to_le32(header->blocks_in_image);
+ header->blocks_allocated = cpu_to_le32(header->blocks_allocated);
qemu_uuid_bswap(&header->uuid_image);
qemu_uuid_bswap(&header->uuid_last_snap);
qemu_uuid_bswap(&header->uuid_link);
@@ -432,7 +432,7 @@ static int vdi_open(BlockDriverState *bs, QDict *options, int flags,
goto fail;
} else if (header.block_size != DEFAULT_CLUSTER_SIZE) {
error_setg(errp, "unsupported VDI image (block size %" PRIu32
- " is not %" PRIu64 ")",
+ " is not %" PRIu32 ")",
header.block_size, DEFAULT_CLUSTER_SIZE);
ret = -ENOTSUP;
goto fail;
diff --git a/block/vhdx-endian.c b/block/vhdx-endian.c
index 41fbdd2b8f..ebfa33cb8a 100644
--- a/block/vhdx-endian.c
+++ b/block/vhdx-endian.c
@@ -35,18 +35,18 @@ void vhdx_header_le_import(VHDXHeader *h)
{
assert(h != NULL);
- le32_to_cpus(&h->signature);
- le32_to_cpus(&h->checksum);
- le64_to_cpus(&h->sequence_number);
+ h->signature = le32_to_cpu(h->signature);
+ h->checksum = le32_to_cpu(h->checksum);
+ h->sequence_number = le64_to_cpu(h->sequence_number);
leguid_to_cpus(&h->file_write_guid);
leguid_to_cpus(&h->data_write_guid);
leguid_to_cpus(&h->log_guid);
- le16_to_cpus(&h->log_version);
- le16_to_cpus(&h->version);
- le32_to_cpus(&h->log_length);
- le64_to_cpus(&h->log_offset);
+ h->log_version = le16_to_cpu(h->log_version);
+ h->version = le16_to_cpu(h->version);
+ h->log_length = le32_to_cpu(h->log_length);
+ h->log_offset = le64_to_cpu(h->log_offset);
}
void vhdx_header_le_export(VHDXHeader *orig_h, VHDXHeader *new_h)
@@ -80,68 +80,68 @@ void vhdx_log_desc_le_import(VHDXLogDescriptor *d)
{
assert(d != NULL);
- le32_to_cpus(&d->signature);
- le64_to_cpus(&d->file_offset);
- le64_to_cpus(&d->sequence_number);
+ d->signature = le32_to_cpu(d->signature);
+ d->file_offset = le64_to_cpu(d->file_offset);
+ d->sequence_number = le64_to_cpu(d->sequence_number);
}
void vhdx_log_desc_le_export(VHDXLogDescriptor *d)
{
assert(d != NULL);
- cpu_to_le32s(&d->signature);
- cpu_to_le32s(&d->trailing_bytes);
- cpu_to_le64s(&d->leading_bytes);
- cpu_to_le64s(&d->file_offset);
- cpu_to_le64s(&d->sequence_number);
+ d->signature = cpu_to_le32(d->signature);
+ d->trailing_bytes = cpu_to_le32(d->trailing_bytes);
+ d->leading_bytes = cpu_to_le64(d->leading_bytes);
+ d->file_offset = cpu_to_le64(d->file_offset);
+ d->sequence_number = cpu_to_le64(d->sequence_number);
}
void vhdx_log_data_le_import(VHDXLogDataSector *d)
{
assert(d != NULL);
- le32_to_cpus(&d->data_signature);
- le32_to_cpus(&d->sequence_high);
- le32_to_cpus(&d->sequence_low);
+ d->data_signature = le32_to_cpu(d->data_signature);
+ d->sequence_high = le32_to_cpu(d->sequence_high);
+ d->sequence_low = le32_to_cpu(d->sequence_low);
}
void vhdx_log_data_le_export(VHDXLogDataSector *d)
{
assert(d != NULL);
- cpu_to_le32s(&d->data_signature);
- cpu_to_le32s(&d->sequence_high);
- cpu_to_le32s(&d->sequence_low);
+ d->data_signature = cpu_to_le32(d->data_signature);
+ d->sequence_high = cpu_to_le32(d->sequence_high);
+ d->sequence_low = cpu_to_le32(d->sequence_low);
}
void vhdx_log_entry_hdr_le_import(VHDXLogEntryHeader *hdr)
{
assert(hdr != NULL);
- le32_to_cpus(&hdr->signature);
- le32_to_cpus(&hdr->checksum);
- le32_to_cpus(&hdr->entry_length);
- le32_to_cpus(&hdr->tail);
- le64_to_cpus(&hdr->sequence_number);
- le32_to_cpus(&hdr->descriptor_count);
+ hdr->signature = le32_to_cpu(hdr->signature);
+ hdr->checksum = le32_to_cpu(hdr->checksum);
+ hdr->entry_length = le32_to_cpu(hdr->entry_length);
+ hdr->tail = le32_to_cpu(hdr->tail);
+ hdr->sequence_number = le64_to_cpu(hdr->sequence_number);
+ hdr->descriptor_count = le32_to_cpu(hdr->descriptor_count);
leguid_to_cpus(&hdr->log_guid);
- le64_to_cpus(&hdr->flushed_file_offset);
- le64_to_cpus(&hdr->last_file_offset);
+ hdr->flushed_file_offset = le64_to_cpu(hdr->flushed_file_offset);
+ hdr->last_file_offset = le64_to_cpu(hdr->last_file_offset);
}
void vhdx_log_entry_hdr_le_export(VHDXLogEntryHeader *hdr)
{
assert(hdr != NULL);
- cpu_to_le32s(&hdr->signature);
- cpu_to_le32s(&hdr->checksum);
- cpu_to_le32s(&hdr->entry_length);
- cpu_to_le32s(&hdr->tail);
- cpu_to_le64s(&hdr->sequence_number);
- cpu_to_le32s(&hdr->descriptor_count);
+ hdr->signature = cpu_to_le32(hdr->signature);
+ hdr->checksum = cpu_to_le32(hdr->checksum);
+ hdr->entry_length = cpu_to_le32(hdr->entry_length);
+ hdr->tail = cpu_to_le32(hdr->tail);
+ hdr->sequence_number = cpu_to_le64(hdr->sequence_number);
+ hdr->descriptor_count = cpu_to_le32(hdr->descriptor_count);
cpu_to_leguids(&hdr->log_guid);
- cpu_to_le64s(&hdr->flushed_file_offset);
- cpu_to_le64s(&hdr->last_file_offset);
+ hdr->flushed_file_offset = cpu_to_le64(hdr->flushed_file_offset);
+ hdr->last_file_offset = cpu_to_le64(hdr->last_file_offset);
}
@@ -150,18 +150,18 @@ void vhdx_region_header_le_import(VHDXRegionTableHeader *hdr)
{
assert(hdr != NULL);
- le32_to_cpus(&hdr->signature);
- le32_to_cpus(&hdr->checksum);
- le32_to_cpus(&hdr->entry_count);
+ hdr->signature = le32_to_cpu(hdr->signature);
+ hdr->checksum = le32_to_cpu(hdr->checksum);
+ hdr->entry_count = le32_to_cpu(hdr->entry_count);
}
void vhdx_region_header_le_export(VHDXRegionTableHeader *hdr)
{
assert(hdr != NULL);
- cpu_to_le32s(&hdr->signature);
- cpu_to_le32s(&hdr->checksum);
- cpu_to_le32s(&hdr->entry_count);
+ hdr->signature = cpu_to_le32(hdr->signature);
+ hdr->checksum = cpu_to_le32(hdr->checksum);
+ hdr->entry_count = cpu_to_le32(hdr->entry_count);
}
void vhdx_region_entry_le_import(VHDXRegionTableEntry *e)
@@ -169,9 +169,9 @@ void vhdx_region_entry_le_import(VHDXRegionTableEntry *e)
assert(e != NULL);
leguid_to_cpus(&e->guid);
- le64_to_cpus(&e->file_offset);
- le32_to_cpus(&e->length);
- le32_to_cpus(&e->data_bits);
+ e->file_offset = le64_to_cpu(e->file_offset);
+ e->length = le32_to_cpu(e->length);
+ e->data_bits = le32_to_cpu(e->data_bits);
}
void vhdx_region_entry_le_export(VHDXRegionTableEntry *e)
@@ -179,9 +179,9 @@ void vhdx_region_entry_le_export(VHDXRegionTableEntry *e)
assert(e != NULL);
cpu_to_leguids(&e->guid);
- cpu_to_le64s(&e->file_offset);
- cpu_to_le32s(&e->length);
- cpu_to_le32s(&e->data_bits);
+ e->file_offset = cpu_to_le64(e->file_offset);
+ e->length = cpu_to_le32(e->length);
+ e->data_bits = cpu_to_le32(e->data_bits);
}
@@ -190,16 +190,16 @@ void vhdx_metadata_header_le_import(VHDXMetadataTableHeader *hdr)
{
assert(hdr != NULL);
- le64_to_cpus(&hdr->signature);
- le16_to_cpus(&hdr->entry_count);
+ hdr->signature = le64_to_cpu(hdr->signature);
+ hdr->entry_count = le16_to_cpu(hdr->entry_count);
}
void vhdx_metadata_header_le_export(VHDXMetadataTableHeader *hdr)
{
assert(hdr != NULL);
- cpu_to_le64s(&hdr->signature);
- cpu_to_le16s(&hdr->entry_count);
+ hdr->signature = cpu_to_le64(hdr->signature);
+ hdr->entry_count = cpu_to_le16(hdr->entry_count);
}
void vhdx_metadata_entry_le_import(VHDXMetadataTableEntry *e)
@@ -207,16 +207,16 @@ void vhdx_metadata_entry_le_import(VHDXMetadataTableEntry *e)
assert(e != NULL);
leguid_to_cpus(&e->item_id);
- le32_to_cpus(&e->offset);
- le32_to_cpus(&e->length);
- le32_to_cpus(&e->data_bits);
+ e->offset = le32_to_cpu(e->offset);
+ e->length = le32_to_cpu(e->length);
+ e->data_bits = le32_to_cpu(e->data_bits);
}
void vhdx_metadata_entry_le_export(VHDXMetadataTableEntry *e)
{
assert(e != NULL);
cpu_to_leguids(&e->item_id);
- cpu_to_le32s(&e->offset);
- cpu_to_le32s(&e->length);
- cpu_to_le32s(&e->data_bits);
+ e->offset = cpu_to_le32(e->offset);
+ e->length = cpu_to_le32(e->length);
+ e->data_bits = cpu_to_le32(e->data_bits);
}
diff --git a/block/vhdx-log.c b/block/vhdx-log.c
index d2f1b98199..ecd64266c5 100644
--- a/block/vhdx-log.c
+++ b/block/vhdx-log.c
@@ -835,11 +835,11 @@ static void vhdx_log_raw_to_le_sector(VHDXLogDescriptor *desc,
/* 8 + 4084 + 4 = 4096, 1 log sector */
memcpy(&desc->leading_bytes, data, 8);
data += 8;
- cpu_to_le64s(&desc->leading_bytes);
+ desc->leading_bytes = cpu_to_le64(desc->leading_bytes);
memcpy(sector->data, data, 4084);
data += 4084;
memcpy(&desc->trailing_bytes, data, 4);
- cpu_to_le32s(&desc->trailing_bytes);
+ desc->trailing_bytes = cpu_to_le32(desc->trailing_bytes);
data += 4;
sector->sequence_high = (uint32_t) (seq >> 32);
diff --git a/block/vhdx.c b/block/vhdx.c
index 0795ca1985..b785aef4b7 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -156,7 +156,7 @@ uint32_t vhdx_update_checksum(uint8_t *buf, size_t size, int crc_offset)
memset(buf + crc_offset, 0, sizeof(crc));
crc = crc32c(0xffffffff, buf, size);
- cpu_to_le32s(&crc);
+ crc = cpu_to_le32(crc);
memcpy(buf + crc_offset, &crc, sizeof(crc));
return crc;
@@ -753,8 +753,8 @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
goto exit;
}
- le32_to_cpus(&s->params.block_size);
- le32_to_cpus(&s->params.data_bits);
+ s->params.block_size = le32_to_cpu(s->params.block_size);
+ s->params.data_bits = le32_to_cpu(s->params.data_bits);
/* We now have the file parameters, so we can tell if this is a
@@ -803,9 +803,9 @@ static int vhdx_parse_metadata(BlockDriverState *bs, BDRVVHDXState *s)
goto exit;
}
- le64_to_cpus(&s->virtual_disk_size);
- le32_to_cpus(&s->logical_sector_size);
- le32_to_cpus(&s->physical_sector_size);
+ s->virtual_disk_size = le64_to_cpu(s->virtual_disk_size);
+ s->logical_sector_size = le32_to_cpu(s->logical_sector_size);
+ s->physical_sector_size = le32_to_cpu(s->physical_sector_size);
if (s->params.block_size < VHDX_BLOCK_SIZE_MIN ||
s->params.block_size > VHDX_BLOCK_SIZE_MAX) {
@@ -985,7 +985,7 @@ static int vhdx_open(BlockDriverState *bs, QDict *options, int flags,
/* endian convert, and verify populated BAT field file offsets against
* region table and log entries */
for (i = 0; i < s->bat_entries; i++) {
- le64_to_cpus(&s->bat[i]);
+ s->bat[i] = le64_to_cpu(s->bat[i]);
if (payblocks--) {
/* payload bat entries */
if ((s->bat[i] & VHDX_BAT_STATE_BIT_MASK) ==
@@ -1509,7 +1509,7 @@ static int vhdx_create_new_metadata(BlockBackend *blk,
mt_file_params->block_size = cpu_to_le32(block_size);
if (type == VHDX_TYPE_FIXED) {
mt_file_params->data_bits |= VHDX_PARAMS_LEAVE_BLOCKS_ALLOCED;
- cpu_to_le32s(&mt_file_params->data_bits);
+ mt_file_params->data_bits = cpu_to_le32(mt_file_params->data_bits);
}
vhdx_guid_generate(&mt_page83->page_83_data);
@@ -1656,7 +1656,7 @@ static int vhdx_create_bat(BlockBackend *blk, BDRVVHDXState *s,
sinfo.file_offset = ROUND_UP(sinfo.file_offset, MiB);
vhdx_update_bat_table_entry(blk_bs(blk), s, &sinfo, &unused, &unused,
block_state);
- cpu_to_le64s(&s->bat[sinfo.bat_idx]);
+ s->bat[sinfo.bat_idx] = cpu_to_le64(s->bat[sinfo.bat_idx]);
sector_num += s->sectors_per_block;
}
ret = blk_pwrite(blk, file_offset, s->bat, length, 0);
diff --git a/block/vhdx.h b/block/vhdx.h
index 7003ab7a79..3a5f5293ad 100644
--- a/block/vhdx.h
+++ b/block/vhdx.h
@@ -420,16 +420,16 @@ int vhdx_log_write_and_flush(BlockDriverState *bs, BDRVVHDXState *s,
static inline void leguid_to_cpus(MSGUID *guid)
{
- le32_to_cpus(&guid->data1);
- le16_to_cpus(&guid->data2);
- le16_to_cpus(&guid->data3);
+ guid->data1 = le32_to_cpu(guid->data1);
+ guid->data2 = le16_to_cpu(guid->data2);
+ guid->data3 = le16_to_cpu(guid->data3);
}
static inline void cpu_to_leguids(MSGUID *guid)
{
- cpu_to_le32s(&guid->data1);
- cpu_to_le16s(&guid->data2);
- cpu_to_le16s(&guid->data3);
+ guid->data1 = cpu_to_le32(guid->data1);
+ guid->data2 = cpu_to_le16(guid->data2);
+ guid->data3 = cpu_to_le16(guid->data3);
}
void vhdx_header_le_import(VHDXHeader *h);
diff --git a/block/vpc.c b/block/vpc.c
index bf294abfa7..80c5b2b197 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -284,9 +284,11 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
checksum = be32_to_cpu(footer->checksum);
footer->checksum = 0;
- if (vpc_checksum(s->footer_buf, HEADER_SIZE) != checksum)
- fprintf(stderr, "block-vpc: The header checksum of '%s' is "
- "incorrect.\n", bs->filename);
+ if (vpc_checksum(s->footer_buf, HEADER_SIZE) != checksum) {
+ error_setg(errp, "Incorrect header checksum");
+ ret = -EINVAL;
+ goto fail;
+ }
/* Write 'checksum' back to footer, or else will leave it with zero. */
footer->checksum = cpu_to_be32(checksum);
@@ -454,10 +456,12 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags,
}
qemu_co_mutex_init(&s->lock);
+ qemu_opts_del(opts);
return 0;
fail:
+ qemu_opts_del(opts);
qemu_vfree(s->pagetable);
#ifdef CACHE
g_free(s->pageentry_u8);
diff --git a/block/vvfat.c b/block/vvfat.c
index fc41841a5c..b7b61ea8b7 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -100,30 +100,26 @@ static inline void array_free(array_t* array)
/* does not automatically grow */
static inline void* array_get(array_t* array,unsigned int index) {
assert(index < array->next);
+ assert(array->pointer);
return array->pointer + index * array->item_size;
}
-static inline int array_ensure_allocated(array_t* array, int index)
+static inline void array_ensure_allocated(array_t *array, int index)
{
if((index + 1) * array->item_size > array->size) {
int new_size = (index + 32) * array->item_size;
array->pointer = g_realloc(array->pointer, new_size);
- if (!array->pointer)
- return -1;
+ assert(array->pointer);
memset(array->pointer + array->size, 0, new_size - array->size);
array->size = new_size;
array->next = index + 1;
}
-
- return 0;
}
static inline void* array_get_next(array_t* array) {
unsigned int next = array->next;
- if (array_ensure_allocated(array, next) < 0)
- return NULL;
-
+ array_ensure_allocated(array, next);
array->next = next + 1;
return array_get(array, next);
}
@@ -973,10 +969,10 @@ static int init_directories(BDRVVVFATState* s,
mapping = array_get(&(s->mapping), i);
if (mapping->mode & MODE_DIRECTORY) {
+ char *path = mapping->path;
mapping->begin = cluster;
if(read_directory(s, i)) {
- error_setg(errp, "Could not read directory %s",
- mapping->path);
+ error_setg(errp, "Could not read directory %s", path);
return -1;
}
mapping = array_get(&(s->mapping), i);
@@ -1262,15 +1258,9 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
"Unable to set VVFAT to 'rw' when drive is read-only");
goto fail;
}
- } else if (!bdrv_is_read_only(bs)) {
- error_report("Opening non-rw vvfat images without an explicit "
- "read-only=on option is deprecated. Future versions "
- "will refuse to open the image instead of "
- "automatically marking the image read-only.");
- /* read only is the default for safety */
- ret = bdrv_set_read_only(bs, true, &local_err);
+ } else {
+ ret = bdrv_apply_auto_read_only(bs, NULL, errp);
if (ret < 0) {
- error_propagate(errp, local_err);
goto fail;
}
}
@@ -2428,16 +2418,13 @@ static int commit_direntries(BDRVVVFATState* s,
direntry_t* direntry = array_get(&(s->directory), dir_index);
uint32_t first_cluster = dir_index == 0 ? 0 : begin_of_direntry(direntry);
mapping_t* mapping = find_mapping_for_cluster(s, first_cluster);
-
int factor = 0x10 * s->sectors_per_cluster;
int old_cluster_count, new_cluster_count;
- int current_dir_index = mapping->info.dir.first_dir_index;
- int first_dir_index = current_dir_index;
+ int current_dir_index;
+ int first_dir_index;
int ret, i;
uint32_t c;
-DLOG(fprintf(stderr, "commit_direntries for %s, parent_mapping_index %d\n", mapping->path, parent_mapping_index));
-
assert(direntry);
assert(mapping);
assert(mapping->begin == first_cluster);
@@ -2445,6 +2432,11 @@ DLOG(fprintf(stderr, "commit_direntries for %s, parent_mapping_index %d\n", mapp
assert(mapping->mode & MODE_DIRECTORY);
assert(dir_index == 0 || is_directory(direntry));
+ DLOG(fprintf(stderr, "commit_direntries for %s, parent_mapping_index %d\n",
+ mapping->path, parent_mapping_index));
+
+ current_dir_index = mapping->info.dir.first_dir_index;
+ first_dir_index = current_dir_index;
mapping->info.dir.parent_mapping_index = parent_mapping_index;
if (first_cluster == 0) {
@@ -2494,6 +2486,9 @@ DLOG(fprintf(stderr, "commit_direntries for %s, parent_mapping_index %d\n", mapp
direntry = array_get(&(s->directory), first_dir_index + i);
if (is_directory(direntry) && !is_dot(direntry)) {
mapping = find_mapping_for_cluster(s, first_cluster);
+ if (mapping == NULL) {
+ return -1;
+ }
assert(mapping->mode & MODE_DIRECTORY);
ret = commit_direntries(s, first_dir_index + i,
array_index(&(s->mapping), mapping));
@@ -2515,13 +2510,17 @@ static int commit_one_file(BDRVVVFATState* s,
uint32_t first_cluster = c;
mapping_t* mapping = find_mapping_for_cluster(s, c);
uint32_t size = filesize_of_direntry(direntry);
- char* cluster = g_malloc(s->cluster_size);
+ char *cluster;
uint32_t i;
int fd = 0;
assert(offset < size);
assert((offset % s->cluster_size) == 0);
+ if (mapping == NULL) {
+ return -1;
+ }
+
for (i = s->cluster_size; i < offset; i += s->cluster_size)
c = modified_fat_get(s, c);
@@ -2529,17 +2528,17 @@ static int commit_one_file(BDRVVVFATState* s,
if (fd < 0) {
fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path,
strerror(errno), errno);
- g_free(cluster);
return fd;
}
if (offset > 0) {
if (lseek(fd, offset, SEEK_SET) != offset) {
qemu_close(fd);
- g_free(cluster);
return -3;
}
}
+ cluster = g_malloc(s->cluster_size);
+
while (offset < size) {
uint32_t c1;
int rest_size = (size - offset > s->cluster_size ?
@@ -2668,8 +2667,12 @@ static int handle_renames_and_mkdirs(BDRVVVFATState* s)
if (commit->action == ACTION_RENAME) {
mapping_t* mapping = find_mapping_for_cluster(s,
commit->param.rename.cluster);
- char* old_path = mapping->path;
+ char *old_path;
+ if (mapping == NULL) {
+ return -1;
+ }
+ old_path = mapping->path;
assert(commit->path);
mapping->path = commit->path;
if (rename(old_path, mapping->path))
@@ -2690,10 +2693,15 @@ static int handle_renames_and_mkdirs(BDRVVVFATState* s)
direntry_t* d = direntry + i;
if (is_file(d) || (is_directory(d) && !is_dot(d))) {
+ int l;
+ char *new_path;
mapping_t* m = find_mapping_for_cluster(s,
begin_of_direntry(d));
- int l = strlen(m->path);
- char* new_path = g_malloc(l + diff + 1);
+ if (m == NULL) {
+ return -1;
+ }
+ l = strlen(m->path);
+ new_path = g_malloc(l + diff + 1);
assert(!strncmp(m->path, mapping->path, l2));
@@ -3130,6 +3138,7 @@ static void vvfat_qcow_options(int *child_flags, QDict *child_options,
int parent_flags, QDict *parent_options)
{
qdict_set_default_str(child_options, BDRV_OPT_READ_ONLY, "off");
+ qdict_set_default_str(child_options, BDRV_OPT_AUTO_READ_ONLY, "off");
qdict_set_default_str(child_options, BDRV_OPT_CACHE_NO_FLUSH, "on");
}
diff --git a/blockdev.c b/blockdev.c
index a8755bd908..81f95d920b 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -590,6 +590,7 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts,
qdict_set_default_str(bs_opts, BDRV_OPT_CACHE_NO_FLUSH, "off");
qdict_set_default_str(bs_opts, BDRV_OPT_READ_ONLY,
read_only ? "on" : "off");
+ qdict_set_default_str(bs_opts, BDRV_OPT_AUTO_READ_ONLY, "on");
assert((bdrv_flags & BDRV_O_CACHE_MASK) == 0);
if (runstate_check(RUN_STATE_INMIGRATE)) {
@@ -759,7 +760,8 @@ QemuOptsList qemu_legacy_drive_opts = {
},
};
-DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
+DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type,
+ Error **errp)
{
const char *value;
BlockBackend *blk;
@@ -808,7 +810,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
qemu_opt_rename(all_opts, opt_renames[i].from, opt_renames[i].to,
&local_err);
if (local_err) {
- error_report_err(local_err);
+ error_propagate(errp, local_err);
return NULL;
}
}
@@ -819,7 +821,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
bool writethrough;
if (bdrv_parse_cache_mode(value, &flags, &writethrough) != 0) {
- error_report("invalid cache option");
+ error_setg(errp, "invalid cache option");
return NULL;
}
@@ -847,7 +849,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
&error_abort);
qemu_opts_absorb_qdict(legacy_opts, bs_opts, &local_err);
if (local_err) {
- error_report_err(local_err);
+ error_propagate(errp, local_err);
goto fail;
}
@@ -860,7 +862,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
media = MEDIA_CDROM;
read_only = true;
} else {
- error_report("'%s' invalid media", value);
+ error_setg(errp, "'%s' invalid media", value);
goto fail;
}
}
@@ -885,7 +887,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
type++) {
}
if (type == IF_COUNT) {
- error_report("unsupported bus type '%s'", value);
+ error_setg(errp, "unsupported bus type '%s'", value);
goto fail;
}
} else {
@@ -902,7 +904,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
if (index != -1) {
if (bus_id != 0 || unit_id != -1) {
- error_report("index cannot be used with bus and unit");
+ error_setg(errp, "index cannot be used with bus and unit");
goto fail;
}
bus_id = drive_index_to_bus_id(type, index);
@@ -921,13 +923,13 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
}
if (max_devs && unit_id >= max_devs) {
- error_report("unit %d too big (max is %d)", unit_id, max_devs - 1);
+ error_setg(errp, "unit %d too big (max is %d)", unit_id, max_devs - 1);
goto fail;
}
if (drive_get(type, bus_id, unit_id) != NULL) {
- error_report("drive with bus=%d, unit=%d (index=%d) exists",
- bus_id, unit_id, index);
+ error_setg(errp, "drive with bus=%d, unit=%d (index=%d) exists",
+ bus_id, unit_id, index);
goto fail;
}
@@ -970,7 +972,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
if (werror != NULL) {
if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO &&
type != IF_NONE) {
- error_report("werror is not supported by this bus type");
+ error_setg(errp, "werror is not supported by this bus type");
goto fail;
}
qdict_put_str(bs_opts, "werror", werror);
@@ -980,7 +982,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
if (rerror != NULL) {
if (type != IF_IDE && type != IF_VIRTIO && type != IF_SCSI &&
type != IF_NONE) {
- error_report("rerror is not supported by this bus type");
+ error_setg(errp, "rerror is not supported by this bus type");
goto fail;
}
qdict_put_str(bs_opts, "rerror", rerror);
@@ -991,7 +993,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
bs_opts = NULL;
if (!blk) {
if (local_err) {
- error_report_err(local_err);
+ error_propagate(errp, local_err);
}
goto fail;
} else {
@@ -1638,7 +1640,7 @@ static void external_snapshot_prepare(BlkActionState *common,
}
options = qdict_new();
- if (s->has_snapshot_node_name) {
+ if (snapshot_node_name) {
qdict_put_str(options, "node-name", snapshot_node_name);
}
qdict_put_str(options, "driver", format);
@@ -2009,14 +2011,8 @@ static void block_dirty_bitmap_clear_prepare(BlkActionState *common,
return;
}
- if (bdrv_dirty_bitmap_frozen(state->bitmap)) {
- error_setg(errp, "Cannot modify a frozen bitmap");
- return;
- } else if (bdrv_dirty_bitmap_qmp_locked(state->bitmap)) {
- error_setg(errp, "Cannot modify a locked bitmap");
- return;
- } else if (!bdrv_dirty_bitmap_enabled(state->bitmap)) {
- error_setg(errp, "Cannot clear a disabled bitmap");
+ if (bdrv_dirty_bitmap_user_locked(state->bitmap)) {
+ error_setg(errp, "Cannot modify a bitmap in use by another operation");
return;
} else if (bdrv_dirty_bitmap_readonly(state->bitmap)) {
error_setg(errp, "Cannot clear a readonly bitmap");
@@ -2026,17 +2022,17 @@ static void block_dirty_bitmap_clear_prepare(BlkActionState *common,
bdrv_clear_dirty_bitmap(state->bitmap, &state->backup);
}
-static void block_dirty_bitmap_clear_abort(BlkActionState *common)
+static void block_dirty_bitmap_restore(BlkActionState *common)
{
BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
common, common);
if (state->backup) {
- bdrv_undo_clear_dirty_bitmap(state->bitmap, state->backup);
+ bdrv_restore_dirty_bitmap(state->bitmap, state->backup);
}
}
-static void block_dirty_bitmap_clear_commit(BlkActionState *common)
+static void block_dirty_bitmap_free_backup(BlkActionState *common)
{
BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
common, common);
@@ -2064,6 +2060,13 @@ static void block_dirty_bitmap_enable_prepare(BlkActionState *common,
return;
}
+ if (bdrv_dirty_bitmap_user_locked(state->bitmap)) {
+ error_setg(errp,
+ "Bitmap '%s' is currently in use by another operation"
+ " and cannot be enabled", action->name);
+ return;
+ }
+
state->was_enabled = bdrv_dirty_bitmap_enabled(state->bitmap);
bdrv_enable_dirty_bitmap(state->bitmap);
}
@@ -2098,6 +2101,13 @@ static void block_dirty_bitmap_disable_prepare(BlkActionState *common,
return;
}
+ if (bdrv_dirty_bitmap_user_locked(state->bitmap)) {
+ error_setg(errp,
+ "Bitmap '%s' is currently in use by another operation"
+ " and cannot be disabled", action->name);
+ return;
+ }
+
state->was_enabled = bdrv_dirty_bitmap_enabled(state->bitmap);
bdrv_disable_dirty_bitmap(state->bitmap);
}
@@ -2112,6 +2122,35 @@ static void block_dirty_bitmap_disable_abort(BlkActionState *common)
}
}
+static void block_dirty_bitmap_merge_prepare(BlkActionState *common,
+ Error **errp)
+{
+ BlockDirtyBitmapMerge *action;
+ BlockDirtyBitmapState *state = DO_UPCAST(BlockDirtyBitmapState,
+ common, common);
+ BdrvDirtyBitmap *merge_source;
+
+ if (action_check_completion_mode(common, errp) < 0) {
+ return;
+ }
+
+ action = common->action->u.x_block_dirty_bitmap_merge.data;
+ state->bitmap = block_dirty_bitmap_lookup(action->node,
+ action->dst_name,
+ &state->bs,
+ errp);
+ if (!state->bitmap) {
+ return;
+ }
+
+ merge_source = bdrv_find_dirty_bitmap(state->bs, action->src_name);
+ if (!merge_source) {
+ return;
+ }
+
+ bdrv_merge_dirty_bitmap(state->bitmap, merge_source, &state->backup, errp);
+}
+
static void abort_prepare(BlkActionState *common, Error **errp)
{
error_setg(errp, "Transaction aborted using Abort action");
@@ -2170,8 +2209,8 @@ static const BlkActionOps actions[] = {
[TRANSACTION_ACTION_KIND_BLOCK_DIRTY_BITMAP_CLEAR] = {
.instance_size = sizeof(BlockDirtyBitmapState),
.prepare = block_dirty_bitmap_clear_prepare,
- .commit = block_dirty_bitmap_clear_commit,
- .abort = block_dirty_bitmap_clear_abort,
+ .commit = block_dirty_bitmap_free_backup,
+ .abort = block_dirty_bitmap_restore,
},
[TRANSACTION_ACTION_KIND_X_BLOCK_DIRTY_BITMAP_ENABLE] = {
.instance_size = sizeof(BlockDirtyBitmapState),
@@ -2183,6 +2222,12 @@ static const BlkActionOps actions[] = {
.prepare = block_dirty_bitmap_disable_prepare,
.abort = block_dirty_bitmap_disable_abort,
},
+ [TRANSACTION_ACTION_KIND_X_BLOCK_DIRTY_BITMAP_MERGE] = {
+ .instance_size = sizeof(BlockDirtyBitmapState),
+ .prepare = block_dirty_bitmap_merge_prepare,
+ .commit = block_dirty_bitmap_free_backup,
+ .abort = block_dirty_bitmap_restore,
+ },
/* Where are transactions for MIRROR, COMMIT and STREAM?
* Although these blockjobs use transaction callbacks like the backup job,
* these jobs do not necessarily adhere to transaction semantics.
@@ -2607,7 +2652,7 @@ void qmp_blockdev_change_medium(bool has_device, const char *device,
bdrv_flags = blk_get_open_flags_from_root_state(blk);
bdrv_flags &= ~(BDRV_O_TEMPORARY | BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING |
- BDRV_O_PROTOCOL);
+ BDRV_O_PROTOCOL | BDRV_O_AUTO_RDONLY);
if (!has_read_only) {
read_only = BLOCKDEV_CHANGE_READ_ONLY_MODE_RETAIN;
@@ -2847,15 +2892,10 @@ void qmp_block_dirty_bitmap_remove(const char *node, const char *name,
return;
}
- if (bdrv_dirty_bitmap_frozen(bitmap)) {
+ if (bdrv_dirty_bitmap_user_locked(bitmap)) {
error_setg(errp,
- "Bitmap '%s' is currently frozen and cannot be removed",
- name);
- return;
- } else if (bdrv_dirty_bitmap_qmp_locked(bitmap)) {
- error_setg(errp,
- "Bitmap '%s' is currently locked and cannot be removed",
- name);
+ "Bitmap '%s' is currently in use by another operation and"
+ " cannot be removed", name);
return;
}
@@ -2885,20 +2925,10 @@ void qmp_block_dirty_bitmap_clear(const char *node, const char *name,
return;
}
- if (bdrv_dirty_bitmap_frozen(bitmap)) {
- error_setg(errp,
- "Bitmap '%s' is currently frozen and cannot be modified",
- name);
- return;
- } else if (bdrv_dirty_bitmap_qmp_locked(bitmap)) {
- error_setg(errp,
- "Bitmap '%s' is currently locked and cannot be modified",
- name);
- return;
- } else if (!bdrv_dirty_bitmap_enabled(bitmap)) {
+ if (bdrv_dirty_bitmap_user_locked(bitmap)) {
error_setg(errp,
- "Bitmap '%s' is currently disabled and cannot be cleared",
- name);
+ "Bitmap '%s' is currently in use by another operation"
+ " and cannot be cleared", name);
return;
} else if (bdrv_dirty_bitmap_readonly(bitmap)) {
error_setg(errp, "Bitmap '%s' is readonly and cannot be cleared", name);
@@ -2919,10 +2949,10 @@ void qmp_x_block_dirty_bitmap_enable(const char *node, const char *name,
return;
}
- if (bdrv_dirty_bitmap_frozen(bitmap)) {
+ if (bdrv_dirty_bitmap_user_locked(bitmap)) {
error_setg(errp,
- "Bitmap '%s' is currently frozen and cannot be enabled",
- name);
+ "Bitmap '%s' is currently in use by another operation"
+ " and cannot be enabled", name);
return;
}
@@ -2940,10 +2970,10 @@ void qmp_x_block_dirty_bitmap_disable(const char *node, const char *name,
return;
}
- if (bdrv_dirty_bitmap_frozen(bitmap)) {
+ if (bdrv_dirty_bitmap_user_locked(bitmap)) {
error_setg(errp,
- "Bitmap '%s' is currently frozen and cannot be disabled",
- name);
+ "Bitmap '%s' is currently in use by another operation"
+ " and cannot be disabled", name);
return;
}
@@ -2961,23 +2991,13 @@ void qmp_x_block_dirty_bitmap_merge(const char *node, const char *dst_name,
return;
}
- if (bdrv_dirty_bitmap_frozen(dst)) {
- error_setg(errp, "Bitmap '%s' is frozen and cannot be modified",
- dst_name);
- return;
- } else if (bdrv_dirty_bitmap_readonly(dst)) {
- error_setg(errp, "Bitmap '%s' is readonly and cannot be modified",
- dst_name);
- return;
- }
-
src = bdrv_find_dirty_bitmap(bs, src_name);
if (!src) {
error_setg(errp, "Dirty bitmap '%s' not found", src_name);
return;
}
- bdrv_merge_dirty_bitmap(dst, src, errp);
+ bdrv_merge_dirty_bitmap(dst, src, NULL, errp);
}
BlockDirtyBitmapSha256 *qmp_x_debug_block_dirty_bitmap_sha256(const char *node,
@@ -3494,10 +3514,10 @@ static BlockJob *do_drive_backup(DriveBackup *backup, JobTxn *txn,
bdrv_unref(target_bs);
goto out;
}
- if (bdrv_dirty_bitmap_qmp_locked(bmap)) {
+ if (bdrv_dirty_bitmap_user_locked(bmap)) {
error_setg(errp,
- "Bitmap '%s' is currently locked and cannot be used for "
- "backup", backup->bitmap);
+ "Bitmap '%s' is currently in use by another operation"
+ " and cannot be used for backup", backup->bitmap);
goto out;
}
}
@@ -3544,6 +3564,7 @@ BlockJob *do_blockdev_backup(BlockdevBackup *backup, JobTxn *txn,
BlockDriverState *bs;
BlockDriverState *target_bs;
Error *local_err = NULL;
+ BdrvDirtyBitmap *bmap = NULL;
AioContext *aio_context;
BlockJob *job = NULL;
int job_flags = JOB_DEFAULT;
@@ -3594,6 +3615,21 @@ BlockJob *do_blockdev_backup(BlockdevBackup *backup, JobTxn *txn,
goto out;
}
}
+
+ if (backup->has_bitmap) {
+ bmap = bdrv_find_dirty_bitmap(bs, backup->bitmap);
+ if (!bmap) {
+ error_setg(errp, "Bitmap '%s' could not be found", backup->bitmap);
+ goto out;
+ }
+ if (bdrv_dirty_bitmap_user_locked(bmap)) {
+ error_setg(errp,
+ "Bitmap '%s' is currently in use by another operation"
+ " and cannot be used for backup", backup->bitmap);
+ goto out;
+ }
+ }
+
if (!backup->auto_finalize) {
job_flags |= JOB_MANUAL_FINALIZE;
}
@@ -3601,7 +3637,7 @@ BlockJob *do_blockdev_backup(BlockdevBackup *backup, JobTxn *txn,
job_flags |= JOB_MANUAL_DISMISS;
}
job = backup_job_create(backup->job_id, bs, target_bs, backup->speed,
- backup->sync, NULL, backup->compress,
+ backup->sync, bmap, backup->compress,
backup->on_source_error, backup->on_target_error,
job_flags, NULL, NULL, txn, &local_err);
if (local_err != NULL) {
@@ -4377,6 +4413,7 @@ void qmp_x_block_latency_histogram_set(
{
BlockBackend *blk = blk_by_name(device);
BlockAcctStats *stats;
+ int ret;
if (!blk) {
error_setg(errp, "Device '%s' not found", device);
@@ -4392,21 +4429,33 @@ void qmp_x_block_latency_histogram_set(
}
if (has_boundaries || has_boundaries_read) {
- block_latency_histogram_set(
+ ret = block_latency_histogram_set(
stats, BLOCK_ACCT_READ,
has_boundaries_read ? boundaries_read : boundaries);
+ if (ret) {
+ error_setg(errp, "Device '%s' set read boundaries fail", device);
+ return;
+ }
}
if (has_boundaries || has_boundaries_write) {
- block_latency_histogram_set(
+ ret = block_latency_histogram_set(
stats, BLOCK_ACCT_WRITE,
has_boundaries_write ? boundaries_write : boundaries);
+ if (ret) {
+ error_setg(errp, "Device '%s' set write boundaries fail", device);
+ return;
+ }
}
if (has_boundaries || has_boundaries_flush) {
- block_latency_histogram_set(
+ ret = block_latency_histogram_set(
stats, BLOCK_ACCT_FLUSH,
has_boundaries_flush ? boundaries_flush : boundaries);
+ if (ret) {
+ error_setg(errp, "Device '%s' set flush boundaries fail", device);
+ return;
+ }
}
}
diff --git a/chardev/char-pty.c b/chardev/char-pty.c
index e8d9a53476..f681d637c1 100644
--- a/chardev/char-pty.c
+++ b/chardev/char-pty.c
@@ -259,7 +259,7 @@ static void char_pty_open(Chardev *chr,
qemu_set_nonblock(master_fd);
chr->filename = g_strdup_printf("pty:%s", pty_name);
- error_report("char device redirected to %s (label %s)",
+ error_printf("char device redirected to %s (label %s)\n",
pty_name, chr->label);
s = PTY_CHARDEV(chr);
diff --git a/chardev/char-socket.c b/chardev/char-socket.c
index a75b46d9fe..eaa8e8b68f 100644
--- a/chardev/char-socket.c
+++ b/chardev/char-socket.c
@@ -26,6 +26,7 @@
#include "chardev/char.h"
#include "io/channel-socket.h"
#include "io/channel-tls.h"
+#include "io/channel-websock.h"
#include "io/net-listener.h"
#include "qemu/error-report.h"
#include "qemu/option.h"
@@ -68,6 +69,8 @@ typedef struct {
GSource *telnet_source;
TCPChardevTelnetInit *telnet_init;
+ bool is_websock;
+
GSource *reconnect_timer;
int64_t reconnect_time;
bool connect_err_reported;
@@ -389,30 +392,37 @@ static void tcp_chr_free_connection(Chardev *chr)
s->connected = 0;
}
-static char *SocketAddress_to_str(const char *prefix, SocketAddress *addr,
- bool is_listen, bool is_telnet)
+static const char *qemu_chr_socket_protocol(SocketChardev *s)
+{
+ if (s->is_telnet) {
+ return "telnet";
+ }
+ return s->is_websock ? "websocket" : "tcp";
+}
+
+static char *qemu_chr_socket_address(SocketChardev *s, const char *prefix)
{
- switch (addr->type) {
+ switch (s->addr->type) {
case SOCKET_ADDRESS_TYPE_INET:
return g_strdup_printf("%s%s:%s:%s%s", prefix,
- is_telnet ? "telnet" : "tcp",
- addr->u.inet.host,
- addr->u.inet.port,
- is_listen ? ",server" : "");
+ qemu_chr_socket_protocol(s),
+ s->addr->u.inet.host,
+ s->addr->u.inet.port,
+ s->is_listen ? ",server" : "");
break;
case SOCKET_ADDRESS_TYPE_UNIX:
return g_strdup_printf("%sunix:%s%s", prefix,
- addr->u.q_unix.path,
- is_listen ? ",server" : "");
+ s->addr->u.q_unix.path,
+ s->is_listen ? ",server" : "");
break;
case SOCKET_ADDRESS_TYPE_FD:
- return g_strdup_printf("%sfd:%s%s", prefix, addr->u.fd.str,
- is_listen ? ",server" : "");
+ return g_strdup_printf("%sfd:%s%s", prefix, s->addr->u.fd.str,
+ s->is_listen ? ",server" : "");
break;
case SOCKET_ADDRESS_TYPE_VSOCK:
return g_strdup_printf("%svsock:%s:%s", prefix,
- addr->u.vsock.cid,
- addr->u.vsock.port);
+ s->addr->u.vsock.cid,
+ s->addr->u.vsock.port);
default:
abort();
}
@@ -424,8 +434,7 @@ static void update_disconnected_filename(SocketChardev *s)
g_free(chr->filename);
if (s->addr) {
- chr->filename = SocketAddress_to_str("disconnected:", s->addr,
- s->is_listen, s->is_telnet);
+ chr->filename = qemu_chr_socket_address(s, "disconnected:");
} else {
chr->filename = g_strdup("disconnected:socket");
}
@@ -514,10 +523,12 @@ static int tcp_chr_sync_read(Chardev *chr, const uint8_t *buf, int len)
return size;
}
-static char *sockaddr_to_str(struct sockaddr_storage *ss, socklen_t ss_len,
- struct sockaddr_storage *ps, socklen_t ps_len,
- bool is_listen, bool is_telnet)
+static char *qemu_chr_compute_filename(SocketChardev *s)
{
+ struct sockaddr_storage *ss = &s->sioc->localAddr;
+ struct sockaddr_storage *ps = &s->sioc->remoteAddr;
+ socklen_t ss_len = s->sioc->localAddrLen;
+ socklen_t ps_len = s->sioc->remoteAddrLen;
char shost[NI_MAXHOST], sserv[NI_MAXSERV];
char phost[NI_MAXHOST], pserv[NI_MAXSERV];
const char *left = "", *right = "";
@@ -527,7 +538,7 @@ static char *sockaddr_to_str(struct sockaddr_storage *ss, socklen_t ss_len,
case AF_UNIX:
return g_strdup_printf("unix:%s%s",
((struct sockaddr_un *)(ss))->sun_path,
- is_listen ? ",server" : "");
+ s->is_listen ? ",server" : "");
#endif
case AF_INET6:
left = "[";
@@ -539,9 +550,9 @@ static char *sockaddr_to_str(struct sockaddr_storage *ss, socklen_t ss_len,
getnameinfo((struct sockaddr *) ps, ps_len, phost, sizeof(phost),
pserv, sizeof(pserv), NI_NUMERICHOST | NI_NUMERICSERV);
return g_strdup_printf("%s:%s%s%s:%s%s <-> %s%s%s:%s",
- is_telnet ? "telnet" : "tcp",
+ qemu_chr_socket_protocol(s),
left, shost, right, sserv,
- is_listen ? ",server" : "",
+ s->is_listen ? ",server" : "",
left, phost, right, pserv);
default:
@@ -576,10 +587,7 @@ static void tcp_chr_connect(void *opaque)
SocketChardev *s = SOCKET_CHARDEV(opaque);
g_free(chr->filename);
- chr->filename = sockaddr_to_str(
- &s->sioc->localAddr, s->sioc->localAddrLen,
- &s->sioc->remoteAddr, s->sioc->remoteAddrLen,
- s->is_listen, s->is_telnet);
+ chr->filename = qemu_chr_compute_filename(s);
s->connected = 1;
update_ioc_handlers(s);
@@ -709,6 +717,41 @@ cont:
}
+static void tcp_chr_websock_handshake(QIOTask *task, gpointer user_data)
+{
+ Chardev *chr = user_data;
+ SocketChardev *s = user_data;
+
+ if (qio_task_propagate_error(task, NULL)) {
+ tcp_chr_disconnect(chr);
+ } else {
+ if (s->do_telnetopt) {
+ tcp_chr_telnet_init(chr);
+ } else {
+ tcp_chr_connect(chr);
+ }
+ }
+}
+
+
+static void tcp_chr_websock_init(Chardev *chr)
+{
+ SocketChardev *s = SOCKET_CHARDEV(chr);
+ QIOChannelWebsock *wioc = NULL;
+ gchar *name;
+
+ wioc = qio_channel_websock_new_server(s->ioc);
+
+ name = g_strdup_printf("chardev-websocket-server-%s", chr->label);
+ qio_channel_set_name(QIO_CHANNEL(wioc), name);
+ g_free(name);
+ object_unref(OBJECT(s->ioc));
+ s->ioc = QIO_CHANNEL(wioc);
+
+ qio_channel_websock_handshake(wioc, tcp_chr_websock_handshake, chr, NULL);
+}
+
+
static void tcp_chr_tls_handshake(QIOTask *task,
gpointer user_data)
{
@@ -718,7 +761,9 @@ static void tcp_chr_tls_handshake(QIOTask *task,
if (qio_task_propagate_error(task, NULL)) {
tcp_chr_disconnect(chr);
} else {
- if (s->do_telnetopt) {
+ if (s->is_websock) {
+ tcp_chr_websock_init(chr);
+ } else if (s->do_telnetopt) {
tcp_chr_telnet_init(chr);
} else {
tcp_chr_connect(chr);
@@ -804,12 +849,12 @@ static int tcp_chr_new_client(Chardev *chr, QIOChannelSocket *sioc)
if (s->tls_creds) {
tcp_chr_tls_init(chr);
+ } else if (s->is_websock) {
+ tcp_chr_websock_init(chr);
+ } else if (s->do_telnetopt) {
+ tcp_chr_telnet_init(chr);
} else {
- if (s->do_telnetopt) {
- tcp_chr_telnet_init(chr);
- } else {
- tcp_chr_connect(chr);
- }
+ tcp_chr_connect(chr);
}
return 0;
@@ -954,13 +999,20 @@ static void qmp_chardev_open_socket(Chardev *chr,
bool is_telnet = sock->has_telnet ? sock->telnet : false;
bool is_tn3270 = sock->has_tn3270 ? sock->tn3270 : false;
bool is_waitconnect = sock->has_wait ? sock->wait : false;
+ bool is_websock = sock->has_websocket ? sock->websocket : false;
int64_t reconnect = sock->has_reconnect ? sock->reconnect : 0;
QIOChannelSocket *sioc = NULL;
SocketAddress *addr;
+ if (!is_listen && is_websock) {
+ error_setg(errp, "%s", "Websocket client is not implemented");
+ goto error;
+ }
+
s->is_listen = is_listen;
s->is_telnet = is_telnet;
s->is_tn3270 = is_tn3270;
+ s->is_websock = is_websock;
s->do_nodelay = do_nodelay;
if (sock->tls_creds) {
Object *creds;
@@ -997,6 +1049,10 @@ static void qmp_chardev_open_socket(Chardev *chr,
s->addr = addr = socket_address_flatten(sock->addr);
+ if (sock->has_reconnect && addr->type == SOCKET_ADDRESS_TYPE_FD) {
+ error_setg(errp, "'reconnect' option is incompatible with 'fd'");
+ goto error;
+ }
qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_RECONNECTABLE);
/* TODO SOCKET_ADDRESS_FD where fd has AF_UNIX */
if (addr->type == SOCKET_ADDRESS_TYPE_UNIX) {
@@ -1067,6 +1123,7 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
bool is_waitconnect = is_listen && qemu_opt_get_bool(opts, "wait", true);
bool is_telnet = qemu_opt_get_bool(opts, "telnet", false);
bool is_tn3270 = qemu_opt_get_bool(opts, "tn3270", false);
+ bool is_websock = qemu_opt_get_bool(opts, "websocket", false);
bool do_nodelay = !qemu_opt_get_bool(opts, "delay", true);
int64_t reconnect = qemu_opt_get_number(opts, "reconnect", 0);
const char *path = qemu_opt_get(opts, "path");
@@ -1115,9 +1172,11 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
sock->telnet = is_telnet;
sock->has_tn3270 = true;
sock->tn3270 = is_tn3270;
+ sock->has_websocket = true;
+ sock->websocket = is_websock;
sock->has_wait = true;
sock->wait = is_waitconnect;
- sock->has_reconnect = true;
+ sock->has_reconnect = qemu_opt_find(opts, "reconnect");
sock->reconnect = reconnect;
sock->tls_creds = g_strdup(tls_creds);
diff --git a/chardev/char.c b/chardev/char.c
index e115166995..152dde5327 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -409,7 +409,8 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename,
}
if (strstart(filename, "tcp:", &p) ||
strstart(filename, "telnet:", &p) ||
- strstart(filename, "tn3270:", &p)) {
+ strstart(filename, "tn3270:", &p) ||
+ strstart(filename, "websocket:", &p)) {
if (sscanf(p, "%64[^:]:%32[^,]%n", host, port, &pos) < 2) {
host[0] = 0;
if (sscanf(p, ":%32[^,]%n", port, &pos) < 1)
@@ -429,6 +430,8 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename,
qemu_opt_set(opts, "telnet", "on", &error_abort);
} else if (strstart(filename, "tn3270:", &p)) {
qemu_opt_set(opts, "tn3270", "on", &error_abort);
+ } else if (strstart(filename, "websocket:", &p)) {
+ qemu_opt_set(opts, "websocket", "on", &error_abort);
}
return opts;
}
@@ -569,7 +572,7 @@ help_string_append(const char *name, void *opaque)
{
GString *str = opaque;
- g_string_append_printf(str, "\n%s", name);
+ g_string_append_printf(str, "\n %s", name);
}
static const char *chardev_alias_translate(const char *name)
@@ -634,7 +637,7 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts, Error **errp)
chardev_name_foreach(help_string_append, str);
- error_report("Available chardev backend types: %s", str->str);
+ error_printf("Available chardev backend types: %s\n", str->str);
g_string_free(str, true);
return NULL;
}
@@ -861,6 +864,9 @@ QemuOptsList qemu_chardev_opts = {
.name = "tls-creds",
.type = QEMU_OPT_STRING,
},{
+ .name = "websocket",
+ .type = QEMU_OPT_BOOL,
+ },{
.name = "width",
.type = QEMU_OPT_NUMBER,
},{
diff --git a/configure b/configure
index 9138af37f8..0a3c6a72c3 100755
--- a/configure
+++ b/configure
@@ -428,7 +428,7 @@ usb_redir=""
opengl=""
opengl_dmabuf="no"
cpuid_h="no"
-avx2_opt="no"
+avx2_opt=""
zlib="yes"
capstone=""
lzo=""
@@ -457,12 +457,9 @@ gtk=""
gtk_gl="no"
tls_priority="NORMAL"
gnutls=""
-gnutls_rnd=""
nettle=""
-nettle_kdf="no"
gcrypt=""
gcrypt_hmac="no"
-gcrypt_kdf="no"
vte=""
virglrenderer=""
tpm="yes"
@@ -473,10 +470,20 @@ tcmalloc="no"
jemalloc="no"
replication="yes"
vxhs=""
+bochs="yes"
+cloop="yes"
+dmg="yes"
+qcow1="yes"
+vdi="yes"
+vvfat="yes"
+qed="yes"
+parallels="yes"
+sheepdog="yes"
libxml2=""
docker="no"
debug_mutex="no"
libpmem=""
+libudev="no"
# cross compilers defaults, can be overridden with --cross-cc-ARCH
cross_cc_aarch64="aarch64-linux-gnu-gcc"
@@ -871,8 +878,9 @@ Linux)
vhost_crypto="yes"
vhost_scsi="yes"
vhost_vsock="yes"
- QEMU_INCLUDES="-I\$(SRC_PATH)/linux-headers -I$(pwd)/linux-headers $QEMU_INCLUDES"
+ QEMU_INCLUDES="-I\$(SRC_PATH)/linux-headers -I$PWD/linux-headers $QEMU_INCLUDES"
supported_os="yes"
+ libudev="yes"
;;
esac
@@ -1332,6 +1340,10 @@ for opt do
;;
--disable-glusterfs) glusterfs="no"
;;
+ --disable-avx2) avx2_opt="no"
+ ;;
+ --enable-avx2) avx2_opt="yes"
+ ;;
--enable-glusterfs) glusterfs="yes"
;;
--disable-virtio-blk-data-plane|--enable-virtio-blk-data-plane)
@@ -1413,6 +1425,42 @@ for opt do
;;
--enable-vxhs) vxhs="yes"
;;
+ --disable-bochs) bochs="no"
+ ;;
+ --enable-bochs) bochs="yes"
+ ;;
+ --disable-cloop) cloop="no"
+ ;;
+ --enable-cloop) cloop="yes"
+ ;;
+ --disable-dmg) dmg="no"
+ ;;
+ --enable-dmg) dmg="yes"
+ ;;
+ --disable-qcow1) qcow1="no"
+ ;;
+ --enable-qcow1) qcow1="yes"
+ ;;
+ --disable-vdi) vdi="no"
+ ;;
+ --enable-vdi) vdi="yes"
+ ;;
+ --disable-vvfat) vvfat="no"
+ ;;
+ --enable-vvfat) vvfat="yes"
+ ;;
+ --disable-qed) qed="no"
+ ;;
+ --enable-qed) qed="yes"
+ ;;
+ --disable-parallels) parallels="no"
+ ;;
+ --enable-parallels) parallels="yes"
+ ;;
+ --disable-sheepdog) sheepdog="no"
+ ;;
+ --enable-sheepdog) sheepdog="yes"
+ ;;
--disable-vhost-user) vhost_user="no"
;;
--enable-vhost-user)
@@ -1706,6 +1754,7 @@ disabled with --disable-FEATURE, default is enabled if available:
libxml2 for Parallels image format
tcmalloc tcmalloc support
jemalloc jemalloc support
+ avx2 AVX2 optimization support
replication replication support
vhost-vsock virtio sockets device support
opengl opengl support
@@ -1714,6 +1763,15 @@ disabled with --disable-FEATURE, default is enabled if available:
qom-cast-debug cast debugging support
tools build qemu-io, qemu-nbd and qemu-image tools
vxhs Veritas HyperScale vDisk backend support
+ bochs bochs image format support
+ cloop cloop image format support
+ dmg dmg image format support
+ qcow1 qcow v1 image format support
+ vdi vdi image format support
+ vvfat vvfat image format support
+ qed qed image format support
+ parallels parallels image format support
+ sheepdog sheepdog block driver support
crypto-afalg Linux AF_ALG crypto backend driver
vhost-user vhost-user support
capstone capstone disassembler support
@@ -2149,23 +2207,6 @@ EOF
fi
fi
-#########################################
-# zlib check
-
-if test "$zlib" != "no" ; then
- cat > $TMPC << EOF
-#include <zlib.h>
-int main(void) { zlibVersion(); return 0; }
-EOF
- if compile_prog "" "-lz" ; then
- :
- else
- error_exit "zlib check failed" \
- "Make sure to have the zlib libs and headers installed."
- fi
-fi
-LIBS="$LIBS -lz"
-
##########################################
# lzo check
@@ -2666,79 +2707,28 @@ fi
##########################################
# GNUTLS probe
-gnutls_works() {
- # Unfortunately some distros have bad pkg-config information for gnutls
- # such that it claims to exist but you get a compiler error if you try
- # to use the options returned by --libs. Specifically, Ubuntu for --static
- # builds doesn't work:
- # https://bugs.launchpad.net/ubuntu/+source/gnutls26/+bug/1478035
- #
- # So sanity check the cflags/libs before assuming gnutls can be used.
- if ! $pkg_config --exists "gnutls"; then
- return 1
- fi
-
- write_c_skeleton
- compile_prog "$($pkg_config --cflags gnutls)" "$($pkg_config --libs gnutls)"
-}
-
-gnutls_gcrypt=no
-gnutls_nettle=no
if test "$gnutls" != "no"; then
- if gnutls_works; then
+ if $pkg_config --exists "gnutls >= 3.1.18"; then
gnutls_cflags=$($pkg_config --cflags gnutls)
gnutls_libs=$($pkg_config --libs gnutls)
libs_softmmu="$gnutls_libs $libs_softmmu"
libs_tools="$gnutls_libs $libs_tools"
QEMU_CFLAGS="$QEMU_CFLAGS $gnutls_cflags"
gnutls="yes"
-
- # gnutls_rnd requires >= 2.11.0
- if $pkg_config --exists "gnutls >= 2.11.0"; then
- gnutls_rnd="yes"
- else
- gnutls_rnd="no"
- fi
-
- if $pkg_config --exists 'gnutls >= 3.0'; then
- gnutls_gcrypt=no
- gnutls_nettle=yes
- elif $pkg_config --exists 'gnutls >= 2.12'; then
- case $($pkg_config --libs --static gnutls) in
- *gcrypt*)
- gnutls_gcrypt=yes
- gnutls_nettle=no
- ;;
- *nettle*)
- gnutls_gcrypt=no
- gnutls_nettle=yes
- ;;
- *)
- gnutls_gcrypt=yes
- gnutls_nettle=no
- ;;
- esac
- else
- gnutls_gcrypt=yes
- gnutls_nettle=no
- fi
elif test "$gnutls" = "yes"; then
- feature_not_found "gnutls" "Install gnutls devel"
+ feature_not_found "gnutls" "Install gnutls devel >= 3.1.18"
else
gnutls="no"
- gnutls_rnd="no"
fi
-else
- gnutls_rnd="no"
fi
# If user didn't give a --disable/enable-gcrypt flag,
# then mark as disabled if user requested nettle
-# explicitly, or if gnutls links to nettle
+# explicitly
if test -z "$gcrypt"
then
- if test "$nettle" = "yes" || test "$gnutls_nettle" = "yes"
+ if test "$nettle" = "yes"
then
gcrypt="no"
fi
@@ -2746,16 +2736,16 @@ fi
# If user didn't give a --disable/enable-nettle flag,
# then mark as disabled if user requested gcrypt
-# explicitly, or if gnutls links to gcrypt
+# explicitly
if test -z "$nettle"
then
- if test "$gcrypt" = "yes" || test "$gnutls_gcrypt" = "yes"
+ if test "$gcrypt" = "yes"
then
nettle="no"
fi
fi
-has_libgcrypt_config() {
+has_libgcrypt() {
if ! has "libgcrypt-config"
then
return 1
@@ -2770,11 +2760,42 @@ has_libgcrypt_config() {
fi
fi
+ maj=`libgcrypt-config --version | awk -F . '{print $1}'`
+ min=`libgcrypt-config --version | awk -F . '{print $2}'`
+
+ if test $maj != 1 || test $min -lt 5
+ then
+ return 1
+ fi
+
return 0
}
+
+if test "$nettle" != "no"; then
+ if $pkg_config --exists "nettle >= 2.7.1"; then
+ nettle_cflags=$($pkg_config --cflags nettle)
+ nettle_libs=$($pkg_config --libs nettle)
+ nettle_version=$($pkg_config --modversion nettle)
+ libs_softmmu="$nettle_libs $libs_softmmu"
+ libs_tools="$nettle_libs $libs_tools"
+ QEMU_CFLAGS="$QEMU_CFLAGS $nettle_cflags"
+ nettle="yes"
+
+ if test -z "$gcrypt"; then
+ gcrypt="no"
+ fi
+ else
+ if test "$nettle" = "yes"; then
+ feature_not_found "nettle" "Install nettle devel >= 2.7.1"
+ else
+ nettle="no"
+ fi
+ fi
+fi
+
if test "$gcrypt" != "no"; then
- if has_libgcrypt_config; then
+ if has_libgcrypt; then
gcrypt_cflags=$(libgcrypt-config --cflags)
gcrypt_libs=$(libgcrypt-config --libs)
# Debian has remove -lgpg-error from libgcrypt-config
@@ -2788,22 +2809,6 @@ if test "$gcrypt" != "no"; then
libs_tools="$gcrypt_libs $libs_tools"
QEMU_CFLAGS="$QEMU_CFLAGS $gcrypt_cflags"
gcrypt="yes"
- if test -z "$nettle"; then
- nettle="no"
- fi
-
- cat > $TMPC << EOF
-#include <gcrypt.h>
-int main(void) {
- gcry_kdf_derive(NULL, 0, GCRY_KDF_PBKDF2,
- GCRY_MD_SHA256,
- NULL, 0, 0, 0, NULL);
- return 0;
-}
-EOF
- if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then
- gcrypt_kdf=yes
- fi
cat > $TMPC << EOF
#include <gcrypt.h>
@@ -2819,7 +2824,7 @@ EOF
fi
else
if test "$gcrypt" = "yes"; then
- feature_not_found "gcrypt" "Install gcrypt devel"
+ feature_not_found "gcrypt" "Install gcrypt devel >= 1.5.0"
else
gcrypt="no"
fi
@@ -2827,36 +2832,6 @@ EOF
fi
-if test "$nettle" != "no"; then
- if $pkg_config --exists "nettle"; then
- nettle_cflags=$($pkg_config --cflags nettle)
- nettle_libs=$($pkg_config --libs nettle)
- nettle_version=$($pkg_config --modversion nettle)
- libs_softmmu="$nettle_libs $libs_softmmu"
- libs_tools="$nettle_libs $libs_tools"
- QEMU_CFLAGS="$QEMU_CFLAGS $nettle_cflags"
- nettle="yes"
-
- cat > $TMPC << EOF
-#include <stddef.h>
-#include <nettle/pbkdf2.h>
-int main(void) {
- pbkdf2_hmac_sha256(8, NULL, 1000, 8, NULL, 8, NULL);
- return 0;
-}
-EOF
- if compile_prog "$nettle_cflags" "$nettle_libs" ; then
- nettle_kdf=yes
- fi
- else
- if test "$nettle" = "yes"; then
- feature_not_found "nettle" "Install nettle devel"
- else
- nettle="no"
- fi
- fi
-fi
-
if test "$gcrypt" = "yes" && test "$nettle" = "yes"
then
error_exit "Only one of gcrypt & nettle can be enabled"
@@ -3543,6 +3518,29 @@ if ! compile_prog "$glib_cflags -Werror" "$glib_libs" ; then
fi
fi
+#########################################
+# zlib check
+
+if test "$zlib" != "no" ; then
+ if $pkg_config --exists zlib; then
+ zlib_cflags=$($pkg_config --cflags zlib)
+ zlib_libs=$($pkg_config --libs zlib)
+ QEMU_CFLAGS="$zlib_cflags $QEMU_CFLAGS"
+ LIBS="$zlib_libs $LIBS"
+ else
+ cat > $TMPC << EOF
+#include <zlib.h>
+int main(void) { zlibVersion(); return 0; }
+EOF
+ if compile_prog "" "-lz" ; then
+ LIBS="$LIBS -lz"
+ else
+ error_exit "zlib check failed" \
+ "Make sure to have the zlib libs and headers installed."
+ fi
+ fi
+fi
+
##########################################
# SHA command probe for modules
if test "$modules" = yes; then
@@ -4202,7 +4200,14 @@ if compile_prog "" "" ; then
memfd=yes
fi
-
+# check for usbfs
+have_usbfs=no
+if test "$linux_user" = "yes"; then
+ if check_include linux/usbdevice_fs.h; then
+ have_usbfs=yes
+ fi
+ have_usbfs=yes
+fi
# check for fallocate
fallocate=no
@@ -5094,7 +5099,7 @@ fi
# There is no point enabling this if cpuid.h is not usable,
# since we won't be able to select the new routines.
-if test $cpuid_h = yes; then
+if test "$cpuid_h" = "yes" -a "$avx2_opt" != "no"; then
cat > $TMPC << EOF
#pragma GCC push_options
#pragma GCC target("avx2")
@@ -5108,6 +5113,8 @@ int main(int argc, char *argv[]) { return bar(argv[0]); }
EOF
if compile_object "" ; then
avx2_opt="yes"
+ else
+ avx2_opt="no"
fi
fi
@@ -5154,6 +5161,21 @@ EOF
fi
fi
+cmpxchg128=no
+if test "$int128" = yes -a "$atomic128" = no; then
+ cat > $TMPC << EOF
+int main(void)
+{
+ unsigned __int128 x = 0, y = 0;
+ __sync_val_compare_and_swap_16(&x, y, x);
+ return 0;
+}
+EOF
+ if compile_prog "" "" ; then
+ cmpxchg128=yes
+ fi
+fi
+
#########################################
# See if 64-bit atomic operations are supported.
# Note that without __atomic builtins, we can only
@@ -5643,6 +5665,17 @@ if test "$libnfs" != "no" ; then
fi
fi
+##########################################
+# Do we have libudev
+if test "$libudev" != "no" ; then
+ if $pkg_config libudev && test "$static" != "yes"; then
+ libudev="yes"
+ libudev_libs=$($pkg_config --libs libudev)
+ else
+ libudev="no"
+ fi
+fi
+
# Now we've finished running tests it's OK to add -Werror to the compiler flags
if test "$werror" = "yes"; then
QEMU_CFLAGS="-Werror $QEMU_CFLAGS"
@@ -5961,11 +5994,8 @@ echo "GTK GL support $gtk_gl"
echo "VTE support $vte $(echo_version $vte $vteversion)"
echo "TLS priority $tls_priority"
echo "GNUTLS support $gnutls"
-echo "GNUTLS rnd $gnutls_rnd"
echo "libgcrypt $gcrypt"
-echo "libgcrypt kdf $gcrypt_kdf"
echo "nettle $nettle $(echo_version $nettle $nettle_version)"
-echo "nettle kdf $nettle_kdf"
echo "libtasn1 $tasn1"
echo "curses support $curses"
echo "virgl support $virglrenderer $(echo_version $virglrenderer $virgl_version)"
@@ -6067,9 +6097,19 @@ echo "jemalloc support $jemalloc"
echo "avx2 optimization $avx2_opt"
echo "replication support $replication"
echo "VxHS block device $vxhs"
+echo "bochs support $bochs"
+echo "cloop support $cloop"
+echo "dmg support $dmg"
+echo "qcow v1 support $qcow1"
+echo "vdi support $vdi"
+echo "vvfat support $vvfat"
+echo "qed support $qed"
+echo "parallels support $parallels"
+echo "sheepdog support $sheepdog"
echo "capstone $capstone"
echo "docker $docker"
echo "libpmem support $libpmem"
+echo "libudev $libudev"
if test "$sdl_too_old" = "yes"; then
echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -6165,7 +6205,7 @@ if test "$mingw32" = "yes" ; then
echo "WIN_SDK=\"$win_sdk\"" >> $config_host_mak
fi
if test "$guest_agent_ntddscsi" = "yes" ; then
- echo "CONFIG_QGA_NTDDDISK=y" >> $config_host_mak
+ echo "CONFIG_QGA_NTDDSCSI=y" >> $config_host_mak
fi
if test "$guest_agent_msi" = "yes"; then
echo "QEMU_GA_MSI_ENABLED=yes" >> $config_host_mak
@@ -6310,6 +6350,9 @@ fi
if test "$memfd" = "yes" ; then
echo "CONFIG_MEMFD=y" >> $config_host_mak
fi
+if test "$have_usbfs" = "yes" ; then
+ echo "CONFIG_USBFS=y" >> $config_host_mak
+fi
if test "$fallocate" = "yes" ; then
echo "CONFIG_FALLOCATE=y" >> $config_host_mak
fi
@@ -6401,24 +6444,15 @@ echo "CONFIG_TLS_PRIORITY=\"$tls_priority\"" >> $config_host_mak
if test "$gnutls" = "yes" ; then
echo "CONFIG_GNUTLS=y" >> $config_host_mak
fi
-if test "$gnutls_rnd" = "yes" ; then
- echo "CONFIG_GNUTLS_RND=y" >> $config_host_mak
-fi
if test "$gcrypt" = "yes" ; then
echo "CONFIG_GCRYPT=y" >> $config_host_mak
if test "$gcrypt_hmac" = "yes" ; then
echo "CONFIG_GCRYPT_HMAC=y" >> $config_host_mak
fi
- if test "$gcrypt_kdf" = "yes" ; then
- echo "CONFIG_GCRYPT_KDF=y" >> $config_host_mak
- fi
fi
if test "$nettle" = "yes" ; then
echo "CONFIG_NETTLE=y" >> $config_host_mak
echo "CONFIG_NETTLE_VERSION_MAJOR=${nettle_version%%.*}" >> $config_host_mak
- if test "$nettle_kdf" = "yes" ; then
- echo "CONFIG_NETTLE_KDF=y" >> $config_host_mak
- fi
fi
if test "$tasn1" = "yes" ; then
echo "CONFIG_TASN1=y" >> $config_host_mak
@@ -6663,6 +6697,10 @@ if test "$atomic128" = "yes" ; then
echo "CONFIG_ATOMIC128=y" >> $config_host_mak
fi
+if test "$cmpxchg128" = "yes" ; then
+ echo "CONFIG_CMPXCHG128=y" >> $config_host_mak
+fi
+
if test "$atomic64" = "yes" ; then
echo "CONFIG_ATOMIC64=y" >> $config_host_mak
fi
@@ -6824,6 +6862,34 @@ if test "$libpmem" = "yes" ; then
echo "CONFIG_LIBPMEM=y" >> $config_host_mak
fi
+if test "$bochs" = "yes" ; then
+ echo "CONFIG_BOCHS=y" >> $config_host_mak
+fi
+if test "$cloop" = "yes" ; then
+ echo "CONFIG_CLOOP=y" >> $config_host_mak
+fi
+if test "$dmg" = "yes" ; then
+ echo "CONFIG_DMG=y" >> $config_host_mak
+fi
+if test "$qcow1" = "yes" ; then
+ echo "CONFIG_QCOW1=y" >> $config_host_mak
+fi
+if test "$vdi" = "yes" ; then
+ echo "CONFIG_VDI=y" >> $config_host_mak
+fi
+if test "$vvfat" = "yes" ; then
+ echo "CONFIG_VVFAT=y" >> $config_host_mak
+fi
+if test "$qed" = "yes" ; then
+ echo "CONFIG_QED=y" >> $config_host_mak
+fi
+if test "$parallels" = "yes" ; then
+ echo "CONFIG_PARALLELS=y" >> $config_host_mak
+fi
+if test "$sheepdog" = "yes" ; then
+ echo "CONFIG_SHEEPDOG=y" >> $config_host_mak
+fi
+
if test "$tcg_interpreter" = "yes"; then
QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/tci $QEMU_INCLUDES"
elif test "$ARCH" = "sparc64" ; then
@@ -6907,6 +6973,11 @@ if test "$docker" != "no"; then
echo "HAVE_USER_DOCKER=y" >> $config_host_mak
fi
+if test "$libudev" != "no"; then
+ echo "CONFIG_LIBUDEV=y" >> $config_host_mak
+ echo "LIBUDEV_LIBS=$libudev_libs" >> $config_host_mak
+fi
+
# use included Linux headers
if test "$linux" = "yes" ; then
mkdir -p linux-headers
@@ -7144,6 +7215,7 @@ case "$target_name" in
;;
xtensa|xtensaeb)
TARGET_ARCH=xtensa
+ bflt="yes"
mttcg="yes"
target_compiler=$cross_cc_xtensa
;;
@@ -7309,6 +7381,9 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
;;
mips*)
disas_config "MIPS"
+ if test -n "${cxx}"; then
+ disas_config "NANOMIPS"
+ fi
;;
moxie*)
disas_config "MOXIE"
@@ -7408,22 +7483,33 @@ if test "$ccache_cpp2" = "yes"; then
echo "export CCACHE_CPP2=y" >> $config_host_mak
fi
-# build tree in object directory in case the source is not in the current directory
+# If we're using a separate build tree, set it up now.
+# DIRS are directories which we simply mkdir in the build tree;
+# LINKS are things to symlink back into the source tree
+# (these can be both files and directories).
+# Caution: do not add files or directories here using wildcards. This
+# will result in problems later if a new file matching the wildcard is
+# added to the source tree -- nothing will cause configure to be rerun
+# so the build tree will be missing the link back to the new file, and
+# tests might fail. Prefer to keep the relevant files in their own
+# directory and symlink the directory instead.
DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos tests/qapi-schema tests/tcg/xtensa tests/qemu-iotests tests/vm"
DIRS="$DIRS tests/fp"
DIRS="$DIRS docs docs/interop fsdev scsi"
DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas pc-bios/s390-ccw"
DIRS="$DIRS roms/seabios roms/vgabios"
-FILES="Makefile tests/tcg/Makefile qdict-test-data.txt"
-FILES="$FILES tests/tcg/cris/Makefile tests/tcg/cris/.gdbinit"
-FILES="$FILES tests/tcg/lm32/Makefile tests/tcg/xtensa/Makefile po/Makefile"
-FILES="$FILES tests/fp/Makefile"
-FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
-FILES="$FILES pc-bios/spapr-rtas/Makefile"
-FILES="$FILES pc-bios/s390-ccw/Makefile"
-FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile"
-FILES="$FILES pc-bios/qemu-icon.bmp"
-FILES="$FILES .gdbinit scripts" # scripts needed by relative path in .gdbinit
+LINKS="Makefile tests/tcg/Makefile qdict-test-data.txt"
+LINKS="$LINKS tests/tcg/cris/Makefile tests/tcg/cris/.gdbinit"
+LINKS="$LINKS tests/tcg/lm32/Makefile tests/tcg/xtensa/Makefile po/Makefile"
+LINKS="$LINKS tests/fp/Makefile"
+LINKS="$LINKS pc-bios/optionrom/Makefile pc-bios/keymaps"
+LINKS="$LINKS pc-bios/spapr-rtas/Makefile"
+LINKS="$LINKS pc-bios/s390-ccw/Makefile"
+LINKS="$LINKS roms/seabios/Makefile roms/vgabios/Makefile"
+LINKS="$LINKS pc-bios/qemu-icon.bmp"
+LINKS="$LINKS .gdbinit scripts" # scripts needed by relative path in .gdbinit
+LINKS="$LINKS tests/acceptance tests/data"
+LINKS="$LINKS tests/qemu-iotests/check"
for bios_file in \
$source_path/pc-bios/*.bin \
$source_path/pc-bios/*.lid \
@@ -7435,18 +7521,10 @@ for bios_file in \
$source_path/pc-bios/u-boot.* \
$source_path/pc-bios/palcode-*
do
- FILES="$FILES pc-bios/$(basename $bios_file)"
-done
-for test_file in $(find $source_path/tests/acpi-test-data -type f)
-do
- FILES="$FILES tests/acpi-test-data$(echo $test_file | sed -e 's/.*acpi-test-data//')"
-done
-for test_file in $(find $source_path/tests/hex-loader-check-data -type f)
-do
- FILES="$FILES tests/hex-loader-check-data$(echo $test_file | sed -e 's/.*hex-loader-check-data//')"
+ LINKS="$LINKS pc-bios/$(basename $bios_file)"
done
mkdir -p $DIRS
-for f in $FILES ; do
+for f in $LINKS ; do
if [ -e "$source_path/$f" ] && [ "$pwd_is_source_path" != "y" ]; then
symlink "$source_path/$f" "$f"
fi
@@ -7468,25 +7546,13 @@ for rom in seabios vgabios ; do
echo "RANLIB=$ranlib" >> $config_mak
done
-# set up tests data directory
-for tests_subdir in acceptance data; do
- if [ ! -e tests/$tests_subdir ]; then
- symlink "$source_path/tests/$tests_subdir" tests/$tests_subdir
- fi
-done
-
# set up qemu-iotests in this build directory
iotests_common_env="tests/qemu-iotests/common.env"
-iotests_check="tests/qemu-iotests/check"
echo "# Automatically generated by configure - do not modify" > "$iotests_common_env"
echo >> "$iotests_common_env"
echo "export PYTHON='$python'" >> "$iotests_common_env"
-if [ ! -e "$iotests_check" ]; then
- symlink "$source_path/$iotests_check" "$iotests_check"
-fi
-
# Save the configure command line for later reuse.
cat <<EOD >config.status
#!/bin/sh
diff --git a/cpus.c b/cpus.c
index 361678e459..a2b33ccb29 100644
--- a/cpus.c
+++ b/cpus.c
@@ -211,12 +211,12 @@ void qemu_tcg_configure(QemuOpts *opts, Error **errp)
error_setg(errp, "No MTTCG when icount is enabled");
} else {
#ifndef TARGET_SUPPORTS_MTTCG
- error_report("Guest not yet converted to MTTCG - "
- "you may get unexpected results");
+ warn_report("Guest not yet converted to MTTCG - "
+ "you may get unexpected results");
#endif
if (!check_tcg_memory_orders_compatible()) {
- error_report("Guest expects a stronger memory ordering "
- "than the host provides");
+ warn_report("Guest expects a stronger memory ordering "
+ "than the host provides");
error_printf("This may cause strange/hard to debug errors\n");
}
mttcg_enabled = true;
@@ -509,8 +509,8 @@ static void icount_warp_rt(void)
seqlock_write_lock(&timers_state.vm_clock_seqlock,
&timers_state.vm_clock_lock);
if (runstate_is_running()) {
- int64_t clock = REPLAY_CLOCK(REPLAY_CLOCK_VIRTUAL_RT,
- cpu_get_clock_locked());
+ int64_t clock = REPLAY_CLOCK_LOCKED(REPLAY_CLOCK_VIRTUAL_RT,
+ cpu_get_clock_locked());
int64_t warp_delta;
warp_delta = clock - timers_state.vm_clock_warp_start;
@@ -1425,7 +1425,8 @@ static int tcg_cpu_exec(CPUState *cpu)
ret = cpu_exec(cpu);
cpu_exec_end(cpu);
#ifdef CONFIG_PROFILER
- tcg_time += profile_getclock() - ti;
+ atomic_set(&tcg_ctx->prof.cpu_exec_time,
+ tcg_ctx->prof.cpu_exec_time + profile_getclock() - ti);
#endif
return ret;
}
@@ -1553,6 +1554,14 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg)
atomic_mb_set(&cpu->exit_request, 0);
}
+ if (use_icount && all_cpu_threads_idle()) {
+ /*
+ * When all cpus are sleeping (e.g in WFI), to avoid a deadlock
+ * in the main_loop, wake it up in order to start the warp timer.
+ */
+ qemu_notify_event();
+ }
+
qemu_tcg_rr_wait_io_event(cpu ? cpu : first_cpu);
deal_with_unplugged_cpus();
}
diff --git a/crypto/Makefile.objs b/crypto/Makefile.objs
index 756bab111b..256c9aca1f 100644
--- a/crypto/Makefile.objs
+++ b/crypto/Makefile.objs
@@ -20,11 +20,11 @@ crypto-obj-y += tlscredsx509.o
crypto-obj-y += tlssession.o
crypto-obj-y += secret.o
crypto-obj-$(CONFIG_GCRYPT) += random-gcrypt.o
-crypto-obj-$(if $(CONFIG_GCRYPT),n,$(CONFIG_GNUTLS_RND)) += random-gnutls.o
-crypto-obj-$(if $(CONFIG_GCRYPT),n,$(if $(CONFIG_GNUTLS_RND),n,y)) += random-platform.o
+crypto-obj-$(if $(CONFIG_GCRYPT),n,$(CONFIG_GNUTLS)) += random-gnutls.o
+crypto-obj-$(if $(CONFIG_GCRYPT),n,$(if $(CONFIG_GNUTLS),n,y)) += random-platform.o
crypto-obj-y += pbkdf.o
-crypto-obj-$(CONFIG_NETTLE_KDF) += pbkdf-nettle.o
-crypto-obj-$(if $(CONFIG_NETTLE_KDF),n,$(CONFIG_GCRYPT_KDF)) += pbkdf-gcrypt.o
+crypto-obj-$(CONFIG_NETTLE) += pbkdf-nettle.o
+crypto-obj-$(if $(CONFIG_NETTLE),n,$(CONFIG_GCRYPT)) += pbkdf-gcrypt.o
crypto-obj-y += ivgen.o
crypto-obj-y += ivgen-essiv.o
crypto-obj-y += ivgen-plain.o
diff --git a/crypto/block-qcow.c b/crypto/block-qcow.c
index 4284e05167..7606231e79 100644
--- a/crypto/block-qcow.c
+++ b/crypto/block-qcow.c
@@ -102,6 +102,8 @@ qcrypto_block_qcow_open(QCryptoBlock *block,
Error **errp)
{
if (flags & QCRYPTO_BLOCK_OPEN_NO_IO) {
+ block->sector_size = QCRYPTO_BLOCK_QCOW_SECTOR_SIZE;
+ block->payload_offset = 0;
return 0;
} else {
if (!options->u.qcow.key_secret) {
diff --git a/crypto/init.c b/crypto/init.c
index f131c42306..c30156405a 100644
--- a/crypto/init.c
+++ b/crypto/init.c
@@ -37,33 +37,14 @@
/* #define DEBUG_GNUTLS */
/*
- * If GNUTLS is built against GCrypt then
- *
- * - When GNUTLS >= 2.12, we must not initialize gcrypt threading
- * because GNUTLS will do that itself
- * - When GNUTLS < 2.12 we must always initialize gcrypt threading
- * - When GNUTLS is disabled we must always initialize gcrypt threading
- *
- * But....
- *
- * When gcrypt >= 1.6.0 we must not initialize gcrypt threading
- * because gcrypt will do that itself.
- *
- * So we need to init gcrypt threading if
+ * We need to init gcrypt threading if
*
* - gcrypt < 1.6.0
- * AND
- * - gnutls < 2.12
- * OR
- * - gnutls is disabled
*
*/
#if (defined(CONFIG_GCRYPT) && \
- (!defined(CONFIG_GNUTLS) || \
- (LIBGNUTLS_VERSION_NUMBER < 0x020c00)) && \
- (!defined(GCRYPT_VERSION_NUMBER) || \
- (GCRYPT_VERSION_NUMBER < 0x010600)))
+ (GCRYPT_VERSION_NUMBER < 0x010600))
#define QCRYPTO_INIT_GCRYPT_THREADS
#else
#undef QCRYPTO_INIT_GCRYPT_THREADS
diff --git a/crypto/tlscredsx509.c b/crypto/tlscredsx509.c
index 98ee0424e5..d6ab4a9862 100644
--- a/crypto/tlscredsx509.c
+++ b/crypto/tlscredsx509.c
@@ -72,14 +72,6 @@ qcrypto_tls_creds_check_cert_times(gnutls_x509_crt_t cert,
}
-#if LIBGNUTLS_VERSION_NUMBER >= 2
-/*
- * The gnutls_x509_crt_get_basic_constraints function isn't
- * available in GNUTLS 1.0.x branches. This isn't critical
- * though, since gnutls_certificate_verify_peers2 will do
- * pretty much the same check at runtime, so we can just
- * disable this code
- */
static int
qcrypto_tls_creds_check_cert_basic_constraints(QCryptoTLSCredsX509 *creds,
gnutls_x509_crt_t cert,
@@ -130,7 +122,6 @@ qcrypto_tls_creds_check_cert_basic_constraints(QCryptoTLSCredsX509 *creds,
return 0;
}
-#endif
static int
@@ -299,14 +290,12 @@ qcrypto_tls_creds_check_cert(QCryptoTLSCredsX509 *creds,
return -1;
}
-#if LIBGNUTLS_VERSION_NUMBER >= 2
if (qcrypto_tls_creds_check_cert_basic_constraints(creds,
cert, certFile,
isServer, isCA,
errp) < 0) {
return -1;
}
-#endif
if (qcrypto_tls_creds_check_cert_key_usage(creds,
cert, certFile,
@@ -615,7 +604,6 @@ qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds,
}
if (cert != NULL && key != NULL) {
-#if LIBGNUTLS_VERSION_NUMBER >= 0x030111
char *password = NULL;
if (creds->passwordid) {
password = qcrypto_secret_lookup_as_utf8(creds->passwordid,
@@ -630,15 +618,6 @@ qcrypto_tls_creds_x509_load(QCryptoTLSCredsX509 *creds,
password,
0);
g_free(password);
-#else /* LIBGNUTLS_VERSION_NUMBER < 0x030111 */
- if (creds->passwordid) {
- error_setg(errp, "PKCS8 decryption requires GNUTLS >= 3.1.11");
- goto cleanup;
- }
- ret = gnutls_certificate_set_x509_key_file(creds->data,
- cert, key,
- GNUTLS_X509_FMT_PEM);
-#endif
if (ret < 0) {
error_setg(errp, "Cannot load certificate '%s' & key '%s': %s",
cert, key, gnutls_strerror(ret));
diff --git a/crypto/tlssession.c b/crypto/tlssession.c
index 66a6fbe19c..0dedd4af52 100644
--- a/crypto/tlssession.c
+++ b/crypto/tlssession.c
@@ -90,13 +90,7 @@ qcrypto_tls_session_pull(void *opaque, void *buf, size_t len)
}
#define TLS_PRIORITY_ADDITIONAL_ANON "+ANON-DH"
-
-#if GNUTLS_VERSION_MAJOR >= 3
-#define TLS_ECDHE_PSK "+ECDHE-PSK:"
-#else
-#define TLS_ECDHE_PSK ""
-#endif
-#define TLS_PRIORITY_ADDITIONAL_PSK TLS_ECDHE_PSK "+DHE-PSK:+PSK"
+#define TLS_PRIORITY_ADDITIONAL_PSK "+ECDHE-PSK:+DHE-PSK:+PSK"
QCryptoTLSSession *
qcrypto_tls_session_new(QCryptoTLSCreds *creds,
@@ -479,6 +473,9 @@ qcrypto_tls_session_read(QCryptoTLSSession *session,
case GNUTLS_E_INTERRUPTED:
errno = EINTR;
break;
+ case GNUTLS_E_PREMATURE_TERMINATION:
+ errno = ECONNABORTED;
+ break;
default:
errno = EIO;
break;
diff --git a/crypto/xts.c b/crypto/xts.c
index 95212341f6..4277ad40de 100644
--- a/crypto/xts.c
+++ b/crypto/xts.c
@@ -24,52 +24,75 @@
*/
#include "qemu/osdep.h"
+#include "qemu/bswap.h"
#include "crypto/xts.h"
-static void xts_mult_x(uint8_t *I)
+typedef union {
+ uint8_t b[XTS_BLOCK_SIZE];
+ uint64_t u[2];
+} xts_uint128;
+
+static inline void xts_uint128_xor(xts_uint128 *D,
+ const xts_uint128 *S1,
+ const xts_uint128 *S2)
{
- int x;
- uint8_t t, tt;
+ D->u[0] = S1->u[0] ^ S2->u[0];
+ D->u[1] = S1->u[1] ^ S2->u[1];
+}
- for (x = t = 0; x < 16; x++) {
- tt = I[x] >> 7;
- I[x] = ((I[x] << 1) | t) & 0xFF;
- t = tt;
- }
- if (tt) {
- I[0] ^= 0x87;
+static inline void xts_uint128_cpu_to_les(xts_uint128 *v)
+{
+ cpu_to_le64s(&v->u[0]);
+ cpu_to_le64s(&v->u[1]);
+}
+
+static inline void xts_uint128_le_to_cpus(xts_uint128 *v)
+{
+ le64_to_cpus(&v->u[0]);
+ le64_to_cpus(&v->u[1]);
+}
+
+static void xts_mult_x(xts_uint128 *I)
+{
+ uint64_t tt;
+
+ xts_uint128_le_to_cpus(I);
+
+ tt = I->u[0] >> 63;
+ I->u[0] <<= 1;
+
+ if (I->u[1] >> 63) {
+ I->u[0] ^= 0x87;
}
+ I->u[1] <<= 1;
+ I->u[1] |= tt;
+
+ xts_uint128_cpu_to_les(I);
}
/**
- * xts_tweak_uncrypt:
+ * xts_tweak_encdec:
* @param ctxt: the cipher context
* @param func: the cipher function
- * @src: buffer providing the cipher text of XTS_BLOCK_SIZE bytes
- * @dst: buffer to output the plain text of XTS_BLOCK_SIZE bytes
+ * @src: buffer providing the input text of XTS_BLOCK_SIZE bytes
+ * @dst: buffer to output the output text of XTS_BLOCK_SIZE bytes
* @iv: the initialization vector tweak of XTS_BLOCK_SIZE bytes
*
- * Decrypt data with a tweak
+ * Encrypt/decrypt data with a tweak
*/
-static void xts_tweak_decrypt(const void *ctx,
- xts_cipher_func *func,
- const uint8_t *src,
- uint8_t *dst,
- uint8_t *iv)
+static inline void xts_tweak_encdec(const void *ctx,
+ xts_cipher_func *func,
+ const xts_uint128 *src,
+ xts_uint128 *dst,
+ xts_uint128 *iv)
{
- unsigned long x;
-
/* tweak encrypt block i */
- for (x = 0; x < XTS_BLOCK_SIZE; x++) {
- dst[x] = src[x] ^ iv[x];
- }
+ xts_uint128_xor(dst, src, iv);
- func(ctx, XTS_BLOCK_SIZE, dst, dst);
+ func(ctx, XTS_BLOCK_SIZE, dst->b, dst->b);
- for (x = 0; x < XTS_BLOCK_SIZE; x++) {
- dst[x] = dst[x] ^ iv[x];
- }
+ xts_uint128_xor(dst, dst, iv);
/* LFSR the tweak */
xts_mult_x(iv);
@@ -85,7 +108,7 @@ void xts_decrypt(const void *datactx,
uint8_t *dst,
const uint8_t *src)
{
- uint8_t PP[XTS_BLOCK_SIZE], CC[XTS_BLOCK_SIZE], T[XTS_BLOCK_SIZE];
+ xts_uint128 PP, CC, T;
unsigned long i, m, mo, lim;
/* get number of blocks */
@@ -102,72 +125,53 @@ void xts_decrypt(const void *datactx,
}
/* encrypt the iv */
- encfunc(tweakctx, XTS_BLOCK_SIZE, T, iv);
-
- for (i = 0; i < lim; i++) {
- xts_tweak_decrypt(datactx, decfunc, src, dst, T);
-
- src += XTS_BLOCK_SIZE;
- dst += XTS_BLOCK_SIZE;
+ encfunc(tweakctx, XTS_BLOCK_SIZE, T.b, iv);
+
+ if (QEMU_PTR_IS_ALIGNED(src, sizeof(uint64_t)) &&
+ QEMU_PTR_IS_ALIGNED(dst, sizeof(uint64_t))) {
+ xts_uint128 *S = (xts_uint128 *)src;
+ xts_uint128 *D = (xts_uint128 *)dst;
+ for (i = 0; i < lim; i++, S++, D++) {
+ xts_tweak_encdec(datactx, decfunc, S, D, &T);
+ }
+ } else {
+ xts_uint128 D;
+
+ for (i = 0; i < lim; i++) {
+ memcpy(&D, src, XTS_BLOCK_SIZE);
+ xts_tweak_encdec(datactx, decfunc, &D, &D, &T);
+ memcpy(dst, &D, XTS_BLOCK_SIZE);
+ src += XTS_BLOCK_SIZE;
+ dst += XTS_BLOCK_SIZE;
+ }
}
/* if length is not a multiple of XTS_BLOCK_SIZE then */
if (mo > 0) {
- memcpy(CC, T, XTS_BLOCK_SIZE);
- xts_mult_x(CC);
+ xts_uint128 S, D;
+ memcpy(&CC, &T, XTS_BLOCK_SIZE);
+ xts_mult_x(&CC);
/* PP = tweak decrypt block m-1 */
- xts_tweak_decrypt(datactx, decfunc, src, PP, CC);
+ memcpy(&S, src, XTS_BLOCK_SIZE);
+ xts_tweak_encdec(datactx, decfunc, &S, &PP, &CC);
/* Pm = first length % XTS_BLOCK_SIZE bytes of PP */
for (i = 0; i < mo; i++) {
- CC[i] = src[XTS_BLOCK_SIZE + i];
- dst[XTS_BLOCK_SIZE + i] = PP[i];
+ CC.b[i] = src[XTS_BLOCK_SIZE + i];
+ dst[XTS_BLOCK_SIZE + i] = PP.b[i];
}
for (; i < XTS_BLOCK_SIZE; i++) {
- CC[i] = PP[i];
+ CC.b[i] = PP.b[i];
}
/* Pm-1 = Tweak uncrypt CC */
- xts_tweak_decrypt(datactx, decfunc, CC, dst, T);
+ xts_tweak_encdec(datactx, decfunc, &CC, &D, &T);
+ memcpy(dst, &D, XTS_BLOCK_SIZE);
}
/* Decrypt the iv back */
- decfunc(tweakctx, XTS_BLOCK_SIZE, iv, T);
-}
-
-
-/**
- * xts_tweak_crypt:
- * @param ctxt: the cipher context
- * @param func: the cipher function
- * @src: buffer providing the plain text of XTS_BLOCK_SIZE bytes
- * @dst: buffer to output the cipher text of XTS_BLOCK_SIZE bytes
- * @iv: the initialization vector tweak of XTS_BLOCK_SIZE bytes
- *
- * Encrypt data with a tweak
- */
-static void xts_tweak_encrypt(const void *ctx,
- xts_cipher_func *func,
- const uint8_t *src,
- uint8_t *dst,
- uint8_t *iv)
-{
- unsigned long x;
-
- /* tweak encrypt block i */
- for (x = 0; x < XTS_BLOCK_SIZE; x++) {
- dst[x] = src[x] ^ iv[x];
- }
-
- func(ctx, XTS_BLOCK_SIZE, dst, dst);
-
- for (x = 0; x < XTS_BLOCK_SIZE; x++) {
- dst[x] = dst[x] ^ iv[x];
- }
-
- /* LFSR the tweak */
- xts_mult_x(iv);
+ decfunc(tweakctx, XTS_BLOCK_SIZE, iv, T.b);
}
@@ -180,7 +184,7 @@ void xts_encrypt(const void *datactx,
uint8_t *dst,
const uint8_t *src)
{
- uint8_t PP[XTS_BLOCK_SIZE], CC[XTS_BLOCK_SIZE], T[XTS_BLOCK_SIZE];
+ xts_uint128 PP, CC, T;
unsigned long i, m, mo, lim;
/* get number of blocks */
@@ -197,34 +201,50 @@ void xts_encrypt(const void *datactx,
}
/* encrypt the iv */
- encfunc(tweakctx, XTS_BLOCK_SIZE, T, iv);
+ encfunc(tweakctx, XTS_BLOCK_SIZE, T.b, iv);
+
+ if (QEMU_PTR_IS_ALIGNED(src, sizeof(uint64_t)) &&
+ QEMU_PTR_IS_ALIGNED(dst, sizeof(uint64_t))) {
+ xts_uint128 *S = (xts_uint128 *)src;
+ xts_uint128 *D = (xts_uint128 *)dst;
+ for (i = 0; i < lim; i++, S++, D++) {
+ xts_tweak_encdec(datactx, encfunc, S, D, &T);
+ }
+ } else {
+ xts_uint128 D;
- for (i = 0; i < lim; i++) {
- xts_tweak_encrypt(datactx, encfunc, src, dst, T);
+ for (i = 0; i < lim; i++) {
+ memcpy(&D, src, XTS_BLOCK_SIZE);
+ xts_tweak_encdec(datactx, encfunc, &D, &D, &T);
+ memcpy(dst, &D, XTS_BLOCK_SIZE);
- dst += XTS_BLOCK_SIZE;
- src += XTS_BLOCK_SIZE;
+ dst += XTS_BLOCK_SIZE;
+ src += XTS_BLOCK_SIZE;
+ }
}
/* if length is not a multiple of XTS_BLOCK_SIZE then */
if (mo > 0) {
+ xts_uint128 S, D;
/* CC = tweak encrypt block m-1 */
- xts_tweak_encrypt(datactx, encfunc, src, CC, T);
+ memcpy(&S, src, XTS_BLOCK_SIZE);
+ xts_tweak_encdec(datactx, encfunc, &S, &CC, &T);
/* Cm = first length % XTS_BLOCK_SIZE bytes of CC */
for (i = 0; i < mo; i++) {
- PP[i] = src[XTS_BLOCK_SIZE + i];
- dst[XTS_BLOCK_SIZE + i] = CC[i];
+ PP.b[i] = src[XTS_BLOCK_SIZE + i];
+ dst[XTS_BLOCK_SIZE + i] = CC.b[i];
}
for (; i < XTS_BLOCK_SIZE; i++) {
- PP[i] = CC[i];
+ PP.b[i] = CC.b[i];
}
/* Cm-1 = Tweak encrypt PP */
- xts_tweak_encrypt(datactx, encfunc, PP, dst, T);
+ xts_tweak_encdec(datactx, encfunc, &PP, &D, &T);
+ memcpy(dst, &D, XTS_BLOCK_SIZE);
}
/* Decrypt the iv back */
- decfunc(tweakctx, XTS_BLOCK_SIZE, iv, T);
+ decfunc(tweakctx, XTS_BLOCK_SIZE, iv, T.b);
}
diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-softmmu.mak
index 6f790f061a..4ea9add003 100644
--- a/default-configs/aarch64-softmmu.mak
+++ b/default-configs/aarch64-softmmu.mak
@@ -8,4 +8,5 @@ CONFIG_DDC=y
CONFIG_DPCD=y
CONFIG_XLNX_ZYNQMP=y
CONFIG_XLNX_ZYNQMP_ARM=y
+CONFIG_XLNX_VERSAL=y
CONFIG_ARM_SMMUV3=y
diff --git a/default-configs/alpha-softmmu.mak b/default-configs/alpha-softmmu.mak
index bbe361f01a..4d654eaa0b 100644
--- a/default-configs/alpha-softmmu.mak
+++ b/default-configs/alpha-softmmu.mak
@@ -8,7 +8,6 @@ CONFIG_I82374=y
CONFIG_I8254=y
CONFIG_I8257=y
CONFIG_PARALLEL=y
-CONFIG_PARALLEL_ISA=y
CONFIG_FDC=y
CONFIG_PCKBD=y
CONFIG_VGA_CIRRUS=y
@@ -19,3 +18,4 @@ CONFIG_IDE_CMD646=y
CONFIG_I8259=y
CONFIG_MC146818RTC=y
CONFIG_ISA_TESTDEV=y
+CONFIG_SMC37C669=y
diff --git a/default-configs/hyperv.mak b/default-configs/hyperv.mak
new file mode 100644
index 0000000000..5d0d9fd830
--- /dev/null
+++ b/default-configs/hyperv.mak
@@ -0,0 +1,2 @@
+CONFIG_HYPERV=$(CONFIG_KVM)
+CONFIG_HYPERV_TESTDEV=y
diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 8c7d4a0fa0..64c998c4c8 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -3,6 +3,7 @@
include pci.mak
include sound.mak
include usb.mak
+include hyperv.mak
CONFIG_QXL=$(CONFIG_SPICE)
CONFIG_VGA_ISA=y
CONFIG_VGA_CIRRUS=y
@@ -50,7 +51,8 @@ CONFIG_PCI_Q35=y
CONFIG_APIC=y
CONFIG_IOAPIC=y
CONFIG_PVPANIC=y
-CONFIG_MEM_HOTPLUG=y
+CONFIG_MEM_DEVICE=y
+CONFIG_DIMM=y
CONFIG_NVDIMM=y
CONFIG_ACPI_NVDIMM=y
CONFIG_PCIE_PORT=y
@@ -58,7 +60,6 @@ CONFIG_XIO3130=y
CONFIG_IOH3420=y
CONFIG_I82801B11=y
CONFIG_SMBIOS=y
-CONFIG_HYPERV_TESTDEV=$(CONFIG_KVM)
CONFIG_PXB=y
CONFIG_ACPI_VMGENID=y
CONFIG_FW_CFG_DMA=y
diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index 3181bbf163..23d871fb3e 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -28,6 +28,7 @@ CONFIG_SM501=y
CONFIG_DDC=y
CONFIG_IDE_SII3112=y
CONFIG_I2C=y
+CONFIG_AT24C=y
CONFIG_BITBANG_I2C=y
CONFIG_M41T80=y
CONFIG_VGA_CIRRUS=y
diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
index b94af6c7c6..aec2855750 100644
--- a/default-configs/ppc64-softmmu.mak
+++ b/default-configs/ppc64-softmmu.mak
@@ -16,4 +16,6 @@ CONFIG_VIRTIO_VGA=y
CONFIG_XICS=$(CONFIG_PSERIES)
CONFIG_XICS_SPAPR=$(CONFIG_PSERIES)
CONFIG_XICS_KVM=$(call land,$(CONFIG_PSERIES),$(CONFIG_KVM))
-CONFIG_MEM_HOTPLUG=y
+CONFIG_MEM_DEVICE=y
+CONFIG_DIMM=y
+CONFIG_SPAPR_RNG=y
diff --git a/default-configs/sparc64-softmmu.mak b/default-configs/sparc64-softmmu.mak
index 52edafe547..ce63d47046 100644
--- a/default-configs/sparc64-softmmu.mak
+++ b/default-configs/sparc64-softmmu.mak
@@ -16,5 +16,4 @@ CONFIG_SIMBA=y
CONFIG_SUNHME=y
CONFIG_MC146818RTC=y
CONFIG_ISA_TESTDEV=y
-CONFIG_EMPTY_SLOT=y
CONFIG_SUN4V_RTC=y
diff --git a/device-hotplug.c b/device-hotplug.c
index cd427e2c76..6090d5f1e9 100644
--- a/device-hotplug.c
+++ b/device-hotplug.c
@@ -28,6 +28,7 @@
#include "sysemu/block-backend.h"
#include "sysemu/blockdev.h"
#include "qapi/qmp/qdict.h"
+#include "qapi/error.h"
#include "qemu/config-file.h"
#include "qemu/option.h"
#include "sysemu/sysemu.h"
@@ -36,6 +37,7 @@
static DriveInfo *add_init_drive(const char *optstr)
{
+ Error *err = NULL;
DriveInfo *dinfo;
QemuOpts *opts;
MachineClass *mc;
@@ -45,8 +47,9 @@ static DriveInfo *add_init_drive(const char *optstr)
return NULL;
mc = MACHINE_GET_CLASS(current_machine);
- dinfo = drive_new(opts, mc->block_default_type);
+ dinfo = drive_new(opts, mc->block_default_type, &err);
if (!dinfo) {
+ error_report_err(err);
qemu_opts_del(opts);
return NULL;
}
diff --git a/disas/Makefile.objs b/disas/Makefile.objs
index 213be2fab2..3c1cdce026 100644
--- a/disas/Makefile.objs
+++ b/disas/Makefile.objs
@@ -14,6 +14,7 @@ common-obj-$(CONFIG_I386_DIS) += i386.o
common-obj-$(CONFIG_M68K_DIS) += m68k.o
common-obj-$(CONFIG_MICROBLAZE_DIS) += microblaze.o
common-obj-$(CONFIG_MIPS_DIS) += mips.o
+common-obj-$(CONFIG_NANOMIPS_DIS) += nanomips.o
common-obj-$(CONFIG_NIOS2_DIS) += nios2.o
common-obj-$(CONFIG_MOXIE_DIS) += moxie.o
common-obj-$(CONFIG_PPC_DIS) += ppc.o
diff --git a/disas/nanomips.cpp b/disas/nanomips.cpp
new file mode 100644
index 0000000000..1238c2ff33
--- /dev/null
+++ b/disas/nanomips.cpp
@@ -0,0 +1,22242 @@
+/*
+ * Source file for nanoMIPS disassembler component of QEMU
+ *
+ * Copyright (C) 2018 Wave Computing
+ * Copyright (C) 2018 Matthew Fortune <matthew.fortune@mips.com>
+ * Copyright (C) 2018 Aleksandar Markovic <aleksandar.markovic@wavecomp.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+extern "C" {
+#include "qemu/osdep.h"
+#include "disas/bfd.h"
+}
+
+#include <cstring>
+#include <stdexcept>
+#include <sstream>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "nanomips.h"
+
+#define IMGASSERTONCE(test)
+
+
+int nanomips_dis(char *buf,
+ unsigned address,
+ unsigned short one,
+ unsigned short two,
+ unsigned short three)
+{
+ std::string disasm;
+ uint16 bits[3] = {one, two, three};
+
+ NMD::TABLE_ENTRY_TYPE type;
+ NMD d(address, NMD::ALL_ATTRIBUTES);
+ int size = d.Disassemble(bits, disasm, type);
+
+ strcpy(buf, disasm.c_str());
+ return size;
+}
+
+int print_insn_nanomips(bfd_vma memaddr, struct disassemble_info *info)
+{
+ int status;
+ bfd_byte buffer[2];
+ uint16_t insn1 = 0, insn2 = 0, insn3 = 0;
+ char buf[200];
+
+ info->bytes_per_chunk = 2;
+ info->display_endian = info->endian;
+ info->insn_info_valid = 1;
+ info->branch_delay_insns = 0;
+ info->data_size = 0;
+ info->insn_type = dis_nonbranch;
+ info->target = 0;
+ info->target2 = 0;
+
+ status = (*info->read_memory_func)(memaddr, buffer, 2, info);
+ if (status != 0) {
+ (*info->memory_error_func)(status, memaddr, info);
+ return -1;
+ }
+
+ if (info->endian == BFD_ENDIAN_BIG) {
+ insn1 = bfd_getb16(buffer);
+ } else {
+ insn1 = bfd_getl16(buffer);
+ }
+ (*info->fprintf_func)(info->stream, "%04x ", insn1);
+
+ /* Handle 32-bit opcodes. */
+ if ((insn1 & 0x1000) == 0) {
+ status = (*info->read_memory_func)(memaddr + 2, buffer, 2, info);
+ if (status != 0) {
+ (*info->memory_error_func)(status, memaddr + 2, info);
+ return -1;
+ }
+
+ if (info->endian == BFD_ENDIAN_BIG) {
+ insn2 = bfd_getb16(buffer);
+ } else {
+ insn2 = bfd_getl16(buffer);
+ }
+ (*info->fprintf_func)(info->stream, "%04x ", insn2);
+ } else {
+ (*info->fprintf_func)(info->stream, " ");
+ }
+ /* Handle 48-bit opcodes. */
+ if ((insn1 >> 10) == 0x18) {
+ status = (*info->read_memory_func)(memaddr + 4, buffer, 2, info);
+ if (status != 0) {
+ (*info->memory_error_func)(status, memaddr + 4, info);
+ return -1;
+ }
+
+ if (info->endian == BFD_ENDIAN_BIG) {
+ insn3 = bfd_getb16(buffer);
+ } else {
+ insn3 = bfd_getl16(buffer);
+ }
+ (*info->fprintf_func)(info->stream, "%04x ", insn3);
+ } else {
+ (*info->fprintf_func)(info->stream, " ");
+ }
+
+ int length = nanomips_dis(buf, memaddr, insn1, insn2, insn3);
+
+ /* FIXME: Should probably use a hash table on the major opcode here. */
+
+ (*info->fprintf_func) (info->stream, "%s", buf);
+ if (length > 0) {
+ return length / 8;
+ }
+
+ info->insn_type = dis_noninsn;
+
+ return insn3 ? 6 : insn2 ? 4 : 2;
+}
+
+
+namespace img
+{
+ address addr32(address a)
+ {
+ return a;
+ }
+
+ std::string format(const char *format, ...)
+ {
+ char buffer[256];
+ va_list args;
+ va_start(args, format);
+ int err = vsprintf(buffer, format, args);
+ if (err < 0) {
+ perror(buffer);
+ }
+ va_end(args);
+ return buffer;
+ }
+
+ std::string format(const char *format,
+ std::string s)
+ {
+ char buffer[256];
+
+ sprintf(buffer, format, s.c_str());
+
+ return buffer;
+ }
+
+ std::string format(const char *format,
+ std::string s1,
+ std::string s2)
+ {
+ char buffer[256];
+
+ sprintf(buffer, format, s1.c_str(), s2.c_str());
+
+ return buffer;
+ }
+
+ std::string format(const char *format,
+ std::string s1,
+ std::string s2,
+ std::string s3)
+ {
+ char buffer[256];
+
+ sprintf(buffer, format, s1.c_str(), s2.c_str(), s3.c_str());
+
+ return buffer;
+ }
+
+ std::string format(const char *format,
+ std::string s1,
+ std::string s2,
+ std::string s3,
+ std::string s4)
+ {
+ char buffer[256];
+
+ sprintf(buffer, format, s1.c_str(), s2.c_str(), s3.c_str(),
+ s4.c_str());
+
+ return buffer;
+ }
+
+ std::string format(const char *format,
+ std::string s1,
+ std::string s2,
+ std::string s3,
+ std::string s4,
+ std::string s5)
+ {
+ char buffer[256];
+
+ sprintf(buffer, format, s1.c_str(), s2.c_str(), s3.c_str(),
+ s4.c_str(), s5.c_str());
+
+ return buffer;
+ }
+
+ std::string format(const char *format,
+ uint64 d,
+ std::string s2)
+ {
+ char buffer[256];
+
+ sprintf(buffer, format, d, s2.c_str());
+
+ return buffer;
+ }
+
+ std::string format(const char *format,
+ std::string s1,
+ uint64 d,
+ std::string s2)
+ {
+ char buffer[256];
+
+ sprintf(buffer, format, s1.c_str(), d, s2.c_str());
+
+ return buffer;
+ }
+
+ std::string format(const char *format,
+ std::string s1,
+ std::string s2,
+ uint64 d)
+ {
+ char buffer[256];
+
+ sprintf(buffer, format, s1.c_str(), s2.c_str(), d);
+
+ return buffer;
+ }
+
+ char as_char(int c)
+ {
+ return static_cast<char>(c);
+ }
+};
+
+
+std::string to_string(img::address a)
+{
+ char buffer[256];
+ sprintf(buffer, "0x%08llx", a);
+ return buffer;
+}
+
+
+uint64 extract_bits(uint64 data, uint32 bit_offset, uint32 bit_size)
+{
+ return (data << (64 - (bit_size + bit_offset))) >> (64 - bit_size);
+}
+
+
+int64 sign_extend(int64 data, int msb)
+{
+ uint64 shift = 63 - msb;
+ return (data << shift) >> shift;
+}
+
+
+uint64 NMD::renumber_registers(uint64 index, uint64 *register_list,
+ size_t register_list_size)
+{
+ if (index < register_list_size) {
+ return register_list[index];
+ }
+
+ throw std::runtime_error(img::format(
+ "Invalid register mapping index %d, size of list = %d",
+ index, register_list_size));
+}
+
+
+/*
+ * these functions should be decode functions but the json does not have
+ * decode sections so they are based on the encode, the equivalent decode
+ * functions need writing eventually.
+ */
+uint64 NMD::encode_gpr3(uint64 d)
+{
+ static uint64 register_list[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
+ return renumber_registers(d, register_list,
+ sizeof(register_list) / sizeof(register_list[0]));
+}
+
+
+uint64 NMD::encode_gpr3_store(uint64 d)
+{
+ static uint64 register_list[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
+ return renumber_registers(d, register_list,
+ sizeof(register_list) / sizeof(register_list[0]));
+}
+
+
+uint64 NMD::encode_rd1_from_rd(uint64 d)
+{
+ static uint64 register_list[] = { 4, 5 };
+ return renumber_registers(d, register_list,
+ sizeof(register_list) / sizeof(register_list[0]));
+}
+
+
+uint64 NMD::encode_gpr4_zero(uint64 d)
+{
+ static uint64 register_list[] = { 8, 9, 10, 0, 4, 5, 6, 7,
+ 16, 17, 18, 19, 20, 21, 22, 23 };
+ return renumber_registers(d, register_list,
+ sizeof(register_list) / sizeof(register_list[0]));
+}
+
+
+uint64 NMD::encode_gpr4(uint64 d)
+{
+ static uint64 register_list[] = { 8, 9, 10, 11, 4, 5, 6, 7,
+ 16, 17, 18, 19, 20, 21, 22, 23 };
+ return renumber_registers(d, register_list,
+ sizeof(register_list) / sizeof(register_list[0]));
+}
+
+
+uint64 NMD::encode_rd2_reg1(uint64 d)
+{
+ static uint64 register_list[] = { 4, 5, 6, 7 };
+ return renumber_registers(d, register_list,
+ sizeof(register_list) / sizeof(register_list[0]));
+}
+
+
+uint64 NMD::encode_rd2_reg2(uint64 d)
+{
+ static uint64 register_list[] = { 5, 6, 7, 8 };
+ return renumber_registers(d, register_list,
+ sizeof(register_list) / sizeof(register_list[0]));
+}
+
+
+uint64 NMD::copy(uint64 d)
+{
+ return d;
+}
+
+
+int64 NMD::copy(int64 d)
+{
+ return d;
+}
+
+
+int64 NMD::neg_copy(uint64 d)
+{
+ return 0ll - d;
+}
+
+
+int64 NMD::neg_copy(int64 d)
+{
+ return -d;
+}
+
+
+/* strange wrapper around gpr3 */
+uint64 NMD::encode_rs3_and_check_rs3_ge_rt3(uint64 d)
+{
+return encode_gpr3(d);
+}
+
+
+/* strange wrapper around gpr3 */
+uint64 NMD::encode_rs3_and_check_rs3_lt_rt3(uint64 d)
+{
+ return encode_gpr3(d);
+}
+
+
+/* nop - done by extraction function */
+uint64 NMD::encode_s_from_address(uint64 d)
+{
+ return d;
+}
+
+
+/* nop - done by extraction function */
+uint64 NMD::encode_u_from_address(uint64 d)
+{
+ return d;
+}
+
+
+/* nop - done by extraction function */
+uint64 NMD::encode_s_from_s_hi(uint64 d)
+{
+ return d;
+}
+
+
+uint64 NMD::encode_count3_from_count(uint64 d)
+{
+ IMGASSERTONCE(d < 8);
+ return d == 0ull ? 8ull : d;
+}
+
+
+uint64 NMD::encode_shift3_from_shift(uint64 d)
+{
+ IMGASSERTONCE(d < 8);
+ return d == 0ull ? 8ull : d;
+}
+
+
+/* special value for load literal */
+int64 NMD::encode_eu_from_s_li16(uint64 d)
+{
+ IMGASSERTONCE(d < 128);
+ return d == 127 ? -1 : (int64)d;
+}
+
+
+uint64 NMD::encode_msbd_from_size(uint64 d)
+{
+ IMGASSERTONCE(d < 32);
+ return d + 1;
+}
+
+
+uint64 NMD::encode_eu_from_u_andi16(uint64 d)
+{
+ IMGASSERTONCE(d < 16);
+ if (d == 12) {
+ return 0x00ffull;
+ }
+ if (d == 13) {
+ return 0xffffull;
+ }
+ return d;
+}
+
+
+uint64 NMD::encode_msbd_from_pos_and_size(uint64 d)
+{
+ IMGASSERTONCE(0);
+ return d;
+}
+
+
+/* save16 / restore16 ???? */
+uint64 NMD::encode_rt1_from_rt(uint64 d)
+{
+ return d ? 31 : 30;
+}
+
+
+/* ? */
+uint64 NMD::encode_lsb_from_pos_and_size(uint64 d)
+{
+ return d;
+}
+
+
+std::string NMD::save_restore_list(uint64 rt, uint64 count, uint64 gp)
+{
+ std::string str;
+
+ for (uint64 counter = 0; counter != count; counter++) {
+ bool use_gp = gp && (counter == count - 1);
+ uint64 this_rt = use_gp ? 28 : ((rt & 0x10) | (rt + counter)) & 0x1f;
+ str += img::format(",%s", GPR(this_rt));
+ }
+
+ return str;
+}
+
+
+std::string NMD::GPR(uint64 reg)
+{
+ static const char *gpr_reg[32] = {
+ "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
+ "a4", "a5", "a6", "a7", "r12", "r13", "r14", "r15",
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+ "r24", "r25", "k0", "k1", "gp", "sp", "fp", "ra"
+ };
+
+ if (reg < 32) {
+ return gpr_reg[reg];
+ }
+
+ throw std::runtime_error(img::format("Invalid GPR register index %d", reg));
+}
+
+
+std::string NMD::FPR(uint64 reg)
+{
+ static const char *fpr_reg[32] = {
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
+ };
+
+ if (reg < 32) {
+ return fpr_reg[reg];
+ }
+
+ throw std::runtime_error(img::format("Invalid FPR register index %d", reg));
+}
+
+
+std::string NMD::AC(uint64 reg)
+{
+ static const char *ac_reg[4] = {
+ "ac0", "ac1", "ac2", "ac3"
+ };
+
+ if (reg < 4) {
+ return ac_reg[reg];
+ }
+
+ throw std::runtime_error(img::format("Invalid AC register index %d", reg));
+}
+
+
+std::string NMD::IMMEDIATE(uint64 value)
+{
+ return img::format("0x%x", value);
+}
+
+
+std::string NMD::IMMEDIATE(int64 value)
+{
+ return img::format("%d", value);
+}
+
+
+std::string NMD::CPR(uint64 reg)
+{
+ /* needs more work */
+ return img::format("CP%d", reg);
+}
+
+
+std::string NMD::ADDRESS(uint64 value, int instruction_size)
+{
+ /* token for string replace */
+ /* const char TOKEN_REPLACE = (char)0xa2; */
+ img::address address = m_pc + value + instruction_size;
+ /* symbol replacement */
+ /* return img::as_char(TOKEN_REPLACE) + to_string(address); */
+ return to_string(address);
+}
+
+
+uint64 NMD::extract_op_code_value(const uint16 * data, int size)
+{
+ switch (size) {
+ case 16:
+ return data[0];
+ case 32:
+ return ((uint64)data[0] << 16) | data[1];
+ case 48:
+ return ((uint64)data[0] << 32) | ((uint64)data[1] << 16) | data[2];
+ default:
+ return data[0];
+ }
+}
+
+
+int NMD::Disassemble(const uint16 * data, std::string & dis,
+ NMD::TABLE_ENTRY_TYPE & type)
+{
+ return Disassemble(data, dis, type, MAJOR, 2);
+}
+
+
+/*
+ * Recurse through tables until the instruction is found then return
+ * the string and size
+ *
+ * inputs:
+ * pointer to a word stream,
+ * disassember table and size
+ * returns:
+ * instruction size - negative is error
+ * disassembly string - on error will constain error string
+ */
+int NMD::Disassemble(const uint16 * data, std::string & dis,
+ NMD::TABLE_ENTRY_TYPE & type, const Pool *table,
+ int table_size)
+{
+ try
+ {
+ for (int i = 0; i < table_size; i++) {
+ uint64 op_code = extract_op_code_value(data,
+ table[i].instructions_size);
+ if ((op_code & table[i].mask) == table[i].value) {
+ /* possible match */
+ conditional_function cond = table[i].condition;
+ if ((cond == 0) || (this->*cond)(op_code)) {
+ try
+ {
+ if (table[i].type == pool) {
+ return Disassemble(data, dis, type,
+ table[i].next_table,
+ table[i].next_table_size);
+ } else if ((table[i].type == instruction) ||
+ (table[i].type == call_instruction) ||
+ (table[i].type == branch_instruction) ||
+ (table[i].type == return_instruction)) {
+ if ((table[i].attributes != 0) &&
+ (m_requested_instruction_categories &
+ table[i].attributes) == 0) {
+ /*
+ * failed due to instruction having
+ * an ASE attribute and the requested version
+ * not having that attribute
+ */
+ dis = "ASE attribute missmatch";
+ return -5;
+ }
+ disassembly_function dis_fn = table[i].disassembly;
+ if (dis_fn == 0) {
+ dis = "disassembler failure - bad table entry";
+ return -6;
+ }
+ type = table[i].type;
+ dis = (this->*dis_fn)(op_code);
+ return table[i].instructions_size;
+ } else {
+ dis = "reserved instruction";
+ return -2;
+ }
+ }
+ catch (std::runtime_error & e)
+ {
+ dis = e.what();
+ return -3; /* runtime error */
+ }
+ }
+ }
+ }
+ }
+ catch (std::exception & e)
+ {
+ dis = e.what();
+ return -4; /* runtime error */
+ }
+
+ dis = "failed to disassemble";
+ return -1; /* failed to disassemble */
+}
+
+
+uint64 NMD::extract_code_18_to_0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 19);
+ return value;
+}
+
+
+uint64 NMD::extract_shift3_2_1_0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 3);
+ return value;
+}
+
+
+uint64 NMD::extr_uil3il3bs9Fmsb11(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 3, 9) << 3;
+ return value;
+}
+
+
+uint64 NMD::extract_count_3_2_1_0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 4);
+ return value;
+}
+
+
+uint64 NMD::extract_rtz3_9_8_7(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 7, 3);
+ return value;
+}
+
+
+uint64 NMD::extr_uil1il1bs17Fmsb17(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 1, 17) << 1;
+ return value;
+}
+
+
+int64 NMD::extr_sil11il0bs10Tmsb9(uint64 instruction)
+{
+ int64 value = 0;
+ value |= extract_bits(instruction, 11, 10);
+ value = sign_extend(value, 9);
+ return value;
+}
+
+
+int64 NMD::extr_sil0il11bs1_il1il1bs10Tmsb11(uint64 instruction)
+{
+ int64 value = 0;
+ value |= extract_bits(instruction, 0, 1) << 11;
+ value |= extract_bits(instruction, 1, 10) << 1;
+ value = sign_extend(value, 11);
+ return value;
+}
+
+
+uint64 NMD::extract_u_10(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 10, 1);
+ return value;
+}
+
+
+uint64 NMD::extract_rtz4_27_26_25_23_22_21(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 21, 3);
+ value |= extract_bits(instruction, 25, 1) << 3;
+ return value;
+}
+
+
+uint64 NMD::extract_sa_15_14_13_12_11(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 11, 5);
+ return value;
+}
+
+
+uint64 NMD::extract_shift_4_3_2_1_0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 5);
+ return value;
+}
+
+
+uint64 NMD::extr_shiftxil7il1bs4Fmsb4(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 7, 4) << 1;
+ return value;
+}
+
+
+uint64 NMD::extract_hint_25_24_23_22_21(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 21, 5);
+ return value;
+}
+
+
+uint64 NMD::extract_count3_14_13_12(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 12, 3);
+ return value;
+}
+
+
+int64 NMD::extr_sil0il31bs1_il2il21bs10_il12il12bs9Tmsb31(uint64 instruction)
+{
+ int64 value = 0;
+ value |= extract_bits(instruction, 0, 1) << 31;
+ value |= extract_bits(instruction, 2, 10) << 21;
+ value |= extract_bits(instruction, 12, 9) << 12;
+ value = sign_extend(value, 31);
+ return value;
+}
+
+
+int64 NMD::extr_sil0il7bs1_il1il1bs6Tmsb7(uint64 instruction)
+{
+ int64 value = 0;
+ value |= extract_bits(instruction, 0, 1) << 7;
+ value |= extract_bits(instruction, 1, 6) << 1;
+ value = sign_extend(value, 7);
+ return value;
+}
+
+
+uint64 NMD::extract_u2_10_9(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 9, 2);
+ return value;
+}
+
+
+uint64 NMD::extract_code_25_24_23_22_21_20_19_18_17_16(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 16, 10);
+ return value;
+}
+
+
+uint64 NMD::extract_rs_20_19_18_17_16(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 16, 5);
+ return value;
+}
+
+
+uint64 NMD::extr_uil1il1bs2Fmsb2(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 1, 2) << 1;
+ return value;
+}
+
+
+uint64 NMD::extract_stripe_6(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 6, 1);
+ return value;
+}
+
+
+uint64 NMD::extr_xil17il0bs1Fmsb0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 17, 1);
+ return value;
+}
+
+
+uint64 NMD::extr_xil2il0bs1_il15il0bs1Fmsb0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 2, 1);
+ value |= extract_bits(instruction, 15, 1);
+ return value;
+}
+
+
+uint64 NMD::extract_ac_13_12(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 14, 2);
+ return value;
+}
+
+
+uint64 NMD::extract_shift_20_19_18_17_16(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 16, 5);
+ return value;
+}
+
+
+uint64 NMD::extract_rdl_25_24(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 24, 1);
+ return value;
+}
+
+
+int64 NMD::extr_sil0il10bs1_il1il1bs9Tmsb10(uint64 instruction)
+{
+ int64 value = 0;
+ value |= extract_bits(instruction, 0, 1) << 10;
+ value |= extract_bits(instruction, 1, 9) << 1;
+ value = sign_extend(value, 10);
+ return value;
+}
+
+
+uint64 NMD::extract_eu_6_5_4_3_2_1_0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 7);
+ return value;
+}
+
+
+uint64 NMD::extract_shift_5_4_3_2_1_0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 6);
+ return value;
+}
+
+
+uint64 NMD::extr_xil10il0bs6Fmsb5(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 10, 6);
+ return value;
+}
+
+
+uint64 NMD::extract_count_19_18_17_16(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 16, 4);
+ return value;
+}
+
+
+uint64 NMD::extract_code_2_1_0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 3);
+ return value;
+}
+
+
+uint64 NMD::extr_xil10il0bs4_il22il0bs4Fmsb3(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 10, 4);
+ value |= extract_bits(instruction, 22, 4);
+ return value;
+}
+
+
+uint64 NMD::extract_u_11_10_9_8_7_6_5_4_3_2_1_0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 12);
+ return value;
+}
+
+
+uint64 NMD::extract_rs_4_3_2_1_0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 5);
+ return value;
+}
+
+
+uint64 NMD::extr_uil3il3bs18Fmsb20(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 3, 18) << 3;
+ return value;
+}
+
+
+uint64 NMD::extr_xil12il0bs1Fmsb0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 12, 1);
+ return value;
+}
+
+
+uint64 NMD::extr_uil0il2bs4Fmsb5(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 4) << 2;
+ return value;
+}
+
+
+uint64 NMD::extract_cofun_25_24_23(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 3, 23);
+ return value;
+}
+
+
+uint64 NMD::extr_uil0il2bs3Fmsb4(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 3) << 2;
+ return value;
+}
+
+
+uint64 NMD::extr_xil10il0bs1Fmsb0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 10, 1);
+ return value;
+}
+
+
+uint64 NMD::extract_rd3_3_2_1(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 1, 3);
+ return value;
+}
+
+
+uint64 NMD::extract_sa_15_14_13_12(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 12, 4);
+ return value;
+}
+
+
+uint64 NMD::extract_rt_25_24_23_22_21(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 21, 5);
+ return value;
+}
+
+
+uint64 NMD::extract_ru_7_6_5_4_3(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 3, 5);
+ return value;
+}
+
+
+uint64 NMD::extr_xil21il0bs5Fmsb4(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 21, 5);
+ return value;
+}
+
+
+uint64 NMD::extr_xil9il0bs3Fmsb2(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 9, 3);
+ return value;
+}
+
+
+uint64 NMD::extract_u_17_to_0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 18);
+ return value;
+}
+
+
+uint64 NMD::extr_xil14il0bs1_il15il0bs1Fmsb0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 14, 1);
+ value |= extract_bits(instruction, 15, 1);
+ return value;
+}
+
+
+uint64 NMD::extract_rsz4_4_2_1_0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 3);
+ value |= extract_bits(instruction, 4, 1) << 3;
+ return value;
+}
+
+
+uint64 NMD::extr_xil24il0bs1Fmsb0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 24, 1);
+ return value;
+}
+
+
+int64 NMD::extr_sil0il21bs1_il1il1bs20Tmsb21(uint64 instruction)
+{
+ int64 value = 0;
+ value |= extract_bits(instruction, 0, 1) << 21;
+ value |= extract_bits(instruction, 1, 20) << 1;
+ value = sign_extend(value, 21);
+ return value;
+}
+
+
+uint64 NMD::extract_op_25_to_3(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 3, 23);
+ return value;
+}
+
+
+uint64 NMD::extract_rs4_4_2_1_0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 3);
+ value |= extract_bits(instruction, 4, 1) << 3;
+ return value;
+}
+
+
+uint64 NMD::extract_bit_23_22_21(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 21, 3);
+ return value;
+}
+
+
+uint64 NMD::extract_rt_41_40_39_38_37(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 37, 5);
+ return value;
+}
+
+
+int64 NMD::extract_shift_21_20_19_18_17_16(uint64 instruction)
+{
+ int64 value = 0;
+ value |= extract_bits(instruction, 16, 6);
+ value = sign_extend(value, 5);
+ return value;
+}
+
+
+uint64 NMD::extr_xil6il0bs3_il10il0bs1Fmsb2(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 6, 3);
+ value |= extract_bits(instruction, 10, 1);
+ return value;
+}
+
+
+uint64 NMD::extract_rd2_3_8(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 3, 1) << 1;
+ value |= extract_bits(instruction, 8, 1);
+ return value;
+}
+
+
+uint64 NMD::extr_xil16il0bs5Fmsb4(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 16, 5);
+ return value;
+}
+
+
+uint64 NMD::extract_code_17_to_0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 18);
+ return value;
+}
+
+
+uint64 NMD::extr_xil0il0bs12Fmsb11(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 12);
+ return value;
+}
+
+
+uint64 NMD::extract_size_20_19_18_17_16(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 16, 5);
+ return value;
+}
+
+
+int64 NMD::extr_sil2il2bs6_il15il8bs1Tmsb8(uint64 instruction)
+{
+ int64 value = 0;
+ value |= extract_bits(instruction, 2, 6) << 2;
+ value |= extract_bits(instruction, 15, 1) << 8;
+ value = sign_extend(value, 8);
+ return value;
+}
+
+
+uint64 NMD::extract_u_15_to_0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 16);
+ return value;
+}
+
+
+uint64 NMD::extract_fs_15_14_13_12_11(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 16, 5);
+ return value;
+}
+
+
+int64 NMD::extr_sil0il0bs8_il15il8bs1Tmsb8(uint64 instruction)
+{
+ int64 value = 0;
+ value |= extract_bits(instruction, 0, 8);
+ value |= extract_bits(instruction, 15, 1) << 8;
+ value = sign_extend(value, 8);
+ return value;
+}
+
+
+uint64 NMD::extract_stype_20_19_18_17_16(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 16, 5);
+ return value;
+}
+
+
+uint64 NMD::extract_rtl_11(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 9, 1);
+ return value;
+}
+
+
+uint64 NMD::extract_hs_20_19_18_17_16(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 16, 5);
+ return value;
+}
+
+
+uint64 NMD::extr_xil10il0bs1_il14il0bs2Fmsb1(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 10, 1);
+ value |= extract_bits(instruction, 14, 2);
+ return value;
+}
+
+
+uint64 NMD::extract_sel_13_12_11(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 11, 3);
+ return value;
+}
+
+
+uint64 NMD::extract_lsb_4_3_2_1_0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 5);
+ return value;
+}
+
+
+uint64 NMD::extr_xil14il0bs2Fmsb1(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 14, 2);
+ return value;
+}
+
+
+uint64 NMD::extract_gp_2(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 2, 1);
+ return value;
+}
+
+
+uint64 NMD::extract_rt3_9_8_7(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 7, 3);
+ return value;
+}
+
+
+uint64 NMD::extract_ft_20_19_18_17_16(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 21, 5);
+ return value;
+}
+
+
+uint64 NMD::extract_u_17_16_15_14_13_12_11(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 11, 7);
+ return value;
+}
+
+
+uint64 NMD::extract_cs_20_19_18_17_16(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 16, 5);
+ return value;
+}
+
+
+uint64 NMD::extr_xil16il0bs10Fmsb9(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 16, 10);
+ return value;
+}
+
+
+uint64 NMD::extract_rt4_9_7_6_5(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 5, 3);
+ value |= extract_bits(instruction, 9, 1) << 3;
+ return value;
+}
+
+
+uint64 NMD::extract_msbt_10_9_8_7_6(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 6, 5);
+ return value;
+}
+
+
+uint64 NMD::extr_uil0il2bs6Fmsb7(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 6) << 2;
+ return value;
+}
+
+
+uint64 NMD::extr_xil17il0bs9Fmsb8(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 17, 9);
+ return value;
+}
+
+
+uint64 NMD::extract_sa_15_14_13(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 13, 3);
+ return value;
+}
+
+
+int64 NMD::extr_sil0il14bs1_il1il1bs13Tmsb14(uint64 instruction)
+{
+ int64 value = 0;
+ value |= extract_bits(instruction, 0, 1) << 14;
+ value |= extract_bits(instruction, 1, 13) << 1;
+ value = sign_extend(value, 14);
+ return value;
+}
+
+
+uint64 NMD::extract_rs3_6_5_4(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 4, 3);
+ return value;
+}
+
+
+uint64 NMD::extr_uil0il32bs32Fmsb63(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 32) << 32;
+ return value;
+}
+
+
+uint64 NMD::extract_shift_10_9_8_7_6(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 6, 5);
+ return value;
+}
+
+
+uint64 NMD::extract_cs_25_24_23_22_21(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 21, 5);
+ return value;
+}
+
+
+uint64 NMD::extract_shiftx_11_10_9_8_7_6(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 6, 6);
+ return value;
+}
+
+
+uint64 NMD::extract_rt_9_8_7_6_5(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 5, 5);
+ return value;
+}
+
+
+uint64 NMD::extract_op_25_24_23_22_21(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 21, 5);
+ return value;
+}
+
+
+uint64 NMD::extr_uil0il2bs7Fmsb8(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 7) << 2;
+ return value;
+}
+
+
+uint64 NMD::extract_bit_16_15_14_13_12_11(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 11, 6);
+ return value;
+}
+
+
+uint64 NMD::extr_xil10il0bs1_il11il0bs5Fmsb4(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 10, 1);
+ value |= extract_bits(instruction, 11, 5);
+ return value;
+}
+
+
+uint64 NMD::extract_mask_20_19_18_17_16_15_14(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 14, 7);
+ return value;
+}
+
+
+uint64 NMD::extract_eu_3_2_1_0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 4);
+ return value;
+}
+
+
+uint64 NMD::extr_uil4il4bs4Fmsb7(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 4, 4) << 4;
+ return value;
+}
+
+
+int64 NMD::extr_sil3il3bs5_il15il8bs1Tmsb8(uint64 instruction)
+{
+ int64 value = 0;
+ value |= extract_bits(instruction, 3, 5) << 3;
+ value |= extract_bits(instruction, 15, 1) << 8;
+ value = sign_extend(value, 8);
+ return value;
+}
+
+
+uint64 NMD::extract_ft_15_14_13_12_11(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 11, 5);
+ return value;
+}
+
+
+int64 NMD::extr_sil0il16bs16_il16il0bs16Tmsb31(uint64 instruction)
+{
+ int64 value = 0;
+ value |= extract_bits(instruction, 0, 16) << 16;
+ value |= extract_bits(instruction, 16, 16);
+ value = sign_extend(value, 31);
+ return value;
+}
+
+
+uint64 NMD::extract_u_20_19_18_17_16_15_14_13(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 13, 8);
+ return value;
+}
+
+
+uint64 NMD::extr_xil15il0bs1Fmsb0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 15, 1);
+ return value;
+}
+
+
+uint64 NMD::extr_xil11il0bs5Fmsb4(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 11, 5);
+ return value;
+}
+
+
+uint64 NMD::extr_uil2il2bs16Fmsb17(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 2, 16) << 2;
+ return value;
+}
+
+
+uint64 NMD::extract_rd_20_19_18_17_16(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 11, 5);
+ return value;
+}
+
+
+uint64 NMD::extract_c0s_20_19_18_17_16(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 16, 5);
+ return value;
+}
+
+
+uint64 NMD::extract_code_1_0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 2);
+ return value;
+}
+
+
+int64 NMD::extr_sil0il25bs1_il1il1bs24Tmsb25(uint64 instruction)
+{
+ int64 value = 0;
+ value |= extract_bits(instruction, 0, 1) << 25;
+ value |= extract_bits(instruction, 1, 24) << 1;
+ value = sign_extend(value, 25);
+ return value;
+}
+
+
+uint64 NMD::extr_xil0il0bs3_il4il0bs1Fmsb2(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 3);
+ value |= extract_bits(instruction, 4, 1);
+ return value;
+}
+
+
+uint64 NMD::extract_u_1_0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 2);
+ return value;
+}
+
+
+uint64 NMD::extr_uil3il3bs1_il8il2bs1Fmsb3(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 3, 1) << 3;
+ value |= extract_bits(instruction, 8, 1) << 2;
+ return value;
+}
+
+
+uint64 NMD::extr_xil9il0bs3_il16il0bs5Fmsb4(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 9, 3);
+ value |= extract_bits(instruction, 16, 5);
+ return value;
+}
+
+
+uint64 NMD::extract_fd_10_9_8_7_6(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 11, 5);
+ return value;
+}
+
+
+uint64 NMD::extr_xil6il0bs3Fmsb2(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 6, 3);
+ return value;
+}
+
+
+uint64 NMD::extr_uil0il2bs5Fmsb6(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 5) << 2;
+ return value;
+}
+
+
+uint64 NMD::extract_rtz4_9_7_6_5(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 5, 3);
+ value |= extract_bits(instruction, 9, 1) << 3;
+ return value;
+}
+
+
+uint64 NMD::extract_sel_15_14_13_12_11(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 11, 5);
+ return value;
+}
+
+
+uint64 NMD::extract_ct_25_24_23_22_21(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 21, 5);
+ return value;
+}
+
+
+uint64 NMD::extr_xil11il0bs1Fmsb0(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 11, 1);
+ return value;
+}
+
+
+uint64 NMD::extr_uil2il2bs19Fmsb20(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 2, 19) << 2;
+ return value;
+}
+
+
+int64 NMD::extract_s_4_2_1_0(uint64 instruction)
+{
+ int64 value = 0;
+ value |= extract_bits(instruction, 0, 3);
+ value |= extract_bits(instruction, 4, 1) << 3;
+ value = sign_extend(value, 3);
+ return value;
+}
+
+
+uint64 NMD::extr_uil0il1bs4Fmsb4(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 0, 4) << 1;
+ return value;
+}
+
+
+uint64 NMD::extr_xil9il0bs2Fmsb1(uint64 instruction)
+{
+ uint64 value = 0;
+ value |= extract_bits(instruction, 9, 2);
+ return value;
+}
+
+
+
+bool NMD::ADDIU_32__cond(uint64 instruction)
+{
+ uint64 rt = extract_rt_25_24_23_22_21(instruction);
+ return rt != 0;
+}
+
+
+bool NMD::ADDIU_RS5__cond(uint64 instruction)
+{
+ uint64 rt = extract_rt_9_8_7_6_5(instruction);
+ return rt != 0;
+}
+
+
+bool NMD::BALRSC_cond(uint64 instruction)
+{
+ uint64 rt = extract_rt_25_24_23_22_21(instruction);
+ return rt != 0;
+}
+
+
+bool NMD::BEQC_16__cond(uint64 instruction)
+{
+ uint64 rs3 = extract_rs3_6_5_4(instruction);
+ uint64 rt3 = extract_rt3_9_8_7(instruction);
+ uint64 u = extr_uil0il1bs4Fmsb4(instruction);
+ return rs3 < rt3 && u != 0;
+}
+
+
+bool NMD::BNEC_16__cond(uint64 instruction)
+{
+ uint64 rs3 = extract_rs3_6_5_4(instruction);
+ uint64 rt3 = extract_rt3_9_8_7(instruction);
+ uint64 u = extr_uil0il1bs4Fmsb4(instruction);
+ return rs3 >= rt3 && u != 0;
+}
+
+
+bool NMD::MOVE_cond(uint64 instruction)
+{
+ uint64 rt = extract_rt_9_8_7_6_5(instruction);
+ return rt != 0;
+}
+
+
+bool NMD::P16_BR1_cond(uint64 instruction)
+{
+ uint64 u = extr_uil0il1bs4Fmsb4(instruction);
+ return u != 0;
+}
+
+
+bool NMD::PREF_S9__cond(uint64 instruction)
+{
+ uint64 hint = extract_hint_25_24_23_22_21(instruction);
+ return hint != 31;
+}
+
+
+bool NMD::PREFE_cond(uint64 instruction)
+{
+ uint64 hint = extract_hint_25_24_23_22_21(instruction);
+ return hint != 31;
+}
+
+
+bool NMD::SLTU_cond(uint64 instruction)
+{
+ uint64 rd = extract_rd_20_19_18_17_16(instruction);
+ return rd != 0;
+}
+
+
+
+/*
+ * ABS.D fd, fs - Floating Point Absolute Value
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 010001 00000 000101
+ * fmt -----
+ * fs -----
+ * fd -----
+ */
+std::string NMD::ABS_D(uint64 instruction)
+{
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 fd_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fs = FPR(copy(fs_value));
+ std::string fd = FPR(copy(fd_value));
+
+ return img::format("ABS.D %s, %s", fd, fs);
+}
+
+
+/*
+ * ABS.S fd, fs - Floating Point Absolute Value
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 010001 00000 000101
+ * fmt -----
+ * fd -----
+ * fs -----
+ */
+std::string NMD::ABS_S(uint64 instruction)
+{
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 fd_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fs = FPR(copy(fs_value));
+ std::string fd = FPR(copy(fd_value));
+
+ return img::format("ABS.S %s, %s", fd, fs);
+}
+
+
+/*
+ * ABSQ_S.PH rt, rs - Find Absolute Value of Two Fractional Halfwords
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 0001000100111111
+ * rt -----
+ * rs -----
+ */
+std::string NMD::ABSQ_S_PH(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string rs = GPR(copy(rs_value));
+
+ return img::format("ABSQ_S.PH %s, %s", rt, rs);
+}
+
+
+/*
+ * ABSQ_S.QB rt, rs - Find Absolute Value of Four Fractional Byte Values
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 0000000100111111
+ * rt -----
+ * rs -----
+ */
+std::string NMD::ABSQ_S_QB(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string rs = GPR(copy(rs_value));
+
+ return img::format("ABSQ_S.QB %s, %s", rt, rs);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 0010000100111111
+ * rt -----
+ * rs -----
+ */
+std::string NMD::ABSQ_S_W(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string rs = GPR(copy(rs_value));
+
+ return img::format("ABSQ_S.W %s, %s", rt, rs);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 0010000100111111
+ * rt -----
+ * rs -----
+ */
+std::string NMD::ACLR(uint64 instruction)
+{
+ uint64 bit_value = extract_bit_23_22_21(instruction);
+ int64 s_value = extr_sil0il0bs8_il15il8bs1Tmsb8(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string bit = IMMEDIATE(copy(bit_value));
+ std::string s = IMMEDIATE(copy(s_value));
+ std::string rs = GPR(copy(rs_value));
+
+ return img::format("ACLR %s, %s(%s)", bit, s, rs);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 0010000100111111
+ * rt -----
+ * rs -----
+ */
+std::string NMD::ADD(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("ADD %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ * ADD.D fd, fs, ft - Floating Point Add
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 010001 000101
+ * fmt -----
+ * ft -----
+ * fs -----
+ * fd -----
+ */
+std::string NMD::ADD_D(uint64 instruction)
+{
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+
+ std::string ft = FPR(copy(ft_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string fd = FPR(copy(fd_value));
+
+ return img::format("ADD.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ * ADD.S fd, fs, ft - Floating Point Add
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 010001 000101
+ * fmt -----
+ * ft -----
+ * fs -----
+ * fd -----
+ */
+std::string NMD::ADD_S(uint64 instruction)
+{
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+
+ std::string ft = FPR(copy(ft_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string fd = FPR(copy(fd_value));
+
+ return img::format("ADD.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 0010000100111111
+ * rt -----
+ * rs -----
+ */
+std::string NMD::ADDIU_32_(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 u_value = extract_u_15_to_0(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string u = IMMEDIATE(copy(u_value));
+
+ return img::format("ADDIU %s, %s, %s", rt, rs, u);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 0010000100111111
+ * rt -----
+ * rs -----
+ */
+std::string NMD::ADDIU_48_(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_41_40_39_38_37(instruction);
+ int64 s_value = extr_sil0il16bs16_il16il0bs16Tmsb31(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string s = IMMEDIATE(copy(s_value));
+
+ return img::format("ADDIU %s, %s", rt, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 0010000100111111
+ * rt -----
+ * rs -----
+ */
+std::string NMD::ADDIU_GP48_(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_41_40_39_38_37(instruction);
+ int64 s_value = extr_sil0il16bs16_il16il0bs16Tmsb31(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string s = IMMEDIATE(copy(s_value));
+
+ return img::format("ADDIU %s, $%d, %s", rt, 28, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 0010000100111111
+ * rt -----
+ * rs -----
+ */
+std::string NMD::ADDIU_GP_B_(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 u_value = extract_u_17_to_0(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string u = IMMEDIATE(copy(u_value));
+
+ return img::format("ADDIU %s, $%d, %s", rt, 28, u);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 0010000100111111
+ * rt -----
+ * rs -----
+ */
+std::string NMD::ADDIU_GP_W_(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 u_value = extr_uil2il2bs19Fmsb20(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string u = IMMEDIATE(copy(u_value));
+
+ return img::format("ADDIU %s, $%d, %s", rt, 28, u);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 0010000100111111
+ * rt -----
+ * rs -----
+ */
+std::string NMD::ADDIU_NEG_(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 u_value = extract_u_11_10_9_8_7_6_5_4_3_2_1_0(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string u = IMMEDIATE(neg_copy(u_value));
+
+ return img::format("ADDIU %s, %s, %s", rt, rs, u);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 0010000100111111
+ * rt -----
+ * rs -----
+ */
+std::string NMD::ADDIU_R1_SP_(uint64 instruction)
+{
+ uint64 u_value = extr_uil0il2bs6Fmsb7(instruction);
+ uint64 rt3_value = extract_rt3_9_8_7(instruction);
+
+ std::string rt3 = GPR(encode_gpr3(rt3_value));
+ std::string u = IMMEDIATE(copy(u_value));
+
+ return img::format("ADDIU %s, $%d, %s", rt3, 29, u);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 0010000100111111
+ * rt -----
+ * rs -----
+ */
+std::string NMD::ADDIU_R2_(uint64 instruction)
+{
+ uint64 u_value = extr_uil0il2bs3Fmsb4(instruction);
+ uint64 rt3_value = extract_rt3_9_8_7(instruction);
+ uint64 rs3_value = extract_rs3_6_5_4(instruction);
+
+ std::string rt3 = GPR(encode_gpr3(rt3_value));
+ std::string rs3 = GPR(encode_gpr3(rs3_value));
+ std::string u = IMMEDIATE(copy(u_value));
+
+ return img::format("ADDIU %s, %s, %s", rt3, rs3, u);
+}
+
+
+/*
+ * ADDIU[RS5] rt, s5 - Add Signed Word and Set Carry Bit
+ *
+ * 5432109876543210
+ * 100100 1
+ * rt -----
+ * s - ---
+ */
+std::string NMD::ADDIU_RS5_(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_9_8_7_6_5(instruction);
+ int64 s_value = extract_s_4_2_1_0(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string s = IMMEDIATE(copy(s_value));
+
+ return img::format("ADDIU %s, %s", rt, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::ADDIUPC_32_(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ int64 s_value = extr_sil0il21bs1_il1il1bs20Tmsb21(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("ADDIUPC %s, %s", rt, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::ADDIUPC_48_(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_41_40_39_38_37(instruction);
+ int64 s_value = extr_sil0il16bs16_il16il0bs16Tmsb31(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 6);
+
+ return img::format("ADDIUPC %s, %s", rt, s);
+}
+
+
+/*
+ * ADDQ.PH rd, rt, rs - Add Fractional Halfword Vectors
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 00000001101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::ADDQ_PH(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("ADDQ.PH %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ * ADDQ_S.PH rd, rt, rs - Add Fractional Halfword Vectors
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 10000001101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::ADDQ_S_PH(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("ADDQ_S.PH %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ * ADDQ_S.W rd, rt, rs - Add Fractional Words
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1100000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::ADDQ_S_W(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("ADDQ_S.W %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ * ADDQH.PH rd, rt, rs - Add Fractional Halfword Vectors And Shift Right
+ * to Halve Results
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 00001001101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::ADDQH_PH(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("ADDQH.PH %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ * ADDQH_R.PH rd, rt, rs - Add Fractional Halfword Vectors And Shift Right
+ * to Halve Results
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 10001001101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::ADDQH_R_PH(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("ADDQH_R.PH %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ * ADDQH_R.W rd, rt, rs - Add Fractional Words And Shift Right to Halve Results
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 00010001101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::ADDQH_R_W(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("ADDQH_R.W %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ * ADDQH.W rd, rt, rs - Add Fractional Words And Shift Right to Halve Results
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 10010001101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::ADDQH_W(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("ADDQH.W %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ * ADDSC rd, rt, rs - Add Signed Word and Set Carry Bit
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::ADDSC(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("ADDSC %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ * ADDU[16] rd3, rs3, rt3 -
+ *
+ * 5432109876543210
+ * 101100 0
+ * rt3 ---
+ * rs3 ---
+ * rd3 ---
+ */
+std::string NMD::ADDU_16_(uint64 instruction)
+{
+ uint64 rt3_value = extract_rt3_9_8_7(instruction);
+ uint64 rs3_value = extract_rs3_6_5_4(instruction);
+ uint64 rd3_value = extract_rd3_3_2_1(instruction);
+
+ std::string rt3 = GPR(encode_gpr3(rt3_value));
+ std::string rs3 = GPR(encode_gpr3(rs3_value));
+ std::string rd3 = GPR(encode_gpr3(rd3_value));
+
+ return img::format("ADDU %s, %s, %s", rd3, rs3, rt3);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::ADDU_32_(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("ADDU %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::ADDU_4X4_(uint64 instruction)
+{
+ uint64 rs4_value = extract_rs4_4_2_1_0(instruction);
+ uint64 rt4_value = extract_rt4_9_7_6_5(instruction);
+
+ std::string rs4 = GPR(encode_gpr4(rs4_value));
+ std::string rt4 = GPR(encode_gpr4(rt4_value));
+
+ return img::format("ADDU %s, %s", rs4, rt4);
+}
+
+
+/*
+ * ADDU.PH rd, rt, rs - Unsigned Add Integer Halfwords
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 00100001101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::ADDU_PH(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("ADDU.PH %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ * ADDU.QB rd, rt, rs - Unsigned Add Quad Byte Vectors
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 00011001101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::ADDU_QB(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("ADDU.QB %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ * ADDU_S.PH rd, rt, rs - Unsigned Add Integer Halfwords
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 10100001101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::ADDU_S_PH(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("ADDU_S.PH %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ * ADDU_S.QB rd, rt, rs - Unsigned Add Quad Byte Vectors
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 10011001101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::ADDU_S_QB(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("ADDU_S.QB %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ * ADDUH.QB rd, rt, rs - Unsigned Add Vector Quad-Bytes And Right Shift
+ * to Halve Results
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 00101001101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::ADDUH_QB(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("ADDUH.QB %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ * ADDUH_R.QB rd, rt, rs - Unsigned Add Vector Quad-Bytes And Right Shift
+ * to Halve Results
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 10101001101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::ADDUH_R_QB(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("ADDUH_R.QB %s, %s, %s", rd, rs, rt);
+}
+
+/*
+ * ADDWC rd, rt, rs - Add Word with Carry Bit
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1111000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::ADDWC(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("ADDWC %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::ALUIPC(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ int64 s_value = extr_sil0il31bs1_il2il21bs10_il12il12bs9Tmsb31(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("ALUIPC %s, %%pcrel_hi(%s)", rt, s);
+}
+
+
+/*
+ * AND[16] rt3, rs3 -
+ *
+ * 5432109876543210
+ * 101100
+ * rt3 ---
+ * rs3 ---
+ * eu ----
+ */
+std::string NMD::AND_16_(uint64 instruction)
+{
+ uint64 rt3_value = extract_rt3_9_8_7(instruction);
+ uint64 rs3_value = extract_rs3_6_5_4(instruction);
+
+ std::string rt3 = GPR(encode_gpr3(rt3_value));
+ std::string rs3 = GPR(encode_gpr3(rs3_value));
+
+ return img::format("AND %s, %s", rs3, rt3);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::AND_32_(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("AND %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ * ANDI rt, rs, u -
+ *
+ * 5432109876543210
+ * 101100
+ * rt3 ---
+ * rs3 ---
+ * eu ----
+ */
+std::string NMD::ANDI_16_(uint64 instruction)
+{
+ uint64 rt3_value = extract_rt3_9_8_7(instruction);
+ uint64 rs3_value = extract_rs3_6_5_4(instruction);
+ uint64 eu_value = extract_eu_3_2_1_0(instruction);
+
+ std::string rt3 = GPR(encode_gpr3(rt3_value));
+ std::string rs3 = GPR(encode_gpr3(rs3_value));
+ std::string eu = IMMEDIATE(encode_eu_from_u_andi16(eu_value));
+
+ return img::format("ANDI %s, %s, %s", rt3, rs3, eu);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::ANDI_32_(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 u_value = extract_u_11_10_9_8_7_6_5_4_3_2_1_0(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string u = IMMEDIATE(copy(u_value));
+
+ return img::format("ANDI %s, %s, %s", rt, rs, u);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::APPEND(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 sa_value = extract_sa_15_14_13_12_11(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string sa = IMMEDIATE(copy(sa_value));
+
+ return img::format("APPEND %s, %s, %s", rt, rs, sa);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::ASET(uint64 instruction)
+{
+ uint64 bit_value = extract_bit_23_22_21(instruction);
+ int64 s_value = extr_sil0il0bs8_il15il8bs1Tmsb8(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string bit = IMMEDIATE(copy(bit_value));
+ std::string s = IMMEDIATE(copy(s_value));
+ std::string rs = GPR(copy(rs_value));
+
+ return img::format("ASET %s, %s(%s)", bit, s, rs);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BALC_16_(uint64 instruction)
+{
+ int64 s_value = extr_sil0il10bs1_il1il1bs9Tmsb10(instruction);
+
+ std::string s = ADDRESS(encode_s_from_address(s_value), 2);
+
+ return img::format("BALC %s", s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BALC_32_(uint64 instruction)
+{
+ int64 s_value = extr_sil0il25bs1_il1il1bs24Tmsb25(instruction);
+
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("BALC %s", s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BALRSC(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string rs = GPR(copy(rs_value));
+
+ return img::format("BALRSC %s, %s", rt, rs);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BBEQZC(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 bit_value = extract_bit_16_15_14_13_12_11(instruction);
+ int64 s_value = extr_sil0il11bs1_il1il1bs10Tmsb11(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string bit = IMMEDIATE(copy(bit_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("BBEQZC %s, %s, %s", rt, bit, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BBNEZC(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 bit_value = extract_bit_16_15_14_13_12_11(instruction);
+ int64 s_value = extr_sil0il11bs1_il1il1bs10Tmsb11(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string bit = IMMEDIATE(copy(bit_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("BBNEZC %s, %s, %s", rt, bit, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BC_16_(uint64 instruction)
+{
+ int64 s_value = extr_sil0il10bs1_il1il1bs9Tmsb10(instruction);
+
+ std::string s = ADDRESS(encode_s_from_address(s_value), 2);
+
+ return img::format("BC %s", s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BC_32_(uint64 instruction)
+{
+ int64 s_value = extr_sil0il25bs1_il1il1bs24Tmsb25(instruction);
+
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("BC %s", s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BC1EQZC(uint64 instruction)
+{
+ int64 s_value = extr_sil0il14bs1_il1il1bs13Tmsb14(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string ft = FPR(copy(ft_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("BC1EQZC %s, %s", ft, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BC1NEZC(uint64 instruction)
+{
+ int64 s_value = extr_sil0il14bs1_il1il1bs13Tmsb14(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string ft = FPR(copy(ft_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("BC1NEZC %s, %s", ft, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BC2EQZC(uint64 instruction)
+{
+ int64 s_value = extr_sil0il14bs1_il1il1bs13Tmsb14(instruction);
+ uint64 ct_value = extract_ct_25_24_23_22_21(instruction);
+
+ std::string ct = CPR(copy(ct_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("BC2EQZC %s, %s", ct, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BC2NEZC(uint64 instruction)
+{
+ int64 s_value = extr_sil0il14bs1_il1il1bs13Tmsb14(instruction);
+ uint64 ct_value = extract_ct_25_24_23_22_21(instruction);
+
+ std::string ct = CPR(copy(ct_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("BC2NEZC %s, %s", ct, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BEQC_16_(uint64 instruction)
+{
+ uint64 u_value = extr_uil0il1bs4Fmsb4(instruction);
+ uint64 rt3_value = extract_rt3_9_8_7(instruction);
+ uint64 rs3_value = extract_rs3_6_5_4(instruction);
+
+ std::string rs3 = GPR(encode_rs3_and_check_rs3_lt_rt3(rs3_value));
+ std::string rt3 = GPR(encode_gpr3(rt3_value));
+ std::string u = ADDRESS(encode_u_from_address(u_value), 2);
+
+ return img::format("BEQC %s, %s, %s", rs3, rt3, u);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BEQC_32_(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ int64 s_value = extr_sil0il14bs1_il1il1bs13Tmsb14(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("BEQC %s, %s, %s", rs, rt, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BEQIC(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ int64 s_value = extr_sil0il11bs1_il1il1bs10Tmsb11(instruction);
+ uint64 u_value = extract_u_17_16_15_14_13_12_11(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string u = IMMEDIATE(copy(u_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("BEQIC %s, %s, %s", rt, u, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BEQZC_16_(uint64 instruction)
+{
+ int64 s_value = extr_sil0il7bs1_il1il1bs6Tmsb7(instruction);
+ uint64 rt3_value = extract_rt3_9_8_7(instruction);
+
+ std::string rt3 = GPR(encode_gpr3(rt3_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 2);
+
+ return img::format("BEQZC %s, %s", rt3, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BGEC(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ int64 s_value = extr_sil0il14bs1_il1il1bs13Tmsb14(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("BGEC %s, %s, %s", rs, rt, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BGEIC(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ int64 s_value = extr_sil0il11bs1_il1il1bs10Tmsb11(instruction);
+ uint64 u_value = extract_u_17_16_15_14_13_12_11(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string u = IMMEDIATE(copy(u_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("BGEIC %s, %s, %s", rt, u, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BGEIUC(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ int64 s_value = extr_sil0il11bs1_il1il1bs10Tmsb11(instruction);
+ uint64 u_value = extract_u_17_16_15_14_13_12_11(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string u = IMMEDIATE(copy(u_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("BGEIUC %s, %s, %s", rt, u, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BGEUC(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ int64 s_value = extr_sil0il14bs1_il1il1bs13Tmsb14(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("BGEUC %s, %s, %s", rs, rt, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BLTC(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ int64 s_value = extr_sil0il14bs1_il1il1bs13Tmsb14(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("BLTC %s, %s, %s", rs, rt, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BLTIC(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ int64 s_value = extr_sil0il11bs1_il1il1bs10Tmsb11(instruction);
+ uint64 u_value = extract_u_17_16_15_14_13_12_11(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string u = IMMEDIATE(copy(u_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("BLTIC %s, %s, %s", rt, u, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BLTIUC(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ int64 s_value = extr_sil0il11bs1_il1il1bs10Tmsb11(instruction);
+ uint64 u_value = extract_u_17_16_15_14_13_12_11(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string u = IMMEDIATE(copy(u_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("BLTIUC %s, %s, %s", rt, u, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BLTUC(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ int64 s_value = extr_sil0il14bs1_il1il1bs13Tmsb14(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("BLTUC %s, %s, %s", rs, rt, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BNEC_16_(uint64 instruction)
+{
+ uint64 u_value = extr_uil0il1bs4Fmsb4(instruction);
+ uint64 rt3_value = extract_rt3_9_8_7(instruction);
+ uint64 rs3_value = extract_rs3_6_5_4(instruction);
+
+ std::string rs3 = GPR(encode_rs3_and_check_rs3_ge_rt3(rs3_value));
+ std::string rt3 = GPR(encode_gpr3(rt3_value));
+ std::string u = ADDRESS(encode_u_from_address(u_value), 2);
+
+ return img::format("BNEC %s, %s, %s", rs3, rt3, u);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BNEC_32_(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ int64 s_value = extr_sil0il14bs1_il1il1bs13Tmsb14(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("BNEC %s, %s, %s", rs, rt, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BNEIC(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ int64 s_value = extr_sil0il11bs1_il1il1bs10Tmsb11(instruction);
+ uint64 u_value = extract_u_17_16_15_14_13_12_11(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string u = IMMEDIATE(copy(u_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("BNEIC %s, %s, %s", rt, u, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BNEZC_16_(uint64 instruction)
+{
+ int64 s_value = extr_sil0il7bs1_il1il1bs6Tmsb7(instruction);
+ uint64 rt3_value = extract_rt3_9_8_7(instruction);
+
+ std::string rt3 = GPR(encode_gpr3(rt3_value));
+ std::string s = ADDRESS(encode_s_from_address(s_value), 2);
+
+ return img::format("BNEZC %s, %s", rt3, s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BPOSGE32C(uint64 instruction)
+{
+ int64 s_value = extr_sil0il14bs1_il1il1bs13Tmsb14(instruction);
+
+ std::string s = ADDRESS(encode_s_from_address(s_value), 4);
+
+ return img::format("BPOSGE32C %s", s);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BREAK_16_(uint64 instruction)
+{
+ uint64 code_value = extract_code_2_1_0(instruction);
+
+ std::string code = IMMEDIATE(copy(code_value));
+
+ return img::format("BREAK %s", code);
+}
+
+
+/*
+ * BREAK code - Break. Cause a Breakpoint exception
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BREAK_32_(uint64 instruction)
+{
+ uint64 code_value = extract_code_18_to_0(instruction);
+
+ std::string code = IMMEDIATE(copy(code_value));
+
+ return img::format("BREAK %s", code);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::BRSC(uint64 instruction)
+{
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rs = GPR(copy(rs_value));
+
+ return img::format("BRSC %s", rs);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CACHE(uint64 instruction)
+{
+ int64 s_value = extr_sil0il0bs8_il15il8bs1Tmsb8(instruction);
+ uint64 op_value = extract_op_25_24_23_22_21(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string op = IMMEDIATE(copy(op_value));
+ std::string s = IMMEDIATE(copy(s_value));
+ std::string rs = GPR(copy(rs_value));
+
+ return img::format("CACHE %s, %s(%s)", op, s, rs);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CACHEE(uint64 instruction)
+{
+ int64 s_value = extr_sil0il0bs8_il15il8bs1Tmsb8(instruction);
+ uint64 op_value = extract_op_25_24_23_22_21(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string op = IMMEDIATE(copy(op_value));
+ std::string s = IMMEDIATE(copy(s_value));
+ std::string rs = GPR(copy(rs_value));
+
+ return img::format("CACHEE %s, %s(%s)", op, s, rs);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CEIL_L_D(uint64 instruction)
+{
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string ft = FPR(copy(ft_value));
+ std::string fs = FPR(copy(fs_value));
+
+ return img::format("CEIL.L.D %s, %s", ft, fs);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CEIL_L_S(uint64 instruction)
+{
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string ft = FPR(copy(ft_value));
+ std::string fs = FPR(copy(fs_value));
+
+ return img::format("CEIL.L.S %s, %s", ft, fs);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CEIL_W_D(uint64 instruction)
+{
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string ft = FPR(copy(ft_value));
+ std::string fs = FPR(copy(fs_value));
+
+ return img::format("CEIL.W.D %s, %s", ft, fs);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CEIL_W_S(uint64 instruction)
+{
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string ft = FPR(copy(ft_value));
+ std::string fs = FPR(copy(fs_value));
+
+ return img::format("CEIL.W.S %s, %s", ft, fs);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CFC1(uint64 instruction)
+{
+ uint64 cs_value = extract_cs_20_19_18_17_16(instruction);
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string cs = CPR(copy(cs_value));
+
+ return img::format("CFC1 %s, %s", rt, cs);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CFC2(uint64 instruction)
+{
+ uint64 cs_value = extract_cs_20_19_18_17_16(instruction);
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string cs = CPR(copy(cs_value));
+
+ return img::format("CFC2 %s, %s", rt, cs);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CLASS_D(uint64 instruction)
+{
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string ft = FPR(copy(ft_value));
+ std::string fs = FPR(copy(fs_value));
+
+ return img::format("CLASS.D %s, %s", ft, fs);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CLASS_S(uint64 instruction)
+{
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string ft = FPR(copy(ft_value));
+ std::string fs = FPR(copy(fs_value));
+
+ return img::format("CLASS.S %s, %s", ft, fs);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CLO(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string rs = GPR(copy(rs_value));
+
+ return img::format("CLO %s, %s", rt, rs);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CLZ(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string rs = GPR(copy(rs_value));
+
+ return img::format("CLZ %s, %s", rt, rs);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_AF_D(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.AF.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_AF_S(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.AF.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_EQ_D(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.EQ.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_EQ_PH(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("CMP.EQ.PH %s, %s", rs, rt);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_EQ_S(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.EQ.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_LE_D(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.LE.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_LE_PH(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("CMP.LE.PH %s, %s", rs, rt);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_LE_S(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.LE.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_LT_D(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.LT.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_LT_PH(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("CMP.LT.PH %s, %s", rs, rt);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_LT_S(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.LT.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_NE_D(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.NE.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_NE_S(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.NE.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_OR_D(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.OR.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_OR_S(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.OR.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_SAF_D(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.SAF.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_SAF_S(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.SAF.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_SEQ_D(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.SEQ.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_SEQ_S(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.SEQ.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_SLE_D(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.SLE.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_SLE_S(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.SLE.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_SLT_D(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.SLT.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_SLT_S(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.SLT.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_SNE_D(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.SNE.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_SNE_S(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.SNE.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_SOR_D(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.SOR.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_SOR_S(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.SOR.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_SUEQ_D(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.SUEQ.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_SUEQ_S(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.SUEQ.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_SULE_D(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.SULE.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_SULE_S(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.SULE.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_SULT_D(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.SULT.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_SULT_S(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.SULT.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_SUN_D(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.SUN.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_SUNE_D(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.SUNE.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_SUNE_S(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.SUNE.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_SUN_S(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.SUN.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_UEQ_D(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.UEQ.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_UEQ_S(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.UEQ.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_ULE_D(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.ULE.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_ULE_S(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.ULE.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_ULT_D(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.ULT.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_ULT_S(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.ULT.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_UN_D(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.UN.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_UNE_D(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.UNE.D %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_UNE_S(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.UNE.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMP_UN_S(uint64 instruction)
+{
+ uint64 fd_value = extract_fd_10_9_8_7_6(instruction);
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string fd = FPR(copy(fd_value));
+ std::string fs = FPR(copy(fs_value));
+ std::string ft = FPR(copy(ft_value));
+
+ return img::format("CMP.UN.S %s, %s, %s", fd, fs, ft);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMPGDU_EQ_QB(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("CMPGDU.EQ.QB %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMPGDU_LE_QB(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("CMPGDU.LE.QB %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMPGDU_LT_QB(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("CMPGDU.LT.QB %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMPGU_EQ_QB(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("CMPGU.EQ.QB %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMPGU_LE_QB(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("CMPGU.LE.QB %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMPGU_LT_QB(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rd_value = extract_rd_20_19_18_17_16(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rd = GPR(copy(rd_value));
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("CMPGU.LT.QB %s, %s, %s", rd, rs, rt);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMPU_EQ_QB(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("CMPU.EQ.QB %s, %s", rs, rt);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMPU_LE_QB(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("CMPU.LE.QB %s, %s", rs, rt);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CMPU_LT_QB(uint64 instruction)
+{
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+ uint64 rs_value = extract_rs_20_19_18_17_16(instruction);
+
+ std::string rs = GPR(copy(rs_value));
+ std::string rt = GPR(copy(rt_value));
+
+ return img::format("CMPU.LT.QB %s, %s", rs, rt);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::COP2_1(uint64 instruction)
+{
+ uint64 cofun_value = extract_cofun_25_24_23(instruction);
+
+ std::string cofun = IMMEDIATE(copy(cofun_value));
+
+ return img::format("COP2_1 %s", cofun);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CTC1(uint64 instruction)
+{
+ uint64 cs_value = extract_cs_20_19_18_17_16(instruction);
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string cs = CPR(copy(cs_value));
+
+ return img::format("CTC1 %s, %s", rt, cs);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CTC2(uint64 instruction)
+{
+ uint64 cs_value = extract_cs_20_19_18_17_16(instruction);
+ uint64 rt_value = extract_rt_25_24_23_22_21(instruction);
+
+ std::string rt = GPR(copy(rt_value));
+ std::string cs = CPR(copy(cs_value));
+
+ return img::format("CTC2 %s, %s", rt, cs);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CVT_D_L(uint64 instruction)
+{
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string ft = FPR(copy(ft_value));
+ std::string fs = FPR(copy(fs_value));
+
+ return img::format("CVT.D.L %s, %s", ft, fs);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */
+std::string NMD::CVT_D_S(uint64 instruction)
+{
+ uint64 fs_value = extract_fs_15_14_13_12_11(instruction);
+ uint64 ft_value = extract_ft_20_19_18_17_16(instruction);
+
+ std::string ft = FPR(copy(ft_value));
+ std::string fs = FPR(copy(fs_value));
+
+ return img::format("CVT.D.S %s, %s", ft, fs);
+}
+
+
+/*
+ *
+ *
+ * 3 2 1
+ * 10987654321098765432109876543210
+ * 001000 x1110000101
+ * rt -----
+ * rs -----
+ * rd -----
+ */